mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
perf(v2): significantly reduce bundle size & initial html payload (#1898)
* perf(v2): reduce bundle size significantly with super short chunk name and registry * changelog * use hash:8 as id for better long term caching * even shorter filename. slice contenthash
This commit is contained in:
parent
c23f981f67
commit
fabaf7772b
7 changed files with 45 additions and 20 deletions
|
@ -3,6 +3,7 @@
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
- Convert sitemap plugin to TypeScript
|
- Convert sitemap plugin to TypeScript
|
||||||
|
- Significantly reduce main bundle size and initial HTML payload on production build. Generated JS files from webpack is also shorter in name.
|
||||||
|
|
||||||
## 2.0.0-alpha.31
|
## 2.0.0-alpha.31
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,20 @@ describe('load utils', () => {
|
||||||
Object.keys(secondAssert).forEach(str => {
|
Object.keys(secondAssert).forEach(str => {
|
||||||
expect(genChunkName(str, undefined, 'blog')).toBe(secondAssert[str]);
|
expect(genChunkName(str, undefined, 'blog')).toBe(secondAssert[str]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Only generate short unique id
|
||||||
|
const thirdAssert = {
|
||||||
|
a: '0cc175b9',
|
||||||
|
b: '92eb5ffe',
|
||||||
|
c: '4a8a08f0',
|
||||||
|
d: '8277e091',
|
||||||
|
};
|
||||||
|
Object.keys(thirdAssert).forEach(str => {
|
||||||
|
expect(genChunkName(str, undefined, undefined, true)).toBe(
|
||||||
|
thirdAssert[str],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(genChunkName('d', undefined, undefined, true)).toBe('8277e091');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('idx', () => {
|
test('idx', () => {
|
||||||
|
|
|
@ -101,19 +101,27 @@ export function genChunkName(
|
||||||
modulePath: string,
|
modulePath: string,
|
||||||
prefix?: string,
|
prefix?: string,
|
||||||
preferredName?: string,
|
preferredName?: string,
|
||||||
|
shortId?: boolean,
|
||||||
): string {
|
): string {
|
||||||
let chunkName: string | undefined = chunkNameCache.get(modulePath);
|
let chunkName: string | undefined = chunkNameCache.get(modulePath);
|
||||||
if (!chunkName) {
|
if (!chunkName) {
|
||||||
let str = modulePath;
|
if (shortId) {
|
||||||
if (preferredName) {
|
chunkName = createHash('md5')
|
||||||
const shortHash = createHash('md5')
|
|
||||||
.update(modulePath)
|
.update(modulePath)
|
||||||
.digest('hex')
|
.digest('hex')
|
||||||
.substr(0, 3);
|
.substr(0, 8);
|
||||||
str = `${preferredName}${shortHash}`;
|
} else {
|
||||||
|
let str = modulePath;
|
||||||
|
if (preferredName) {
|
||||||
|
const shortHash = createHash('md5')
|
||||||
|
.update(modulePath)
|
||||||
|
.digest('hex')
|
||||||
|
.substr(0, 3);
|
||||||
|
str = `${preferredName}${shortHash}`;
|
||||||
|
}
|
||||||
|
const name = str === '/' ? 'index' : docuHash(str);
|
||||||
|
chunkName = prefix ? `${prefix}---${name}` : name;
|
||||||
}
|
}
|
||||||
const name = str === '/' ? 'index' : docuHash(str);
|
|
||||||
chunkName = prefix ? `${prefix}---${name}` : name;
|
|
||||||
chunkNameCache.set(modulePath, chunkName);
|
chunkNameCache.set(modulePath, chunkName);
|
||||||
}
|
}
|
||||||
return chunkName;
|
return chunkName;
|
||||||
|
|
|
@ -56,9 +56,11 @@ function ComponentCreator(path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const chunkRegistry = registry[target] || {};
|
const chunkRegistry = registry[target] || {};
|
||||||
optsLoader[keys.join('.')] = chunkRegistry.loader;
|
/* eslint-disable prefer-destructuring */
|
||||||
optsModules.push(chunkRegistry.module);
|
optsLoader[keys.join('.')] = chunkRegistry[0];
|
||||||
optsWebpack.push(chunkRegistry.webpack);
|
optsModules.push(chunkRegistry[1]);
|
||||||
|
optsWebpack.push(chunkRegistry[2]);
|
||||||
|
/* eslint-enable prefer-destructuring */
|
||||||
}
|
}
|
||||||
|
|
||||||
traverseChunk(chunkNames, []);
|
traverseChunk(chunkNames, []);
|
||||||
|
|
|
@ -117,11 +117,10 @@ export async function load(siteDir: string): Promise<Props> {
|
||||||
`export default {
|
`export default {
|
||||||
${Object.keys(registry)
|
${Object.keys(registry)
|
||||||
.map(
|
.map(
|
||||||
key => ` '${key}': {
|
key =>
|
||||||
'loader': ${registry[key].loader},
|
` '${key}': [${registry[key].loader}, ${JSON.stringify(
|
||||||
'module': ${JSON.stringify(registry[key].modulePath)},
|
registry[key].modulePath,
|
||||||
'webpack': require.resolveWeak(${JSON.stringify(registry[key].modulePath)}),
|
)}, require.resolveWeak(${JSON.stringify(registry[key].modulePath)})],`,
|
||||||
},`,
|
|
||||||
)
|
)
|
||||||
.join('\n')}};\n`,
|
.join('\n')}};\n`,
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,6 +24,7 @@ function getModulePath(target: Module): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) {
|
export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) {
|
||||||
|
const isProd = process.env.NODE_ENV === 'production';
|
||||||
const routesImports = [
|
const routesImports = [
|
||||||
`import React from 'react';`,
|
`import React from 'react';`,
|
||||||
`import ComponentCreator from '@docusaurus/ComponentCreator';`,
|
`import ComponentCreator from '@docusaurus/ComponentCreator';`,
|
||||||
|
@ -82,7 +83,7 @@ export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const modulePath = getModulePath(value as Module);
|
const modulePath = getModulePath(value as Module);
|
||||||
const chunkName = genChunkName(modulePath, prefix, name);
|
const chunkName = genChunkName(modulePath, prefix, name, isProd);
|
||||||
const loader = `() => import(/* webpackChunkName: '${chunkName}' */ ${JSON.stringify(
|
const loader = `() => import(/* webpackChunkName: '${chunkName}' */ ${JSON.stringify(
|
||||||
modulePath,
|
modulePath,
|
||||||
)})`;
|
)})`;
|
||||||
|
|
|
@ -32,8 +32,8 @@ export function createBaseConfig(
|
||||||
output: {
|
output: {
|
||||||
pathinfo: false,
|
pathinfo: false,
|
||||||
path: outDir,
|
path: outDir,
|
||||||
filename: isProd ? '[name].[contenthash].js' : '[name].js',
|
filename: isProd ? '[name].[contenthash:8].js' : '[name].js',
|
||||||
chunkFilename: isProd ? '[name].[contenthash].js' : '[name].js',
|
chunkFilename: isProd ? '[name].[contenthash:8].js' : '[name].js',
|
||||||
publicPath: baseUrl,
|
publicPath: baseUrl,
|
||||||
},
|
},
|
||||||
// Don't throw warning when asset created is over 250kb
|
// Don't throw warning when asset created is over 250kb
|
||||||
|
@ -157,8 +157,8 @@ export function createBaseConfig(
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: isProd ? '[name].[contenthash].css' : '[name].css',
|
filename: isProd ? '[name].[contenthash:8].css' : '[name].css',
|
||||||
chunkFilename: isProd ? '[name].[contenthash].css' : '[name].css',
|
chunkFilename: isProd ? '[name].[contenthash:8].css' : '[name].css',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue