@docusaurus/core 0.0.0-5823 → 0.0.0-5828
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/docusaurus.mjs +6 -5
- package/lib/client/{serverRenderer.d.ts → renderToHtml.d.ts} +1 -1
- package/lib/client/{serverRenderer.js → renderToHtml.js} +1 -1
- package/lib/client/serverEntry.d.ts +3 -4
- package/lib/client/serverEntry.js +12 -113
- package/lib/commands/build.d.ts +1 -1
- package/lib/commands/build.js +155 -99
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/serve.js +4 -4
- package/lib/commands/start.js +120 -90
- package/lib/ssg.d.ts +31 -0
- package/lib/ssg.js +172 -0
- package/lib/templates/templates.d.ts +28 -0
- package/lib/templates/templates.js +63 -0
- package/lib/utils.d.ts +8 -0
- package/lib/utils.js +31 -0
- package/lib/webpack/base.d.ts +5 -1
- package/lib/webpack/base.js +4 -6
- package/lib/webpack/client.d.ts +15 -1
- package/lib/webpack/client.js +78 -23
- package/lib/webpack/minification.d.ts +8 -0
- package/lib/webpack/minification.js +97 -0
- package/lib/webpack/server.d.ts +5 -3
- package/lib/webpack/server.js +41 -50
- package/lib/webpack/utils.d.ts +13 -4
- package/lib/webpack/utils.js +27 -83
- package/package.json +12 -11
- /package/lib/{webpack/templates/index.html.template.ejs → templates/dev.html.template.ejs} +0 -0
- /package/lib/{webpack/templates → templates}/ssr.html.template.d.ts +0 -0
- /package/lib/{webpack/templates → templates}/ssr.html.template.js +0 -0
package/bin/docusaurus.mjs
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
// @ts-check
|
|
10
10
|
|
|
11
|
+
import {inspect} from 'node:util';
|
|
11
12
|
import logger from '@docusaurus/logger';
|
|
12
13
|
import cli from 'commander';
|
|
13
14
|
import {DOCUSAURUS_VERSION} from '@docusaurus/utils';
|
|
@@ -61,8 +62,6 @@ cli
|
|
|
61
62
|
'--no-minify',
|
|
62
63
|
'build website without minimizing JS bundles (default: false)',
|
|
63
64
|
)
|
|
64
|
-
// @ts-expect-error: Promise<string> is not assignable to Promise<void>... but
|
|
65
|
-
// good enough here.
|
|
66
65
|
.action(build);
|
|
67
66
|
|
|
68
67
|
cli
|
|
@@ -269,9 +268,11 @@ cli.parse(process.argv);
|
|
|
269
268
|
|
|
270
269
|
process.on('unhandledRejection', (err) => {
|
|
271
270
|
console.log('');
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
|
|
272
|
+
// We need to use inspect with increased depth to log the full causal chain
|
|
273
|
+
// By default Node logging has depth=2
|
|
274
|
+
// see also https://github.com/nodejs/node/issues/51637
|
|
275
|
+
logger.error(inspect(err, {depth: Infinity}));
|
|
275
276
|
|
|
276
277
|
logger.info`Docusaurus version: number=${DOCUSAURUS_VERSION}
|
|
277
278
|
Node version: number=${process.version}`;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { renderToPipeableStream } from 'react-dom/server';
|
|
8
8
|
import { Writable } from 'stream';
|
|
9
|
-
export async function
|
|
9
|
+
export async function renderToHtml(app) {
|
|
10
10
|
// Inspired from
|
|
11
11
|
// https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation
|
|
12
12
|
// https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/static-entry.js
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}): Promise<string>;
|
|
7
|
+
import type { AppRenderer } from '../common';
|
|
8
|
+
declare const render: AppRenderer;
|
|
9
|
+
export default render;
|
|
@@ -5,59 +5,15 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import fs from 'fs-extra';
|
|
10
|
-
// eslint-disable-next-line no-restricted-imports
|
|
11
|
-
import _ from 'lodash';
|
|
12
|
-
import * as eta from 'eta';
|
|
13
8
|
import { StaticRouter } from 'react-router-dom';
|
|
14
9
|
import { HelmetProvider } from 'react-helmet-async';
|
|
15
|
-
import { getBundles } from 'react-loadable-ssr-addon-v5-slorber';
|
|
16
10
|
import Loadable from 'react-loadable';
|
|
17
|
-
import {
|
|
18
|
-
import { renderStaticApp } from './serverRenderer';
|
|
11
|
+
import { renderToHtml } from './renderToHtml';
|
|
19
12
|
import preload from './preload';
|
|
20
13
|
import App from './App';
|
|
21
14
|
import { createStatefulBrokenLinks, BrokenLinksProvider, } from './BrokenLinksContext';
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
}));
|
|
25
|
-
function renderSSRTemplate(ssrTemplate, data) {
|
|
26
|
-
const compiled = getCompiledSSRTemplate(ssrTemplate);
|
|
27
|
-
return compiled(data, eta.defaultConfig);
|
|
28
|
-
}
|
|
29
|
-
function buildSSRErrorMessage({ error, pathname, }) {
|
|
30
|
-
const parts = [
|
|
31
|
-
`Docusaurus server-side rendering could not render static page with path ${pathname} because of error: ${error.message}`,
|
|
32
|
-
];
|
|
33
|
-
const isNotDefinedErrorRegex = /(?:window|document|localStorage|navigator|alert|location|buffer|self) is not defined/i;
|
|
34
|
-
if (isNotDefinedErrorRegex.test(error.message)) {
|
|
35
|
-
// prettier-ignore
|
|
36
|
-
parts.push(`It looks like you are using code that should run on the client-side only.
|
|
37
|
-
To get around it, try using \`<BrowserOnly>\` (https://docusaurus.io/docs/docusaurus-core/#browseronly) or \`ExecutionEnvironment\` (https://docusaurus.io/docs/docusaurus-core/#executionenvironment).
|
|
38
|
-
It might also require to wrap your client code in \`useEffect\` hook and/or import a third-party library dynamically (if any).`);
|
|
39
|
-
}
|
|
40
|
-
return parts.join('\n');
|
|
41
|
-
}
|
|
42
|
-
export default async function render(locals) {
|
|
43
|
-
try {
|
|
44
|
-
return await doRender(locals);
|
|
45
|
-
}
|
|
46
|
-
catch (errorUnknown) {
|
|
47
|
-
const error = errorUnknown;
|
|
48
|
-
const message = buildSSRErrorMessage({ error, pathname: locals.path });
|
|
49
|
-
const ssrError = new Error(message, { cause: error });
|
|
50
|
-
// It is important to log the error here because the stacktrace causal chain
|
|
51
|
-
// is not available anymore upper in the tree (this SSR runs in eval)
|
|
52
|
-
console.error(ssrError);
|
|
53
|
-
throw ssrError;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
// Renderer for static-site-generator-webpack-plugin (async rendering).
|
|
57
|
-
async function doRender(locals) {
|
|
58
|
-
const { routesLocation, headTags, preBodyTags, postBodyTags, onLinksCollected, onHeadTagsCollected, baseUrl, ssrTemplate, noIndex, DOCUSAURUS_VERSION, } = locals;
|
|
59
|
-
const location = routesLocation[locals.path];
|
|
60
|
-
await preload(location);
|
|
15
|
+
const render = async ({ pathname }) => {
|
|
16
|
+
await preload(pathname);
|
|
61
17
|
const modules = new Set();
|
|
62
18
|
const routerContext = {};
|
|
63
19
|
const helmetContext = {};
|
|
@@ -66,77 +22,20 @@ async function doRender(locals) {
|
|
|
66
22
|
// @ts-expect-error: we are migrating away from react-loadable anyways
|
|
67
23
|
<Loadable.Capture report={(moduleName) => modules.add(moduleName)}>
|
|
68
24
|
<HelmetProvider context={helmetContext}>
|
|
69
|
-
<StaticRouter location={
|
|
25
|
+
<StaticRouter location={pathname} context={routerContext}>
|
|
70
26
|
<BrokenLinksProvider brokenLinks={statefulBrokenLinks}>
|
|
71
27
|
<App />
|
|
72
28
|
</BrokenLinksProvider>
|
|
73
29
|
</StaticRouter>
|
|
74
30
|
</HelmetProvider>
|
|
75
31
|
</Loadable.Capture>);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
32
|
+
const html = await renderToHtml(app);
|
|
33
|
+
const collectedData = {
|
|
34
|
+
helmet: helmetContext.helmet,
|
|
79
35
|
anchors: statefulBrokenLinks.getCollectedAnchors(),
|
|
80
36
|
links: statefulBrokenLinks.getCollectedLinks(),
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
helmet.title.toString(),
|
|
87
|
-
helmet.meta.toString(),
|
|
88
|
-
helmet.link.toString(),
|
|
89
|
-
helmet.script.toString(),
|
|
90
|
-
];
|
|
91
|
-
onHeadTagsCollected(location, helmet);
|
|
92
|
-
const metaAttributes = metaStrings.filter(Boolean);
|
|
93
|
-
const { generatedFilesDir } = locals;
|
|
94
|
-
const manifestPath = path.join(generatedFilesDir, 'client-manifest.json');
|
|
95
|
-
// Using readJSON seems to fail for users of some plugins, possibly because of
|
|
96
|
-
// the eval sandbox having a different `Buffer` instance (native one instead
|
|
97
|
-
// of polyfilled one)
|
|
98
|
-
const manifest = (await fs
|
|
99
|
-
.readFile(manifestPath, 'utf-8')
|
|
100
|
-
.then(JSON.parse));
|
|
101
|
-
// Get all required assets for this particular page based on client
|
|
102
|
-
// manifest information.
|
|
103
|
-
const modulesToBeLoaded = [...manifest.entrypoints, ...Array.from(modules)];
|
|
104
|
-
const bundles = getBundles(manifest, modulesToBeLoaded);
|
|
105
|
-
const stylesheets = (bundles.css ?? []).map((b) => b.file);
|
|
106
|
-
const scripts = (bundles.js ?? []).map((b) => b.file);
|
|
107
|
-
const renderedHtml = renderSSRTemplate(ssrTemplate, {
|
|
108
|
-
appHtml,
|
|
109
|
-
baseUrl,
|
|
110
|
-
htmlAttributes,
|
|
111
|
-
bodyAttributes,
|
|
112
|
-
headTags,
|
|
113
|
-
preBodyTags,
|
|
114
|
-
postBodyTags,
|
|
115
|
-
metaAttributes,
|
|
116
|
-
scripts,
|
|
117
|
-
stylesheets,
|
|
118
|
-
noIndex,
|
|
119
|
-
version: DOCUSAURUS_VERSION,
|
|
120
|
-
});
|
|
121
|
-
try {
|
|
122
|
-
if (process.env.SKIP_HTML_MINIFICATION === 'true') {
|
|
123
|
-
return renderedHtml;
|
|
124
|
-
}
|
|
125
|
-
// Minify html with https://github.com/DanielRuf/html-minifier-terser
|
|
126
|
-
return await minify(renderedHtml, {
|
|
127
|
-
removeComments: false,
|
|
128
|
-
removeRedundantAttributes: true,
|
|
129
|
-
removeEmptyAttributes: true,
|
|
130
|
-
removeScriptTypeAttributes: true,
|
|
131
|
-
removeStyleLinkTypeAttributes: true,
|
|
132
|
-
useShortDoctype: true,
|
|
133
|
-
minifyJS: true,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
catch (err) {
|
|
137
|
-
// prettier-ignore
|
|
138
|
-
console.error(`Minification of page ${locals.path} failed.`);
|
|
139
|
-
console.error(err);
|
|
140
|
-
throw err;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
37
|
+
modules: Array.from(modules),
|
|
38
|
+
};
|
|
39
|
+
return { html, collectedData };
|
|
40
|
+
};
|
|
41
|
+
export default render;
|
package/lib/commands/build.d.ts
CHANGED
|
@@ -10,4 +10,4 @@ export type BuildCLIOptions = Pick<LoadContextOptions, 'config' | 'locale' | 'ou
|
|
|
10
10
|
minify?: boolean;
|
|
11
11
|
dev?: boolean;
|
|
12
12
|
};
|
|
13
|
-
export declare function build(siteDirParam?: string, cliOptions?: Partial<BuildCLIOptions>, forceTerminate?: boolean): Promise<
|
|
13
|
+
export declare function build(siteDirParam?: string, cliOptions?: Partial<BuildCLIOptions>, forceTerminate?: boolean): Promise<void>;
|
package/lib/commands/build.js
CHANGED
|
@@ -10,19 +10,19 @@ exports.build = void 0;
|
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
13
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
13
14
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
14
15
|
const utils_1 = require("@docusaurus/utils");
|
|
15
|
-
const copy_webpack_plugin_1 = tslib_1.__importDefault(require("copy-webpack-plugin"));
|
|
16
|
-
const react_loadable_ssr_addon_v5_slorber_1 = tslib_1.__importDefault(require("react-loadable-ssr-addon-v5-slorber"));
|
|
17
|
-
const webpack_bundle_analyzer_1 = require("webpack-bundle-analyzer");
|
|
18
|
-
const webpack_merge_1 = tslib_1.__importDefault(require("webpack-merge"));
|
|
19
16
|
const server_1 = require("../server");
|
|
20
17
|
const brokenLinks_1 = require("../server/brokenLinks");
|
|
21
|
-
const client_1 =
|
|
18
|
+
const client_1 = require("../webpack/client");
|
|
22
19
|
const server_2 = tslib_1.__importDefault(require("../webpack/server"));
|
|
23
20
|
const utils_2 = require("../webpack/utils");
|
|
24
|
-
const
|
|
21
|
+
const utils_3 = require("../utils");
|
|
25
22
|
const i18n_1 = require("../server/i18n");
|
|
23
|
+
const ssg_1 = require("../ssg");
|
|
24
|
+
const templates_1 = require("../templates/templates");
|
|
25
|
+
const ssr_html_template_1 = tslib_1.__importDefault(require("../templates/ssr.html.template"));
|
|
26
26
|
async function build(siteDirParam = '.', cliOptions = {},
|
|
27
27
|
// When running build, we force terminate the process to prevent async
|
|
28
28
|
// operations from never returning. However, if run as part of docusaurus
|
|
@@ -43,13 +43,15 @@ forceTerminate = true) {
|
|
|
43
43
|
});
|
|
44
44
|
async function tryToBuildLocale({ locale, isLastLocale, }) {
|
|
45
45
|
try {
|
|
46
|
-
|
|
46
|
+
utils_3.PerfLogger.start(`Building site for locale ${locale}`);
|
|
47
|
+
await buildLocale({
|
|
47
48
|
siteDir,
|
|
48
49
|
locale,
|
|
49
50
|
cliOptions,
|
|
50
51
|
forceTerminate,
|
|
51
52
|
isLastLocale,
|
|
52
53
|
});
|
|
54
|
+
utils_3.PerfLogger.end(`Building site for locale ${locale}`);
|
|
53
55
|
}
|
|
54
56
|
catch (err) {
|
|
55
57
|
throw new Error(logger_1.default.interpolate `Unable to build website for locale name=${locale}.`, {
|
|
@@ -57,6 +59,24 @@ forceTerminate = true) {
|
|
|
57
59
|
});
|
|
58
60
|
}
|
|
59
61
|
}
|
|
62
|
+
utils_3.PerfLogger.start(`Get locales to build`);
|
|
63
|
+
const locales = await getLocalesToBuild({ siteDir, cliOptions });
|
|
64
|
+
utils_3.PerfLogger.end(`Get locales to build`);
|
|
65
|
+
if (locales.length > 1) {
|
|
66
|
+
logger_1.default.info `Website will be built for all these locales: ${locales}`;
|
|
67
|
+
}
|
|
68
|
+
utils_3.PerfLogger.start(`Building ${locales.length} locales`);
|
|
69
|
+
await (0, utils_1.mapAsyncSequential)(locales, (locale) => {
|
|
70
|
+
const isLastLocale = locales.indexOf(locale) === locales.length - 1;
|
|
71
|
+
return tryToBuildLocale({ locale, isLastLocale });
|
|
72
|
+
});
|
|
73
|
+
utils_3.PerfLogger.end(`Building ${locales.length} locales`);
|
|
74
|
+
}
|
|
75
|
+
exports.build = build;
|
|
76
|
+
async function getLocalesToBuild({ siteDir, cliOptions, }) {
|
|
77
|
+
if (cliOptions.locale) {
|
|
78
|
+
return [cliOptions.locale];
|
|
79
|
+
}
|
|
60
80
|
const context = await (0, server_1.loadContext)({
|
|
61
81
|
siteDir,
|
|
62
82
|
outDir: cliOptions.outDir,
|
|
@@ -67,31 +87,23 @@ forceTerminate = true) {
|
|
|
67
87
|
const i18n = await (0, i18n_1.loadI18n)(context.siteConfig, {
|
|
68
88
|
locale: cliOptions.locale,
|
|
69
89
|
});
|
|
70
|
-
if (cliOptions.locale) {
|
|
71
|
-
return tryToBuildLocale({ locale: cliOptions.locale, isLastLocale: true });
|
|
72
|
-
}
|
|
73
90
|
if (i18n.locales.length > 1) {
|
|
74
91
|
logger_1.default.info `Website will be built for all these locales: ${i18n.locales}`;
|
|
75
92
|
}
|
|
76
93
|
// We need the default locale to always be the 1st in the list. If we build it
|
|
77
94
|
// last, it would "erase" the localized sites built in sub-folders
|
|
78
|
-
|
|
95
|
+
return [
|
|
79
96
|
i18n.defaultLocale,
|
|
80
97
|
...i18n.locales.filter((locale) => locale !== i18n.defaultLocale),
|
|
81
98
|
];
|
|
82
|
-
const results = await (0, utils_1.mapAsyncSequential)(orderedLocales, (locale) => {
|
|
83
|
-
const isLastLocale = orderedLocales.indexOf(locale) === orderedLocales.length - 1;
|
|
84
|
-
return tryToBuildLocale({ locale, isLastLocale });
|
|
85
|
-
});
|
|
86
|
-
return results[0];
|
|
87
99
|
}
|
|
88
|
-
exports.build = build;
|
|
89
100
|
async function buildLocale({ siteDir, locale, cliOptions, forceTerminate, isLastLocale, }) {
|
|
90
101
|
// Temporary workaround to unlock the ability to translate the site config
|
|
91
102
|
// We'll remove it if a better official API can be designed
|
|
92
103
|
// See https://github.com/facebook/docusaurus/issues/4542
|
|
93
104
|
process.env.DOCUSAURUS_CURRENT_LOCALE = locale;
|
|
94
105
|
logger_1.default.info `name=${`[${locale}]`} Creating an optimized production build...`;
|
|
106
|
+
utils_3.PerfLogger.start('Loading site');
|
|
95
107
|
const props = await (0, server_1.load)({
|
|
96
108
|
siteDir,
|
|
97
109
|
outDir: cliOptions.outDir,
|
|
@@ -99,108 +111,152 @@ async function buildLocale({ siteDir, locale, cliOptions, forceTerminate, isLast
|
|
|
99
111
|
locale,
|
|
100
112
|
localizePath: cliOptions.locale ? false : undefined,
|
|
101
113
|
});
|
|
114
|
+
utils_3.PerfLogger.end('Loading site');
|
|
102
115
|
// Apply user webpack config.
|
|
103
|
-
const { outDir,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
const collectedLinks = {};
|
|
119
|
-
const headTags = {};
|
|
120
|
-
let serverConfig = await (0, server_2.default)({
|
|
121
|
-
props,
|
|
122
|
-
onLinksCollected: ({ staticPagePath, links, anchors }) => {
|
|
123
|
-
collectedLinks[staticPagePath] = { links, anchors };
|
|
124
|
-
},
|
|
125
|
-
onHeadTagsCollected: (staticPagePath, tags) => {
|
|
126
|
-
headTags[staticPagePath] = tags;
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
// The staticDirectories option can contain empty directories, or non-existent
|
|
130
|
-
// directories (e.g. user deleted `static`). Instead of issuing an error, we
|
|
131
|
-
// just silently filter them out, because user could have never configured it
|
|
132
|
-
// in the first place (the default option should always "work").
|
|
133
|
-
const staticDirectories = (await Promise.all(staticDirectoriesOption.map(async (dir) => {
|
|
134
|
-
const staticDir = path_1.default.resolve(siteDir, dir);
|
|
135
|
-
if ((await fs_extra_1.default.pathExists(staticDir)) &&
|
|
136
|
-
(await fs_extra_1.default.readdir(staticDir)).length > 0) {
|
|
137
|
-
return staticDir;
|
|
138
|
-
}
|
|
139
|
-
return '';
|
|
140
|
-
}))).filter(Boolean);
|
|
141
|
-
if (staticDirectories.length > 0) {
|
|
142
|
-
serverConfig = (0, webpack_merge_1.default)(serverConfig, {
|
|
143
|
-
plugins: [
|
|
144
|
-
new copy_webpack_plugin_1.default({
|
|
145
|
-
patterns: staticDirectories.map((dir) => ({
|
|
146
|
-
from: dir,
|
|
147
|
-
to: outDir,
|
|
148
|
-
toType: 'dir',
|
|
149
|
-
})),
|
|
150
|
-
}),
|
|
151
|
-
],
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
// Plugin Lifecycle - configureWebpack and configurePostCss.
|
|
155
|
-
plugins.forEach((plugin) => {
|
|
156
|
-
const { configureWebpack, configurePostCss } = plugin;
|
|
157
|
-
if (configurePostCss) {
|
|
158
|
-
clientConfig = (0, utils_2.applyConfigurePostCss)(configurePostCss.bind(plugin), clientConfig);
|
|
159
|
-
}
|
|
160
|
-
if (configureWebpack) {
|
|
161
|
-
clientConfig = (0, utils_2.applyConfigureWebpack)(configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
|
162
|
-
clientConfig, false, props.siteConfig.webpack?.jsLoader, plugin.content);
|
|
163
|
-
serverConfig = (0, utils_2.applyConfigureWebpack)(configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
|
|
164
|
-
serverConfig, true, props.siteConfig.webpack?.jsLoader, plugin.content);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
// Make sure generated client-manifest is cleaned first so we don't reuse
|
|
116
|
+
const { outDir, plugins } = props;
|
|
117
|
+
// We can build the 2 configs in parallel
|
|
118
|
+
utils_3.PerfLogger.start('Creating webpack configs');
|
|
119
|
+
const [{ clientConfig, clientManifestPath }, { serverConfig, serverBundlePath }] = await Promise.all([
|
|
120
|
+
getBuildClientConfig({
|
|
121
|
+
props,
|
|
122
|
+
cliOptions,
|
|
123
|
+
}),
|
|
124
|
+
getBuildServerConfig({
|
|
125
|
+
props,
|
|
126
|
+
}),
|
|
127
|
+
]);
|
|
128
|
+
utils_3.PerfLogger.end('Creating webpack configs');
|
|
129
|
+
// Make sure generated client-manifest is cleaned first, so we don't reuse
|
|
168
130
|
// the one from previous builds.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
131
|
+
// TODO do we really need this? .docusaurus folder is cleaned between builds
|
|
132
|
+
utils_3.PerfLogger.start('Deleting previous client manifest');
|
|
133
|
+
await ensureUnlink(clientManifestPath);
|
|
134
|
+
utils_3.PerfLogger.end('Deleting previous client manifest');
|
|
172
135
|
// Run webpack to build JS bundle (client) and static html files (server).
|
|
136
|
+
utils_3.PerfLogger.start('Bundling');
|
|
173
137
|
await (0, utils_2.compile)([clientConfig, serverConfig]);
|
|
138
|
+
utils_3.PerfLogger.end('Bundling');
|
|
139
|
+
utils_3.PerfLogger.start('Executing static site generation');
|
|
140
|
+
const { collectedData } = await executeSSG({
|
|
141
|
+
props,
|
|
142
|
+
serverBundlePath,
|
|
143
|
+
clientManifestPath,
|
|
144
|
+
});
|
|
145
|
+
utils_3.PerfLogger.end('Executing static site generation');
|
|
174
146
|
// Remove server.bundle.js because it is not needed.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
await fs_extra_1.default.unlink(serverBundle);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
147
|
+
utils_3.PerfLogger.start('Deleting server bundle');
|
|
148
|
+
await ensureUnlink(serverBundlePath);
|
|
149
|
+
utils_3.PerfLogger.end('Deleting server bundle');
|
|
181
150
|
// Plugin Lifecycle - postBuild.
|
|
151
|
+
utils_3.PerfLogger.start('Executing postBuild()');
|
|
152
|
+
await executePluginsPostBuild({ plugins, props, collectedData });
|
|
153
|
+
utils_3.PerfLogger.end('Executing postBuild()');
|
|
154
|
+
// TODO execute this in parallel to postBuild?
|
|
155
|
+
utils_3.PerfLogger.start('Executing broken links checker');
|
|
156
|
+
await executeBrokenLinksCheck({ props, collectedData });
|
|
157
|
+
utils_3.PerfLogger.end('Executing broken links checker');
|
|
158
|
+
logger_1.default.success `Generated static files in path=${path_1.default.relative(process.cwd(), outDir)}.`;
|
|
159
|
+
if (isLastLocale) {
|
|
160
|
+
logger_1.default.info `Use code=${'npm run serve'} command to test your build locally.`;
|
|
161
|
+
}
|
|
162
|
+
if (forceTerminate && isLastLocale && !cliOptions.bundleAnalyzer) {
|
|
163
|
+
process.exit(0);
|
|
164
|
+
}
|
|
165
|
+
return outDir;
|
|
166
|
+
}
|
|
167
|
+
async function executeSSG({ props, serverBundlePath, clientManifestPath, }) {
|
|
168
|
+
utils_3.PerfLogger.start('Reading client manifest');
|
|
169
|
+
const manifest = await fs_extra_1.default.readJSON(clientManifestPath, 'utf-8');
|
|
170
|
+
utils_3.PerfLogger.end('Reading client manifest');
|
|
171
|
+
utils_3.PerfLogger.start('Compiling SSR template');
|
|
172
|
+
const ssrTemplate = await (0, templates_1.compileSSRTemplate)(props.siteConfig.ssrTemplate ?? ssr_html_template_1.default);
|
|
173
|
+
utils_3.PerfLogger.end('Compiling SSR template');
|
|
174
|
+
utils_3.PerfLogger.start('Loading App renderer');
|
|
175
|
+
const renderer = await (0, ssg_1.loadAppRenderer)({
|
|
176
|
+
serverBundlePath,
|
|
177
|
+
});
|
|
178
|
+
utils_3.PerfLogger.end('Loading App renderer');
|
|
179
|
+
utils_3.PerfLogger.start('Generate static files');
|
|
180
|
+
const ssgResult = await (0, ssg_1.generateStaticFiles)({
|
|
181
|
+
pathnames: props.routesPaths,
|
|
182
|
+
renderer,
|
|
183
|
+
params: {
|
|
184
|
+
trailingSlash: props.siteConfig.trailingSlash,
|
|
185
|
+
outDir: props.outDir,
|
|
186
|
+
baseUrl: props.baseUrl,
|
|
187
|
+
manifest,
|
|
188
|
+
headTags: props.headTags,
|
|
189
|
+
preBodyTags: props.preBodyTags,
|
|
190
|
+
postBodyTags: props.postBodyTags,
|
|
191
|
+
ssrTemplate,
|
|
192
|
+
noIndex: props.siteConfig.noIndex,
|
|
193
|
+
DOCUSAURUS_VERSION: utils_1.DOCUSAURUS_VERSION,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
utils_3.PerfLogger.end('Generate static files');
|
|
197
|
+
return ssgResult;
|
|
198
|
+
}
|
|
199
|
+
async function executePluginsPostBuild({ plugins, props, collectedData, }) {
|
|
200
|
+
const head = lodash_1.default.mapValues(collectedData, (d) => d.helmet);
|
|
182
201
|
await Promise.all(plugins.map(async (plugin) => {
|
|
183
202
|
if (!plugin.postBuild) {
|
|
184
203
|
return;
|
|
185
204
|
}
|
|
186
205
|
await plugin.postBuild({
|
|
187
206
|
...props,
|
|
188
|
-
head
|
|
207
|
+
head,
|
|
189
208
|
content: plugin.content,
|
|
190
209
|
});
|
|
191
210
|
}));
|
|
211
|
+
}
|
|
212
|
+
async function executeBrokenLinksCheck({ props: { routes, siteConfig: { onBrokenLinks, onBrokenAnchors }, }, collectedData, }) {
|
|
213
|
+
const collectedLinks = lodash_1.default.mapValues(collectedData, (d) => ({
|
|
214
|
+
links: d.links,
|
|
215
|
+
anchors: d.anchors,
|
|
216
|
+
}));
|
|
192
217
|
await (0, brokenLinks_1.handleBrokenLinks)({
|
|
193
218
|
collectedLinks,
|
|
194
219
|
routes,
|
|
195
220
|
onBrokenLinks,
|
|
196
221
|
onBrokenAnchors,
|
|
197
222
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
223
|
+
}
|
|
224
|
+
async function getBuildClientConfig({ props, cliOptions, }) {
|
|
225
|
+
const { plugins } = props;
|
|
226
|
+
const result = await (0, client_1.createBuildClientConfig)({
|
|
227
|
+
props,
|
|
228
|
+
minify: cliOptions.minify ?? true,
|
|
229
|
+
bundleAnalyzer: cliOptions.bundleAnalyzer ?? false,
|
|
230
|
+
});
|
|
231
|
+
let { config } = result;
|
|
232
|
+
config = (0, utils_2.executePluginsConfigureWebpack)({
|
|
233
|
+
plugins,
|
|
234
|
+
config,
|
|
235
|
+
isServer: false,
|
|
236
|
+
jsLoader: props.siteConfig.webpack?.jsLoader,
|
|
237
|
+
});
|
|
238
|
+
return { clientConfig: config, clientManifestPath: result.clientManifestPath };
|
|
239
|
+
}
|
|
240
|
+
async function getBuildServerConfig({ props }) {
|
|
241
|
+
const { plugins } = props;
|
|
242
|
+
const result = await (0, server_2.default)({
|
|
243
|
+
props,
|
|
244
|
+
});
|
|
245
|
+
let { config } = result;
|
|
246
|
+
config = (0, utils_2.executePluginsConfigurePostCss)({
|
|
247
|
+
plugins,
|
|
248
|
+
config,
|
|
249
|
+
});
|
|
250
|
+
config = (0, utils_2.executePluginsConfigureWebpack)({
|
|
251
|
+
plugins,
|
|
252
|
+
config,
|
|
253
|
+
isServer: true,
|
|
254
|
+
jsLoader: props.siteConfig.webpack?.jsLoader,
|
|
255
|
+
});
|
|
256
|
+
return { serverConfig: config, serverBundlePath: result.serverBundlePath };
|
|
257
|
+
}
|
|
258
|
+
async function ensureUnlink(filepath) {
|
|
259
|
+
if (await fs_extra_1.default.pathExists(filepath)) {
|
|
260
|
+
await fs_extra_1.default.unlink(filepath);
|
|
204
261
|
}
|
|
205
|
-
return outDir;
|
|
206
262
|
}
|
package/lib/commands/deploy.js
CHANGED
|
@@ -184,7 +184,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`);
|
|
|
184
184
|
if (!cliOptions.skipBuild) {
|
|
185
185
|
// Build site, then push to deploymentBranch branch of specified repo.
|
|
186
186
|
try {
|
|
187
|
-
await (0, build_1.build)(siteDir, cliOptions, false).then(runDeploy);
|
|
187
|
+
await (0, build_1.build)(siteDir, cliOptions, false).then(() => runDeploy(outDir));
|
|
188
188
|
}
|
|
189
189
|
catch (err) {
|
|
190
190
|
logger_1.default.error('Deployment of the build output failed.');
|
package/lib/commands/serve.js
CHANGED
|
@@ -21,11 +21,11 @@ const getHostPort_1 = require("../server/getHostPort");
|
|
|
21
21
|
async function serve(siteDirParam = '.', cliOptions = {}) {
|
|
22
22
|
const siteDir = await fs_extra_1.default.realpath(siteDirParam);
|
|
23
23
|
const buildDir = cliOptions.dir ?? utils_1.DEFAULT_BUILD_DIR_NAME;
|
|
24
|
-
|
|
24
|
+
const outDir = path_1.default.resolve(siteDir, buildDir);
|
|
25
25
|
if (cliOptions.build) {
|
|
26
|
-
|
|
26
|
+
await (0, build_1.build)(siteDir, {
|
|
27
27
|
config: cliOptions.config,
|
|
28
|
-
outDir
|
|
28
|
+
outDir,
|
|
29
29
|
}, false);
|
|
30
30
|
}
|
|
31
31
|
const { host, port } = await (0, getHostPort_1.getHostPort)(cliOptions);
|
|
@@ -51,7 +51,7 @@ async function serve(siteDirParam = '.', cliOptions = {}) {
|
|
|
51
51
|
req.url = req.url.replace(baseUrl, '/');
|
|
52
52
|
(0, serve_handler_1.default)(req, res, {
|
|
53
53
|
cleanUrls: true,
|
|
54
|
-
public:
|
|
54
|
+
public: outDir,
|
|
55
55
|
trailingSlash,
|
|
56
56
|
directoryListing: false,
|
|
57
57
|
});
|