in packages/docusaurus/src/commands/build.ts [96:253]
async function buildLocale({
siteDir,
locale,
cliOptions,
forceTerminate,
isLastLocale,
}: {
siteDir: string;
locale: string;
cliOptions: Partial<BuildCLIOptions>;
forceTerminate: boolean;
isLastLocale: boolean;
}): Promise<string> {
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
logger.info`name=${`[${locale}]`} Creating an optimized production build...`;
const props: Props = await load({
siteDir,
customOutDir: cliOptions.outDir,
customConfigFilePath: cliOptions.config,
locale,
localizePath: cliOptions.locale ? false : undefined,
});
// Apply user webpack config.
const {
outDir,
generatedFilesDir,
plugins,
siteConfig: {baseUrl, onBrokenLinks, staticDirectories},
routes,
} = props;
const clientManifestPath = path.join(
generatedFilesDir,
'client-manifest.json',
);
let clientConfig: Configuration = merge(
await createClientConfig(props, cliOptions.minify),
{
plugins: [
// Remove/clean build folders before building bundles.
new CleanWebpackPlugin({verbose: false}),
// Visualize size of webpack output files with an interactive zoomable
// tree map.
cliOptions.bundleAnalyzer && new BundleAnalyzerPlugin(),
// Generate client manifests file that will be used for server bundle.
new ReactLoadableSSRAddon({
filename: clientManifestPath,
}),
].filter(Boolean),
},
);
const allCollectedLinks: {[location: string]: string[]} = {};
let serverConfig: Configuration = await createServerConfig({
props,
onLinksCollected: (staticPagePath, links) => {
allCollectedLinks[staticPagePath] = links;
},
});
if (staticDirectories.length > 0) {
await Promise.all(staticDirectories.map((dir) => fs.ensureDir(dir)));
serverConfig = merge(serverConfig, {
plugins: [
new CopyWebpackPlugin({
patterns: staticDirectories
.map((dir) => path.resolve(siteDir, dir))
.map((dir) => ({from: dir, to: outDir})),
}),
],
});
}
// Plugin Lifecycle - configureWebpack and configurePostCss.
plugins.forEach((plugin) => {
const {configureWebpack, configurePostCss} = plugin;
if (configurePostCss) {
clientConfig = applyConfigurePostCss(
configurePostCss.bind(plugin),
clientConfig,
);
}
if (configureWebpack) {
clientConfig = applyConfigureWebpack(
configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
clientConfig,
false,
props.siteConfig.webpack?.jsLoader,
plugin.content,
);
serverConfig = applyConfigureWebpack(
configureWebpack.bind(plugin), // The plugin lifecycle may reference `this`.
serverConfig,
true,
props.siteConfig.webpack?.jsLoader,
plugin.content,
);
}
});
// Make sure generated client-manifest is cleaned first so we don't reuse
// the one from previous builds.
if (await fs.pathExists(clientManifestPath)) {
await fs.unlink(clientManifestPath);
}
// Run webpack to build JS bundle (client) and static html files (server).
await compile([clientConfig, serverConfig]);
// Remove server.bundle.js because it is not needed.
if (typeof serverConfig.output?.filename === 'string') {
const serverBundle = path.join(outDir, serverConfig.output.filename);
if (await fs.pathExists(serverBundle)) {
await fs.unlink(serverBundle);
}
}
// Plugin Lifecycle - postBuild.
await Promise.all(
plugins.map(async (plugin) => {
if (!plugin.postBuild) {
return;
}
await plugin.postBuild({...props, content: plugin.content});
}),
);
await handleBrokenLinks({
allCollectedLinks,
routes,
onBrokenLinks,
outDir,
baseUrl,
});
logger.success`Generated static files in path=${path.relative(
process.cwd(),
outDir,
)}.`;
if (isLastLocale) {
logger.info`Use code=${'npm run serve'} command to test your build locally.`;
}
if (forceTerminate && isLastLocale && !cliOptions.bundleAnalyzer) {
process.exit(0);
}
return outDir;
}