Skip to content

Commit

Permalink
refactor: when ssg build, init only one rsbuild instance (#1169)
Browse files Browse the repository at this point in the history
  • Loading branch information
SoonIter authored Jul 4, 2024
1 parent e38f484 commit 3b49d67
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 60 deletions.
34 changes: 9 additions & 25 deletions packages/core/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,15 @@ export async function bundle(
enableSSG: boolean,
) {
try {
if (enableSSG) {
const [clientBuilder, ssrBuilder] = await Promise.all([
initRsbuild(docDirectory, config, pluginDriver, false),
initRsbuild(docDirectory, config, pluginDriver, true, {
output: {
minify: false,
},
tools: {
rspack(options) {
options.output.filename = 'main.cjs';
},
},
}),
]);
await Promise.all([clientBuilder.build(), ssrBuilder.build()]);
} else {
// Only build client bundle
const clientBuilder = await initRsbuild(
docDirectory,
config,
pluginDriver,
false,
);
await clientBuilder.build();
}
// if enableSSG, build both client and server bundle
// else only build client bundle
const rsbuild = await initRsbuild(
docDirectory,
config,
pluginDriver,
enableSSG,
);
await rsbuild.build();
} finally {
await writeSearchIndex(config);
}
Expand Down
100 changes: 75 additions & 25 deletions packages/core/src/node/initRsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function isPluginIncluded(config: UserConfig, pluginName: string): boolean {
async function createInternalBuildConfig(
userDocRoot: string,
config: UserConfig,
isSSR: boolean,
enableSSG: boolean,
routeService: RouteService,
pluginDriver: PluginDriver,
runtimeTempDir: string,
Expand All @@ -61,10 +61,10 @@ async function createInternalBuildConfig(
const CUSTOM_THEME_DIR =
config?.themeDir ?? path.join(process.cwd(), 'theme');
const baseOutDir = config?.outDir ?? OUTPUT_DIR;
const outDir = isSSR ? path.join(baseOutDir, 'ssr') : baseOutDir;
const csrOutDir = baseOutDir;
const ssrOutDir = path.join(baseOutDir, 'ssr');

const DEFAULT_THEME = require.resolve('@rspress/theme-default');
const checkDeadLinks = (config?.markdown?.checkDeadLinks && !isSSR) ?? false;
const base = config?.base ?? '';

// In production, we need to add assetPrefix in asset path
Expand Down Expand Up @@ -95,6 +95,10 @@ async function createInternalBuildConfig(
];
const ssrBrowserslist = ['node >= 14'];

const detectCustomIconAlias = await detectCustomIcon(CUSTOM_THEME_DIR);
const reactSSRAlias = await resolveReactAlias(reactVersion, true);
const reactCSRAlias = await resolveReactAlias(reactVersion, false);

return {
plugins: [
...(isPluginIncluded(config, PLUGIN_REACT_NAME) ? [] : [pluginReact()]),
Expand All @@ -103,7 +107,6 @@ async function createInternalBuildConfig(
rsbuildPluginDocVM({
userDocRoot,
config,
isSSR,
runtimeTempDir,
routeService,
pluginDriver,
Expand All @@ -117,11 +120,9 @@ async function createInternalBuildConfig(
printUrls: ({ urls }) => {
return urls.map(url => `${url}/${removeLeadingSlash(base)}`);
},
publicDir: isSSR
? false
: {
name: path.join(userDocRoot, PUBLIC_DIR),
},
publicDir: {
name: path.join(userDocRoot, PUBLIC_DIR),
},
},
dev: {
progressBar: false,
Expand All @@ -145,19 +146,15 @@ async function createInternalBuildConfig(
].filter(Boolean),
},
output: {
target: isSSR ? 'node' : 'web',
assetPrefix,
distPath: {
// `root` must be a relative path in Rsbuild
root: path.isAbsolute(outDir) ? path.relative(cwd, outDir) : outDir,
// just for rsbuild preview
root: csrOutDir,
},
overrideBrowserslist: isSSR ? ssrBrowserslist : webBrowserslist,
assetPrefix,
},
source: {
entry: {
index: isSSR ? SSR_ENTRY : CLIENT_ENTRY,
},
alias: {
...detectCustomIconAlias,
'@mdx-js/react': require.resolve('@mdx-js/react'),
'@theme': [CUSTOM_THEME_DIR, DEFAULT_THEME],
'@/theme-default': DEFAULT_THEME,
Expand All @@ -166,21 +163,16 @@ async function createInternalBuildConfig(
'react-syntax-highlighter': path.dirname(
require.resolve('react-syntax-highlighter/package.json'),
),
...(await resolveReactAlias(reactVersion, isSSR)),
...(await detectCustomIcon(CUSTOM_THEME_DIR)),
'@theme-assets': path.join(DEFAULT_THEME, '../assets'),
},
include: [PACKAGE_ROOT, path.join(cwd, 'node_modules', RSPRESS_TEMP_DIR)],
define: {
'process.env.__ASSET_PREFIX__': JSON.stringify(assetPrefix),
'process.env.__SSR__': JSON.stringify(isSSR),
'process.env.__IS_REACT_18__': JSON.stringify(reactVersion === 18),
'process.env.TEST': JSON.stringify(process.env.TEST),
},
},
performance: {
// No need to print the server bundles size
printFileSize: !isSSR,
chunkSplit: {
override: {
cacheGroups: {
Expand All @@ -198,13 +190,17 @@ async function createInternalBuildConfig(
},
},
tools: {
bundlerChain(chain, { CHAIN_ID }) {
bundlerChain(chain, { CHAIN_ID, target }) {
const isServer = target === 'node';
const jsModuleRule = chain.module.rule(CHAIN_ID.RULE.JS);

const swcLoaderOptions = jsModuleRule
.use(CHAIN_ID.USE.SWC)
.get('options');

const checkDeadLinks =
(config?.markdown?.checkDeadLinks && !isServer) ?? false;

chain.module
.rule('MDX')
.type('javascript/auto')
Expand Down Expand Up @@ -244,16 +240,70 @@ async function createInternalBuildConfig(
.rule('css-virtual-module')
.test(/\.rspress[\\/]runtime[\\/]virtual-global-styles/)
.merge({ sideEffects: true });

if (isServer) {
chain.output.filename('main.cjs');
}
},
},
environments: {
web: {
source: {
entry: {
index: CLIENT_ENTRY,
},
alias: {
...reactCSRAlias,
},
define: {
'process.env.__SSR__': JSON.stringify(false),
},
},
output: {
target: 'web',
overrideBrowserslist: webBrowserslist,
distPath: {
root: csrOutDir,
},
},
},
...(enableSSG
? {
node: {
source: {
entry: {
index: SSR_ENTRY,
},
alias: {
...reactSSRAlias,
},
define: {
'process.env.__SSR__': JSON.stringify(true),
},
},
performance: {
printFileSize: false,
},
output: {
target: 'node',
overrideBrowserslist: ssrBrowserslist,
distPath: {
root: ssrOutDir,
},
minify: false,
},
},
}
: {}),
},
};
}

export async function initRsbuild(
rootDir: string,
config: UserConfig,
pluginDriver: PluginDriver,
isSSR = false,
enableSSG: boolean,
extraRsbuildConfig?: RsbuildConfig,
): Promise<RsbuildInstance> {
const cwd = process.cwd();
Expand All @@ -276,7 +326,7 @@ export async function initRsbuild(
const internalRsbuildConfig = await createInternalBuildConfig(
userDocRoot,
config,
isSSR,
enableSSG,
routeService,
pluginDriver,
runtimeTempDir,
Expand Down
21 changes: 12 additions & 9 deletions packages/core/src/node/runtimeModule/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,22 @@ export const runtimeModuleFactory: RuntimeModuleFactory[] = [

// We will use this plugin to generate runtime module in browser, which is important to ensure the client have access to some compile-time data
export function rsbuildPluginDocVM(
factoryContext: Omit<FactoryContext, 'alias'>,
factoryContext: Omit<FactoryContext, 'alias' | 'isSSR'>,
): RsbuildPlugin {
const { pluginDriver } = factoryContext;
return {
name: 'rsbuild-plugin-doc-vm',
setup(api) {
api.modifyBundlerChain(async bundlerChain => {
api.modifyBundlerChain(async (bundlerChain, { target }) => {
const isServer = target === 'node';
// The order should be sync
const alias = bundlerChain.resolve.alias.entries();
const runtimeModule: Record<string, string> = {};
// Add internal runtime module
for (const factory of runtimeModuleFactory) {
const moduleResult = await factory({
...factoryContext,
isSSR: isServer,
alias: alias as Record<string, string>,
});
Object.assign(runtimeModule, moduleResult);
Expand All @@ -82,13 +84,14 @@ export function rsbuildPluginDocVM(
}
runtimeModule[key] = modulesByPlugin[key];
});
bundlerChain.plugin('rspress-runtime-module').use(
// @ts-expect-error
new RspackVirtualModulePlugin(
runtimeModule,
factoryContext.runtimeTempDir,
),
);
bundlerChain
.plugin('rspress-runtime-module')
.use(
new RspackVirtualModulePlugin(
runtimeModule,
factoryContext.runtimeTempDir,
),
);
});
},
};
Expand Down
9 changes: 8 additions & 1 deletion packages/shared/src/runtime-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ export const DEFAULT_HIGHLIGHT_LANGUAGES = [
['mdx', 'tsx'],
];

// TODO: these utils should be divided into node and runtime
export const isSCM = () => Boolean(process.env.BUILD_VERSION);

export const isProduction = () => process.env.NODE_ENV === 'production';

export const isDebugMode = () => Boolean(process.env.DOC_DEBUG);
export const isDebugMode = () => {
if (!process.env.DEBUG) {
return false;
}
const values = process.env.DEBUG?.toLocaleLowerCase().split(',') ?? [];
return ['rsbuild', 'builder', '*'].some(key => values.includes(key));
};

export const cleanUrl = (url: string): string =>
url.replace(HASH_REGEXP, '').replace(QUERY_REGEXP, '');
Expand Down

0 comments on commit 3b49d67

Please sign in to comment.