@docusaurus/core 0.0.0-5823 → 0.0.0-5827

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.
@@ -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
- // Do not use logger.error here: it does not print error causes
273
- console.error(err);
274
- console.log('');
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}`;
@@ -5,4 +5,4 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { ReactNode } from 'react';
8
- export declare function renderStaticApp(app: ReactNode): Promise<string>;
8
+ export declare function renderToHtml(app: ReactNode): Promise<string>;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { renderToPipeableStream } from 'react-dom/server';
8
8
  import { Writable } from 'stream';
9
- export async function renderStaticApp(app) {
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 { Locals } from '@slorber/static-site-generator-webpack-plugin';
8
- export default function render(locals: Locals & {
9
- path: string;
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 { minify } from 'html-minifier-terser';
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 getCompiledSSRTemplate = _.memoize((template) => eta.compile(template.trim(), {
23
- rmWhitespace: true,
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={location} context={routerContext}>
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 appHtml = await renderStaticApp(app);
77
- onLinksCollected({
78
- staticPagePath: location,
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
- const { helmet } = helmetContext;
83
- const htmlAttributes = helmet.htmlAttributes.toString();
84
- const bodyAttributes = helmet.bodyAttributes.toString();
85
- const metaStrings = [
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;
@@ -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<string>;
13
+ export declare function build(siteDirParam?: string, cliOptions?: Partial<BuildCLIOptions>, forceTerminate?: boolean): Promise<void>;
@@ -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 = tslib_1.__importDefault(require("../webpack/client"));
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 CleanWebpackPlugin_1 = tslib_1.__importDefault(require("../webpack/plugins/CleanWebpackPlugin"));
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
- return await buildLocale({
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
- const orderedLocales = [
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, generatedFilesDir, plugins, siteConfig: { onBrokenLinks, onBrokenAnchors, staticDirectories: staticDirectoriesOption, }, routes, } = props;
104
- const clientManifestPath = path_1.default.join(generatedFilesDir, 'client-manifest.json');
105
- let clientConfig = (0, webpack_merge_1.default)(await (0, client_1.default)(props, cliOptions.minify, true), {
106
- plugins: [
107
- // Remove/clean build folders before building bundles.
108
- new CleanWebpackPlugin_1.default({ verbose: false }),
109
- // Visualize size of webpack output files with an interactive zoomable
110
- // tree map.
111
- cliOptions.bundleAnalyzer && new webpack_bundle_analyzer_1.BundleAnalyzerPlugin(),
112
- // Generate client manifests file that will be used for server bundle.
113
- new react_loadable_ssr_addon_v5_slorber_1.default({
114
- filename: clientManifestPath,
115
- }),
116
- ].filter((x) => Boolean(x)),
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
- if (await fs_extra_1.default.pathExists(clientManifestPath)) {
170
- await fs_extra_1.default.unlink(clientManifestPath);
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
- if (typeof serverConfig.output?.filename === 'string') {
176
- const serverBundle = path_1.default.join(outDir, serverConfig.output.filename);
177
- if (await fs_extra_1.default.pathExists(serverBundle)) {
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: headTags,
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
- logger_1.default.success `Generated static files in path=${path_1.default.relative(process.cwd(), outDir)}.`;
199
- if (isLastLocale) {
200
- logger_1.default.info `Use code=${'npm run serve'} command to test your build locally.`;
201
- }
202
- if (forceTerminate && isLastLocale && !cliOptions.bundleAnalyzer) {
203
- process.exit(0);
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
  }
@@ -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.');
@@ -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
- let dir = path_1.default.resolve(siteDir, buildDir);
24
+ const outDir = path_1.default.resolve(siteDir, buildDir);
25
25
  if (cliOptions.build) {
26
- dir = await (0, build_1.build)(siteDir, {
26
+ await (0, build_1.build)(siteDir, {
27
27
  config: cliOptions.config,
28
- outDir: dir,
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: dir,
54
+ public: outDir,
55
55
  trailingSlash,
56
56
  directoryListing: false,
57
57
  });