diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts
index bc4180ca7b37..cc70ef21d218 100644
--- a/packages/docusaurus-types/src/config.d.ts
+++ b/packages/docusaurus-types/src/config.d.ts
@@ -39,6 +39,7 @@ export type FasterConfig = {
export type FutureV4Config = {
removeLegacyPostBuildHeadAttribute: boolean;
useCssCascadeLayers: boolean;
+ siteStorageNamespacing: boolean;
};
// VCS (Version Control System) info about a given change, e.g., a git commit.
@@ -96,8 +97,6 @@ export type FutureConfig = {
experimental_faster: FasterConfig;
- experimental_storage: StorageConfig;
-
experimental_vcs: VcsConfig;
/**
@@ -180,6 +179,13 @@ export type DocusaurusConfig = {
* Similar to Remix future flags, see https://remix.run/blog/future-flags
*/
future: FutureConfig;
+ /**
+ * Site-wide browser storage options that theme authors should strive to
+ * respect.
+ *
+ * @see https://docusaurus.io/docs/api/docusaurus-config#storage
+ */
+ storage: StorageConfig;
/**
* This option adds `` to
* every page to tell search engines to avoid indexing your site.
diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
index 091d94e9ac18..704bb6aee625 100644
--- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
+++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap
@@ -20,10 +20,6 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -31,6 +27,7 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -73,6 +70,10 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -105,10 +106,6 @@ exports[`loadSiteConfig website with ts + js config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -116,6 +113,7 @@ exports[`loadSiteConfig website with ts + js config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -158,6 +156,10 @@ exports[`loadSiteConfig website with ts + js config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -190,10 +192,6 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -201,6 +199,7 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -243,6 +242,10 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -275,10 +278,6 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -286,6 +285,7 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -328,6 +328,10 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -360,10 +364,6 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -371,6 +371,7 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -413,6 +414,10 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -445,10 +450,6 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -456,6 +457,7 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -498,6 +500,10 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -530,10 +536,6 @@ exports[`loadSiteConfig website with valid async config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -541,6 +543,7 @@ exports[`loadSiteConfig website with valid async config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -585,6 +588,10 @@ exports[`loadSiteConfig website with valid async config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "Hello World",
"themeConfig": {},
@@ -617,10 +624,6 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -628,6 +631,7 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -672,6 +676,10 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "Hello World",
"themeConfig": {},
@@ -704,10 +712,6 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -715,6 +719,7 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -759,6 +764,10 @@ exports[`loadSiteConfig website with valid config creator function 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "Hello World",
"themeConfig": {},
@@ -794,10 +803,6 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -805,6 +810,7 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -857,6 +863,10 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "Hello World",
"themeConfig": {},
diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap
index 6990d4d4a006..08fc5ae5ca38 100644
--- a/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap
+++ b/packages/docusaurus/src/server/__tests__/__snapshots__/site.test.ts.snap
@@ -100,10 +100,6 @@ exports[`loadSite custom-i18n-site loads site 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -111,6 +107,7 @@ exports[`loadSite custom-i18n-site loads site 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -161,6 +158,10 @@ exports[`loadSite custom-i18n-site loads site 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -273,10 +274,6 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom config 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -284,6 +281,7 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom config 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -326,6 +324,10 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom config 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -438,10 +440,6 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom outDir 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -449,6 +447,7 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom outDir 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -491,6 +490,10 @@ exports[`loadSite simple-site-with-baseUrl loads site - custom outDir 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -603,10 +606,6 @@ exports[`loadSite simple-site-with-baseUrl loads site 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -614,6 +613,7 @@ exports[`loadSite simple-site-with-baseUrl loads site 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -656,6 +656,10 @@ exports[`loadSite simple-site-with-baseUrl loads site 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -812,10 +816,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr + custom
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -823,6 +823,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr + custom
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -887,6 +888,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr + custom
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -1043,10 +1048,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - custom outDir 1`] =
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -1054,6 +1055,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - custom outDir 1`] =
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -1118,6 +1120,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - custom outDir 1`] =
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -1274,10 +1280,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale de 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -1285,6 +1287,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale de 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -1349,6 +1352,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale de 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -1505,10 +1512,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale en 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -1516,6 +1519,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale en 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -1580,6 +1584,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale en 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -1736,10 +1744,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale es 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -1747,6 +1751,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale es 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -1811,6 +1816,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale es 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -1967,10 +1976,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -1978,6 +1983,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -2042,6 +2048,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale fr 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -2198,10 +2208,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale it 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -2209,6 +2215,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale it 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -2273,6 +2280,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site - locale it 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
@@ -2429,10 +2440,6 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site 1`] = `
"swcJsMinimizer": false,
},
"experimental_router": "browser",
- "experimental_storage": {
- "namespace": false,
- "type": "localStorage",
- },
"experimental_vcs": {
"getFileCreationInfo": [Function],
"getFileLastUpdateInfo": [Function],
@@ -2440,6 +2447,7 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site 1`] = `
},
"v4": {
"removeLegacyPostBuildHeadAttribute": false,
+ "siteStorageNamespacing": false,
"useCssCascadeLayers": false,
},
},
@@ -2504,6 +2512,10 @@ exports[`loadSite simple-site-with-baseUrl-i18n loads site 1`] = `
"staticDirectories": [
"static",
],
+ "storage": {
+ "namespace": false,
+ "type": "localStorage",
+ },
"stylesheets": [],
"tagline": "",
"themeConfig": {},
diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts
index 379ce8af2898..42475f8bc26a 100644
--- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts
+++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts
@@ -61,6 +61,7 @@ describe('normalizeConfig', () => {
v4: {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
+ siteStorageNamespacing: true,
},
experimental_faster: {
swcJsLoader: true,
@@ -73,10 +74,6 @@ describe('normalizeConfig', () => {
ssgWorkerThreads: true,
gitEagerVcs: true,
},
- experimental_storage: {
- type: 'sessionStorage',
- namespace: true,
- },
experimental_vcs: {
initialize: (_params) => {},
getFileCreationInfo: (_filePath) => null,
@@ -84,6 +81,10 @@ describe('normalizeConfig', () => {
},
experimental_router: 'hash',
},
+ storage: {
+ type: 'sessionStorage',
+ namespace: true,
+ },
tagline: 'my awesome site',
organizationName: 'facebook',
projectName: 'docusaurus',
@@ -1060,6 +1061,303 @@ describe('presets', () => {
});
});
+describe('storage', () => {
+ function storageContaining(storage: Partial) {
+ return expect.objectContaining({
+ storage: expect.objectContaining(storage),
+ });
+ }
+
+ it('accepts storage - undefined', () => {
+ expect(
+ normalizeConfig({
+ storage: undefined,
+ }),
+ ).toEqual(storageContaining(DEFAULT_STORAGE_CONFIG));
+ });
+
+ it('accepts storage - empty', () => {
+ expect(
+ normalizeConfig({
+ storage: {},
+ }),
+ ).toEqual(storageContaining(DEFAULT_STORAGE_CONFIG));
+ });
+
+ it('accepts storage - full', () => {
+ const storage: StorageConfig = {
+ type: 'sessionStorage',
+ namespace: 'myNamespace',
+ };
+ expect(
+ normalizeConfig({
+ storage,
+ }),
+ ).toEqual(storageContaining(storage));
+ });
+
+ it('rejects storage - boolean', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = true;
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage" must be of type object
+ "
+ `);
+ });
+
+ it('rejects storage - number', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = 42;
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage" must be of type object
+ "
+ `);
+ });
+
+ it('rejects legacy future.experimental_storage', () => {
+ expect(() =>
+ normalizeConfig({
+ future: {
+ // @ts-expect-error: legacy config removed
+ experimental_storage: {namespace: true},
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ "Docusaurus config \`future.experimental_storage\` has been promoted to stable and is no longer supported.
+ Please use the top-level \`storage\` option instead.
+ See https://docusaurus.io/docs/api/docusaurus-config#storage
+ "
+ `);
+ });
+
+ describe('type', () => {
+ it('accepts type', () => {
+ const storage: Partial = {
+ type: 'sessionStorage',
+ };
+ expect(
+ normalizeConfig({
+ storage,
+ }),
+ ).toEqual(
+ storageContaining({
+ ...DEFAULT_STORAGE_CONFIG,
+ ...storage,
+ }),
+ );
+ });
+
+ it('accepts type - undefined', () => {
+ const storage: Partial = {
+ type: undefined,
+ };
+ expect(
+ normalizeConfig({
+ storage,
+ }),
+ ).toEqual(storageContaining({type: 'localStorage'}));
+ });
+
+ it('rejects type - null', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = {type: 42};
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage.type" must be one of [localStorage, sessionStorage]
+ "storage.type" must be a string
+ "
+ `);
+ });
+
+ it('rejects type - number', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = {type: 42};
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage.type" must be one of [localStorage, sessionStorage]
+ "storage.type" must be a string
+ "
+ `);
+ });
+
+ it('rejects type - invalid enum value', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = {type: 'badType'};
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage.type" must be one of [localStorage, sessionStorage]
+ "
+ `);
+ });
+ });
+
+ describe('namespace', () => {
+ it('defaults to true when future.v4.siteStorageNamespacing is enabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: true,
+ },
+ },
+ storage: {
+ type: 'localStorage',
+ },
+ }),
+ ).toEqual(storageContaining({namespace: true}));
+ });
+
+ it('defaults to false when future.v4.siteStorageNamespacing is disabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: false,
+ },
+ },
+ storage: {
+ type: 'localStorage',
+ },
+ }),
+ ).toEqual(storageContaining({namespace: false}));
+ });
+
+ it('defaults to false when namespace is not provided', () => {
+ expect(
+ normalizeConfig({
+ storage: {
+ type: 'localStorage',
+ },
+ }),
+ ).toEqual(storageContaining({namespace: false}));
+ });
+
+ it('respects explicit namespace when future.v4.siteStorageNamespacing is enabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: true,
+ },
+ },
+ storage: {
+ namespace: false,
+ },
+ }),
+ ).toEqual(storageContaining({namespace: false}));
+ });
+
+ it('respects explicit namespace when future.v4.siteStorageNamespacing is disabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: false,
+ },
+ },
+ storage: {
+ namespace: false,
+ },
+ }),
+ ).toEqual(storageContaining({namespace: false}));
+ });
+
+ it('respects explicit string namespace when future.v4.siteStorageNamespacing is enabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: true,
+ },
+ },
+ storage: {
+ namespace: 'myNamespace',
+ },
+ }),
+ ).toEqual(storageContaining({namespace: 'myNamespace'}));
+ });
+
+ it('respects explicit string namespace when future.v4.siteStorageNamespacing is disabled', () => {
+ expect(
+ normalizeConfig({
+ future: {
+ v4: {
+ siteStorageNamespacing: false,
+ },
+ },
+ storage: {
+ namespace: 'myNamespace',
+ },
+ }),
+ ).toEqual(storageContaining({namespace: 'myNamespace'}));
+ });
+
+ it('accepts namespace - boolean', () => {
+ const storage: Partial = {
+ namespace: true,
+ };
+ expect(
+ normalizeConfig({
+ storage,
+ }),
+ ).toEqual(storageContaining(storage));
+ });
+
+ it('accepts namespace - string', () => {
+ const storage: Partial = {
+ namespace: 'myNamespace',
+ };
+ expect(
+ normalizeConfig({
+ storage,
+ }),
+ ).toEqual(storageContaining(storage));
+ });
+
+ it('rejects namespace - null', () => {
+ const storage: Partial = {namespace: null};
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage.namespace" must be one of [string, boolean]
+ "
+ `);
+ });
+
+ it('rejects namespace - number', () => {
+ // @ts-expect-error: invalid
+ const storage: Partial = {namespace: 42};
+ expect(() =>
+ normalizeConfig({
+ storage,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""storage.namespace" must be one of [string, boolean]
+ "
+ `);
+ });
+ });
+});
+
describe('future', () => {
function futureContaining(future: Partial) {
return expect.objectContaining({
@@ -1088,6 +1386,7 @@ describe('future', () => {
v4: {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
+ siteStorageNamespacing: true,
},
experimental_faster: {
swcJsLoader: true,
@@ -1105,10 +1404,6 @@ describe('future', () => {
getFileCreationInfo: (_filePath) => null,
getFileLastUpdateInfo: (_filePath) => null,
},
- experimental_storage: {
- type: 'sessionStorage',
- namespace: 'myNamespace',
- },
experimental_router: 'hash',
};
expect(
@@ -1215,213 +1510,6 @@ describe('future', () => {
});
});
- describe('storage', () => {
- function storageContaining(storage: Partial) {
- return futureContaining({
- experimental_storage: expect.objectContaining(storage),
- });
- }
-
- it('accepts storage - undefined', () => {
- expect(
- normalizeConfig({
- future: {
- experimental_storage: undefined,
- },
- }),
- ).toEqual(futureContaining(DEFAULT_FUTURE_CONFIG));
- });
-
- it('accepts storage - empty', () => {
- expect(
- normalizeConfig({
- future: {experimental_storage: {}},
- }),
- ).toEqual(futureContaining(DEFAULT_FUTURE_CONFIG));
- });
-
- it('accepts storage - full', () => {
- const storage: StorageConfig = {
- type: 'sessionStorage',
- namespace: 'myNamespace',
- };
- expect(
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toEqual(storageContaining(storage));
- });
-
- it('rejects storage - boolean', () => {
- // @ts-expect-error: invalid
- const storage: Partial = true;
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage" must be of type object
- "
- `);
- });
-
- it('rejects storage - number', () => {
- // @ts-expect-error: invalid
- const storage: Partial = 42;
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage" must be of type object
- "
- `);
- });
-
- describe('type', () => {
- it('accepts type', () => {
- const storage: Partial = {
- type: 'sessionStorage',
- };
- expect(
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toEqual(
- storageContaining({
- ...DEFAULT_STORAGE_CONFIG,
- ...storage,
- }),
- );
- });
-
- it('accepts type - undefined', () => {
- const storage: Partial = {
- type: undefined,
- };
- expect(
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toEqual(storageContaining({type: 'localStorage'}));
- });
-
- it('rejects type - null', () => {
- // @ts-expect-error: invalid
- const storage: Partial = {type: 42};
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage.type" must be one of [localStorage, sessionStorage]
- "future.experimental_storage.type" must be a string
- "
- `);
- });
-
- it('rejects type - number', () => {
- // @ts-expect-error: invalid
- const storage: Partial = {type: 42};
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage.type" must be one of [localStorage, sessionStorage]
- "future.experimental_storage.type" must be a string
- "
- `);
- });
-
- it('rejects type - invalid enum value', () => {
- // @ts-expect-error: invalid
- const storage: Partial = {type: 'badType'};
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage.type" must be one of [localStorage, sessionStorage]
- "
- `);
- });
- });
-
- describe('namespace', () => {
- it('accepts namespace - boolean', () => {
- const storage: Partial = {
- namespace: true,
- };
- expect(
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toEqual(storageContaining(storage));
- });
-
- it('accepts namespace - string', () => {
- const storage: Partial = {
- namespace: 'myNamespace',
- };
- expect(
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toEqual(storageContaining(storage));
- });
-
- it('rejects namespace - null', () => {
- const storage: Partial = {namespace: null};
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage.namespace" must be one of [string, boolean]
- "
- `);
- });
-
- it('rejects namespace - number', () => {
- // @ts-expect-error: invalid
- const storage: Partial = {namespace: 42};
- expect(() =>
- normalizeConfig({
- future: {
- experimental_storage: storage,
- },
- }),
- ).toThrowErrorMatchingInlineSnapshot(`
- ""future.experimental_storage.namespace" must be one of [string, boolean]
- "
- `);
- });
- });
- });
-
describe('vcs', () => {
function vcsContaining(vcs: Partial) {
return futureContaining({
@@ -2472,6 +2560,7 @@ describe('future', () => {
const v4: FutureV4Config = {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
+ siteStorageNamespacing: true,
};
expect(
normalizeConfig({
@@ -2662,5 +2751,80 @@ describe('future', () => {
`);
});
});
+
+ describe('siteStorageNamespacing', () => {
+ it('accepts - undefined', () => {
+ const v4: Partial = {
+ siteStorageNamespacing: undefined,
+ };
+ expect(
+ normalizeConfig({
+ future: {
+ v4,
+ },
+ }),
+ ).toEqual(v4Containing({siteStorageNamespacing: false}));
+ });
+
+ it('accepts - true', () => {
+ const v4: Partial = {
+ siteStorageNamespacing: true,
+ };
+ expect(
+ normalizeConfig({
+ future: {
+ v4,
+ },
+ }),
+ ).toEqual(v4Containing({siteStorageNamespacing: true}));
+ });
+
+ it('accepts - false', () => {
+ const v4: Partial = {
+ siteStorageNamespacing: false,
+ };
+ expect(
+ normalizeConfig({
+ future: {
+ v4,
+ },
+ }),
+ ).toEqual(v4Containing({siteStorageNamespacing: false}));
+ });
+
+ it('rejects - null', () => {
+ const v4: Partial = {
+ // @ts-expect-error: invalid
+ siteStorageNamespacing: null,
+ };
+ expect(() =>
+ normalizeConfig({
+ future: {
+ v4,
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""future.v4.siteStorageNamespacing" must be a boolean
+ "
+ `);
+ });
+
+ it('rejects - number', () => {
+ const v4: Partial = {
+ // @ts-expect-error: invalid
+ siteStorageNamespacing: 42,
+ };
+ expect(() =>
+ normalizeConfig({
+ future: {
+ v4,
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ ""future.v4.siteStorageNamespacing" must be a boolean
+ "
+ `);
+ });
+ });
});
});
diff --git a/packages/docusaurus/src/server/__tests__/storage.test.ts b/packages/docusaurus/src/server/__tests__/storage.test.ts
index f91b9ddbef3e..57999a6dc454 100644
--- a/packages/docusaurus/src/server/__tests__/storage.test.ts
+++ b/packages/docusaurus/src/server/__tests__/storage.test.ts
@@ -6,11 +6,8 @@
*/
import {createSiteStorage} from '../storage';
-import {
- DEFAULT_FUTURE_CONFIG,
- DEFAULT_STORAGE_CONFIG,
-} from '../configValidation';
-import type {FutureConfig, StorageConfig, SiteStorage} from '@docusaurus/types';
+import {DEFAULT_STORAGE_CONFIG} from '../configValidation';
+import type {StorageConfig, SiteStorage} from '@docusaurus/types';
function test({
url = 'https://docusaurus.io',
@@ -21,15 +18,14 @@ function test({
baseUrl?: string;
storage?: Partial;
}): SiteStorage {
- const future: FutureConfig = {
- ...DEFAULT_FUTURE_CONFIG,
- experimental_storage: {
+ return createSiteStorage({
+ url,
+ baseUrl,
+ storage: {
...DEFAULT_STORAGE_CONFIG,
...storage,
},
- };
-
- return createSiteStorage({url, baseUrl, future});
+ });
}
const DefaultSiteStorage: SiteStorage = {
diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts
index e57a7ba45abe..6ccde0034917 100644
--- a/packages/docusaurus/src/server/configValidation.ts
+++ b/packages/docusaurus/src/server/configValidation.ts
@@ -100,18 +100,19 @@ export const DEFAULT_FASTER_CONFIG_TRUE: FasterConfig = {
export const DEFAULT_FUTURE_V4_CONFIG: FutureV4Config = {
removeLegacyPostBuildHeadAttribute: false,
useCssCascadeLayers: false,
+ siteStorageNamespacing: false,
};
// When using the "v4: true" shortcut
export const DEFAULT_FUTURE_V4_CONFIG_TRUE: FutureV4Config = {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
+ siteStorageNamespacing: true,
};
export const DEFAULT_FUTURE_CONFIG: FutureConfig = {
v4: DEFAULT_FUTURE_V4_CONFIG,
experimental_faster: DEFAULT_FASTER_CONFIG,
- experimental_storage: DEFAULT_STORAGE_CONFIG,
experimental_vcs: getVcsPreset('default-v1'),
experimental_router: 'browser',
};
@@ -143,6 +144,7 @@ export const DEFAULT_CONFIG: Pick<
DocusaurusConfig,
| 'i18n'
| 'future'
+ | 'storage'
| 'onBrokenLinks'
| 'onBrokenAnchors'
| 'onBrokenMarkdownLinks'
@@ -165,6 +167,7 @@ export const DEFAULT_CONFIG: Pick<
> = {
i18n: DEFAULT_I18N_CONFIG,
future: DEFAULT_FUTURE_CONFIG,
+ storage: DEFAULT_STORAGE_CONFIG,
onBrokenLinks: 'throw',
onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw
onBrokenMarkdownLinks: undefined,
@@ -318,6 +321,9 @@ const FUTURE_V4_SCHEMA = Joi.alternatives()
useCssCascadeLayers: Joi.boolean().default(
DEFAULT_FUTURE_V4_CONFIG.useCssCascadeLayers,
),
+ siteStorageNamespacing: Joi.boolean().default(
+ DEFAULT_FUTURE_V4_CONFIG.siteStorageNamespacing,
+ ),
}),
Joi.boolean()
.required()
@@ -332,12 +338,11 @@ const STORAGE_CONFIG_SCHEMA = Joi.object({
type: Joi.string()
.equal('localStorage', 'sessionStorage')
.default(DEFAULT_STORAGE_CONFIG.type),
- namespace: Joi.alternatives()
- .try(Joi.string(), Joi.boolean())
- .default(DEFAULT_STORAGE_CONFIG.namespace),
+ // No schema default on purpose: we derive this from future.v4 flag later.
+ namespace: Joi.alternatives().try(Joi.string(), Joi.boolean()),
})
.optional()
- .default(DEFAULT_STORAGE_CONFIG);
+ .default({type: DEFAULT_STORAGE_CONFIG.type});
const VCS_CONFIG_OBJECT_SCHEMA = Joi.object({
// All the fields are required on purpose
@@ -369,10 +374,20 @@ const VCS_CONFIG_SCHEMA = Joi.custom((input) => {
return value;
}).default(true);
-const FUTURE_CONFIG_SCHEMA = Joi.object({
+const FUTURE_CONFIG_SCHEMA = Joi.object<
+ FutureConfig & {experimental_storage?: never}
+>({
v4: FUTURE_V4_SCHEMA,
experimental_faster: FASTER_CONFIG_SCHEMA,
- experimental_storage: STORAGE_CONFIG_SCHEMA,
+ experimental_storage: Joi.any()
+ .forbidden()
+ .messages({
+ 'any.unknown': `Docusaurus config ${logger.code(
+ 'future.experimental_storage',
+ )} has been promoted to stable and is no longer supported.
+Please use the top-level ${logger.code('storage')} option instead.
+See https://docusaurus.io/docs/api/docusaurus-config#storage`,
+ }),
experimental_vcs: VCS_CONFIG_SCHEMA,
experimental_router: Joi.string()
.equal('browser', 'hash')
@@ -391,6 +406,7 @@ export const ConfigSchema = Joi.object({
trailingSlash: Joi.boolean(), // No default value! undefined = retrocompatible legacy behavior!
i18n: I18N_CONFIG_SCHEMA,
future: FUTURE_CONFIG_SCHEMA,
+ storage: STORAGE_CONFIG_SCHEMA,
onBrokenLinks: Joi.string()
.equal('ignore', 'log', 'warn', 'throw')
.default(DEFAULT_CONFIG.onBrokenLinks),
@@ -533,6 +549,10 @@ export const ConfigSchema = Joi.object({
// Expressing this kind of logic in Joi is a pain
// We also want to decouple logic from Joi: easier to remove it later!
function postProcessDocusaurusConfig(config: DocusaurusConfig) {
+ if (config.storage.namespace === undefined) {
+ config.storage.namespace = config.future.v4.siteStorageNamespacing;
+ }
+
if (config.onBrokenMarkdownLinks) {
logger.warn`The code=${'siteConfig.onBrokenMarkdownLinks'} config option is deprecated and will be removed in Docusaurus v4.
Please migrate and move this option to code=${'siteConfig.markdown.hooks.onBrokenMarkdownLinks'} instead.`;
diff --git a/packages/docusaurus/src/server/storage.ts b/packages/docusaurus/src/server/storage.ts
index 657f4a359c2d..932db7df2695 100644
--- a/packages/docusaurus/src/server/storage.ts
+++ b/packages/docusaurus/src/server/storage.ts
@@ -9,11 +9,7 @@ import {normalizeUrl, simpleHash} from '@docusaurus/utils';
import {addTrailingSlash} from '@docusaurus/utils-common';
import type {DocusaurusConfig, SiteStorage} from '@docusaurus/types';
-type PartialFuture = Pick;
-
-type PartialConfig = Pick & {
- future: PartialFuture;
-};
+type PartialConfig = Pick;
function automaticNamespace(config: PartialConfig): string {
const normalizedUrl = addTrailingSlash(
@@ -23,17 +19,17 @@ function automaticNamespace(config: PartialConfig): string {
}
function getNamespaceString(config: PartialConfig): string | null {
- if (config.future.experimental_storage.namespace === true) {
+ if (config.storage.namespace === true) {
return automaticNamespace(config);
- } else if (config.future.experimental_storage.namespace === false) {
+ } else if (config.storage.namespace === false) {
return null;
} else {
- return config.future.experimental_storage.namespace;
+ return config.storage.namespace;
}
}
export function createSiteStorage(config: PartialConfig): SiteStorage {
- const {type} = config.future.experimental_storage;
+ const {type} = config.storage;
const namespaceString = getNamespaceString(config);
const namespace = namespaceString ? `-${namespaceString}` : '';
diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx
index 5acad437ccc7..deec583c530b 100644
--- a/website/docs/api/docusaurus.config.js.mdx
+++ b/website/docs/api/docusaurus.config.js.mdx
@@ -234,6 +234,7 @@ export default {
v4: {
removeLegacyPostBuildHeadAttribute: true,
useCssCascadeLayers: true,
+ siteStorageNamespacing: true,
},
experimental_faster: {
swcJsLoader: true,
@@ -245,10 +246,6 @@ export default {
ssgWorkerThreads: true,
mdxCrossCompilerCache: true,
},
- experimental_storage: {
- type: 'localStorage',
- namespace: true,
- },
experimental_router: 'hash',
},
};
@@ -257,6 +254,7 @@ export default {
- `v4`: Permits to opt-in for upcoming Docusaurus v4 breaking changes and features, to prepare your site in advance for this new version. Use `true` as a shorthand to enable all the flags.
- [`removeLegacyPostBuildHeadAttribute`](https://github.com/facebook/docusaurus/pull/10435): Removes the legacy `plugin.postBuild({head})` API that prevents us from applying useful SSG optimizations ([explanations](https://github.com/facebook/docusaurus/pull/10850)).
- [`useCssCascadeLayers`](https://github.com/facebook/docusaurus/pull/11142): This enables the [Docusaurus CSS Cascade Layers plugin](./plugins/plugin-css-cascade-layers.mdx) with pre-configured layers that we plan to apply by default for Docusaurus v4.
+ - `siteStorageNamespacing`: Changes the default value of [`storage.namespace`](#storage) to `true`. This helps you prepare for the upcoming Docusaurus v4 default behavior.
- `experimental_faster`: An object containing feature flags to make the Docusaurus build faster. This requires adding the `@docusaurus/faster` package to your site's dependencies. Use `true` as a shorthand to enable all flags. Read more on the [Docusaurus Faster](https://github.com/facebook/docusaurus/issues/10556) issue. Available feature flags:
- [`swcJsLoader`](https://github.com/facebook/docusaurus/pull/10435): Use [SWC](https://swc.rs/) to transpile JS (instead of [Babel](https://babeljs.io/)).
- [`swcJsMinimizer`](https://github.com/facebook/docusaurus/pull/10441): Use [SWC](https://swc.rs/) to minify JS (instead of [Terser](https://github.com/terser/terser)).
@@ -267,9 +265,6 @@ export default {
- [`mdxCrossCompilerCache`](https://github.com/facebook/docusaurus/pull/10479): Compile MDX files only once for both browser/Node.js environments instead of twice.
- [`ssgWorkerThreads`](https://github.com/facebook/docusaurus/pull/10826): Using a Node.js worker thread pool to execute the static site generation phase faster. Requires `future.v4.removeLegacyPostBuildHeadAttribute` to be turned on.
- [`gitEagerVcs`](https://github.com/facebook/docusaurus/pull/11512): Upgrades the default [VCS strategy](#vcs) to `default-v2`, that reads your whole Git repository at once instead of per-file, making Git operations faster on large repositories.
-- `experimental_storage`: Site-wide browser storage options that theme authors should strive to respect.
- - `type`: The browser storage theme authors should use. Possible values are `localStorage` and `sessionStorage`. Defaults to `localStorage`.
- - `namespace`: Whether to namespace the browser storage keys to avoid storage key conflicts when Docusaurus sites are hosted under the same domain, or on localhost. Possible values are `string | boolean`. The namespace is appended at the end of the storage keys `key-namespace`. Use `true` to automatically generate a random namespace from your site `url + baseUrl`. Defaults to `false` (no namespace, historical behavior).
- `experimental_router`: The router type to use. Possible values are `browser` and `hash`. Defaults to `browser`. The `hash` router is only useful for rare cases where you want to opt-out of static site generation, have a fully client-side app with a single `index.html` entrypoint file. This can be useful to distribute a Docusaurus site as a `.zip` archive that you can [browse locally without running a web server](https://github.com/facebook/docusaurus/issues/3825).
- [`experimental_vcs`](#vcs): The Version Control System (VCS) implementation to use to read file info (creation/last update date/author). Read the [dedicated section](#vcs) below for details.
@@ -361,6 +356,26 @@ type VcsPreset =
| 'default-v2';
```
+### `storage` {/* #storage */}
+
+- Type: `Object`
+
+Site-wide browser storage options that theme authors should strive to respect.
+
+- `type`: The browser storage theme authors should use. Possible values are `localStorage` and `sessionStorage`. Defaults to `localStorage`.
+- `namespace`: Whether to namespace the browser storage keys to avoid storage key conflicts when Docusaurus sites are hosted under the same domain, or on localhost. Possible values are `string | boolean`. The namespace is appended at the end of the storage keys `key-namespace`. Use `true` to automatically generate a random namespace from your site `url + baseUrl`. Defaults to `false` (historical behavior), unless `future.v4.siteStorageNamespacing` is turned on.
+
+Example:
+
+```js title="docusaurus.config.js"
+export default {
+ storage: {
+ type: 'localStorage',
+ namespace: true,
+ },
+};
+```
+
### `noIndex` {/* #noIndex */}
- Type: `boolean`
diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts
index f242e5aba33d..f49ef0c0247b 100644
--- a/website/docusaurus.config.ts
+++ b/website/docusaurus.config.ts
@@ -193,9 +193,6 @@ export default async function createConfigAsync() {
ssgWorkerThreads: true,
gitEagerVcs: true,
},
- experimental_storage: {
- namespace: true,
- },
experimental_vcs: vcs,
experimental_router: router,
},