diff --git a/packages/docusaurus/lib/default-theme/DocBody/index.js b/packages/docusaurus/lib/default-theme/DocBody/index.js
index ccae3f62b9..6835f2beb7 100644
--- a/packages/docusaurus/lib/default-theme/DocBody/index.js
+++ b/packages/docusaurus/lib/default-theme/DocBody/index.js
@@ -14,14 +14,14 @@ import Head from '@docusaurus/Head';
import styles from './styles.module.css';
function DocBody(props) {
- const {metadata, modules} = props;
+ const {metadata, content} = props;
const {language, version} = metadata;
const context = useContext(DocusaurusContext);
useEffect(() => {
context.setContext({metadata});
}, []);
- const DocContents = modules[0];
+ const DocContents = content;
return (
diff --git a/packages/docusaurus/lib/default-theme/Pages/index.js b/packages/docusaurus/lib/default-theme/Pages/index.js
index f7328cd2d7..ba26a08e7a 100644
--- a/packages/docusaurus/lib/default-theme/Pages/index.js
+++ b/packages/docusaurus/lib/default-theme/Pages/index.js
@@ -12,12 +12,12 @@ import Layout from '@theme/Layout'; // eslint-disable-line
import DocusaurusContext from '@docusaurus/context';
-function Pages({modules}) {
+function Pages({content}) {
const context = useContext(DocusaurusContext);
const {metadata = {}, siteConfig = {}} = context;
const {baseUrl, favicon} = siteConfig;
const {language} = metadata;
- const PageContents = modules[0];
+ const PageContents = content;
return (
diff --git a/packages/docusaurus/lib/server/load/index.js b/packages/docusaurus/lib/server/load/index.js
index 254dcb890b..7ffb853c0d 100644
--- a/packages/docusaurus/lib/server/load/index.js
+++ b/packages/docusaurus/lib/server/load/index.js
@@ -58,6 +58,7 @@ module.exports = async function load(siteDir, cliOptions = {}) {
// Routing
const {
+ registry,
routesAsyncModules,
routesConfig,
routesMetadata,
@@ -65,12 +66,19 @@ module.exports = async function load(siteDir, cliOptions = {}) {
routesPaths,
} = await loadRoutes(pluginsRouteConfigs);
- // Mapping of routePath -> metadataPath. Example: '/blog' -> '@generated/metadata/blog-c06.json'
- // Very useful to know which json metadata file is related to certain route
await generate(
generatedFilesDir,
- 'routesMetadataPath.json',
- JSON.stringify(routesMetadataPath, null, 2),
+ 'registry.js',
+ `export default {
+${Object.keys(registry)
+ .map(
+ key => ` '${key}': {
+ 'importStatement': ${registry[key].importStatement},
+ 'module': '${registry[key].modulePath}',
+ 'webpack': require.resolveWeak('${registry[key].modulePath}'),
+ },`,
+ )
+ .join('\n')}};\n`,
);
// Mapping of routePath -> async imported modules. Example: '/blog' -> ['@theme/BlogPage']
diff --git a/packages/docusaurus/lib/server/load/plugins.js b/packages/docusaurus/lib/server/load/plugins.js
index 28a8efe7e2..f74189bb39 100644
--- a/packages/docusaurus/lib/server/load/plugins.js
+++ b/packages/docusaurus/lib/server/load/plugins.js
@@ -63,6 +63,7 @@ module.exports = async function loadPlugins({pluginConfigs = [], context}) {
// 3. Plugin lifecycle - contentLoaded
const pluginsRouteConfigs = [];
+
const actions = {
addRoute: config => pluginsRouteConfigs.push(config),
};
diff --git a/packages/docusaurus/lib/server/load/routes.js b/packages/docusaurus/lib/server/load/routes.js
index 6240893ed0..429862df75 100644
--- a/packages/docusaurus/lib/server/load/routes.js
+++ b/packages/docusaurus/lib/server/load/routes.js
@@ -7,25 +7,27 @@
const {genChunkName, docuHash} = require('@docusaurus/utils');
const {stringify} = require('querystring');
+const _ = require('lodash');
async function loadRoutes(pluginsRouteConfigs) {
const routesImports = [
`import React from 'react';`,
- `import Loadable from 'react-loadable';`,
- `import Loading from '@theme/Loading';`,
`import NotFound from '@theme/NotFound';`,
+ `import ComponentCreator from '@docusaurus/ComponentCreator';`,
];
// Routes paths. Example: ['/', '/docs', '/blog/2017/09/03/test']
const routesPaths = [];
const addRoutesPath = routePath => {
routesPaths.push(routePath);
};
+
// Mapping of routePath -> metadataPath. Example: '/blog' -> '@generated/metadata/blog-c06.json'
const routesMetadataPath = {};
const addRoutesMetadataPath = routePath => {
const fileName = `${docuHash(routePath)}.json`;
routesMetadataPath[routePath] = `@generated/metadata/${fileName}`;
};
+
// Mapping of routePath -> metadata. Example: '/blog' -> { isBlogPage: true, permalink: '/blog' }
const routesMetadata = {};
const addRoutesMetadata = (routePath, metadata) => {
@@ -33,13 +35,21 @@ async function loadRoutes(pluginsRouteConfigs) {
routesMetadata[routePath] = metadata;
}
};
+
+ const registry = {};
+
// Mapping of routePath -> async imported modules. Example: '/blog' -> ['@theme/BlogPage']
const routesAsyncModules = {};
- const addRoutesAsyncModule = (routePath, module) => {
+ const addRoutesAsyncModule = (routePath, key, importChunk) => {
+ // TODO: Port other plugins to use modules and not rely on this.
if (!routesAsyncModules[routePath]) {
- routesAsyncModules[routePath] = [];
+ routesAsyncModules[routePath] = {};
}
- routesAsyncModules[routePath].push(module);
+ routesAsyncModules[routePath][key] = importChunk.chunkName;
+ registry[importChunk.chunkName] = {
+ importStatement: importChunk.importStatement,
+ modulePath: importChunk.modulePath,
+ };
};
// This is the higher level overview of route code generation
@@ -48,7 +58,7 @@ async function loadRoutes(pluginsRouteConfigs) {
path: routePath,
component,
metadata,
- modules = [],
+ modules = {},
routes,
} = routeConfig;
@@ -58,9 +68,9 @@ async function loadRoutes(pluginsRouteConfigs) {
// Given an input (object or string), get the import path str
const getModulePath = target => {
- const isObj = typeof target === 'object';
- const importStr = isObj ? target.path : target;
+ const importStr = _.isObject(target) ? target.path : target;
const queryStr = target.query ? `?${stringify(target.query)}` : '';
+
return `${importStr}${queryStr}`;
};
@@ -68,71 +78,67 @@ async function loadRoutes(pluginsRouteConfigs) {
throw new Error(`path: ${routePath} need a component`);
}
const componentPath = getModulePath(component);
- addRoutesAsyncModule(routePath, componentPath);
- const genImportStr = (modulePath, prefix, name) => {
- const chunkName = genChunkName(name || modulePath, prefix);
+ const genImportChunk = (modulePath, prefix, name) => {
+ const chunkName = genChunkName(modulePath, prefix, name);
const finalStr = JSON.stringify(modulePath);
- return `() => import(/* webpackChunkName: '${chunkName}' */ ${finalStr})`;
+ return {
+ chunkName,
+ modulePath,
+ importStatement: `() => import(/* webpackChunkName: '${chunkName}' */ ${finalStr})`,
+ };
};
+ const componentChunk = genImportChunk(componentPath, 'component');
+ addRoutesAsyncModule(routePath, 'component', componentChunk);
+
if (routes) {
- const componentStr = `Loadable({
- loader: ${genImportStr(componentPath, 'component')},
- loading: Loading
- })`;
return `
{
path: '${routePath}',
- component: ${componentStr},
+ component: ComponentCreator('${routePath}'),
routes: [${routes.map(generateRouteCode).join(',')}],
}`;
}
- const modulesImportStr = modules
- .map((module, i) => {
- const modulePath = getModulePath(module);
- addRoutesAsyncModule(routePath, modulePath);
- return `Mod${i}: ${genImportStr(modulePath, i, routePath)},`;
- })
- .join('\n');
- const modulesLoadedStr = modules
- .map((module, i) => `loaded.Mod${i}.default,`)
- .join('\n');
+ function genRouteAsyncModule(value) {
+ if (Array.isArray(value)) {
+ return value.map(genRouteAsyncModule);
+ }
- let metadataImportStr = '';
- if (metadata) {
- const metadataPath = routesMetadataPath[routePath];
- addRoutesAsyncModule(routePath, metadataPath);
- metadataImportStr = `metadata: ${genImportStr(
- metadataPath,
- 'metadata',
+ if (_.isObject(value) && !value.__import) {
+ const newValue = {};
+ Object.keys(value).forEach(key => {
+ newValue[key] = genRouteAsyncModule(value[key]);
+ });
+ return newValue;
+ }
+
+ const importChunk = genImportChunk(
+ getModulePath(value),
+ 'module',
routePath,
- )},`;
+ );
+ registry[importChunk.chunkName] = {
+ importStatement: importChunk.importStatement,
+ modulePath: importChunk.modulePath,
+ };
+ return importChunk.chunkName;
}
- const componentStr = `Loadable.Map({
- loader: {
- ${modulesImportStr}
- ${metadataImportStr}
- Component: ${genImportStr(componentPath, 'component')},
- },
- loading: Loading,
- render(loaded, props) {
- const Component = loaded.Component.default;
- const metadata = loaded.metadata || {};
- const modules = [${modulesLoadedStr}];
- return (
-
- );
- }
-})\n`;
+ _.assign(routesAsyncModules[routePath], genRouteAsyncModule(modules));
+
+ if (metadata) {
+ const metadataPath = routesMetadataPath[routePath];
+ const metadataChunk = genImportChunk(metadataPath, 'metadata', routePath);
+ addRoutesAsyncModule(routePath, 'metadata', metadataChunk);
+ }
return `
{
path: '${routePath}',
exact: true,
- component: ${componentStr}
+ component: ComponentCreator('${routePath}')
}`;
}
@@ -152,6 +158,7 @@ export default [
];\n`;
return {
+ registry,
routesAsyncModules,
routesConfig,
routesMetadata,