From fabaf7772b83cce0abc4f0433d4edddf74d3303f Mon Sep 17 00:00:00 2001 From: Endi Date: Sun, 27 Oct 2019 21:09:19 +0700 Subject: [PATCH] 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 --- CHANGELOG-2.x.md | 1 + .../src/__tests__/index.test.ts | 14 ++++++++++++ packages/docusaurus-utils/src/index.ts | 22 +++++++++++++------ .../src/client/exports/ComponentCreator.js | 8 ++++--- packages/docusaurus/src/server/index.ts | 9 ++++---- packages/docusaurus/src/server/routes.ts | 3 ++- packages/docusaurus/src/webpack/base.ts | 8 +++---- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/CHANGELOG-2.x.md b/CHANGELOG-2.x.md index b6cec6facd..5ba3a327a4 100644 --- a/CHANGELOG-2.x.md +++ b/CHANGELOG-2.x.md @@ -3,6 +3,7 @@ ## Unreleased - 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 diff --git a/packages/docusaurus-utils/src/__tests__/index.test.ts b/packages/docusaurus-utils/src/__tests__/index.test.ts index 464b6587bc..2c0b770b17 100644 --- a/packages/docusaurus-utils/src/__tests__/index.test.ts +++ b/packages/docusaurus-utils/src/__tests__/index.test.ts @@ -108,6 +108,20 @@ describe('load utils', () => { Object.keys(secondAssert).forEach(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', () => { diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index ccc87cd2d8..01c73cdd36 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -101,19 +101,27 @@ export function genChunkName( modulePath: string, prefix?: string, preferredName?: string, + shortId?: boolean, ): string { let chunkName: string | undefined = chunkNameCache.get(modulePath); if (!chunkName) { - let str = modulePath; - if (preferredName) { - const shortHash = createHash('md5') + if (shortId) { + chunkName = createHash('md5') .update(modulePath) .digest('hex') - .substr(0, 3); - str = `${preferredName}${shortHash}`; + .substr(0, 8); + } 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); } return chunkName; diff --git a/packages/docusaurus/src/client/exports/ComponentCreator.js b/packages/docusaurus/src/client/exports/ComponentCreator.js index 46ab1b15dc..d82095d670 100644 --- a/packages/docusaurus/src/client/exports/ComponentCreator.js +++ b/packages/docusaurus/src/client/exports/ComponentCreator.js @@ -56,9 +56,11 @@ function ComponentCreator(path) { } const chunkRegistry = registry[target] || {}; - optsLoader[keys.join('.')] = chunkRegistry.loader; - optsModules.push(chunkRegistry.module); - optsWebpack.push(chunkRegistry.webpack); + /* eslint-disable prefer-destructuring */ + optsLoader[keys.join('.')] = chunkRegistry[0]; + optsModules.push(chunkRegistry[1]); + optsWebpack.push(chunkRegistry[2]); + /* eslint-enable prefer-destructuring */ } traverseChunk(chunkNames, []); diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index 0b9270e4ac..f97654b9a3 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -117,11 +117,10 @@ export async function load(siteDir: string): Promise { `export default { ${Object.keys(registry) .map( - key => ` '${key}': { - 'loader': ${registry[key].loader}, - 'module': ${JSON.stringify(registry[key].modulePath)}, - 'webpack': require.resolveWeak(${JSON.stringify(registry[key].modulePath)}), - },`, + key => + ` '${key}': [${registry[key].loader}, ${JSON.stringify( + registry[key].modulePath, + )}, require.resolveWeak(${JSON.stringify(registry[key].modulePath)})],`, ) .join('\n')}};\n`, ); diff --git a/packages/docusaurus/src/server/routes.ts b/packages/docusaurus/src/server/routes.ts index 520f22a9e0..6f2bfa8619 100644 --- a/packages/docusaurus/src/server/routes.ts +++ b/packages/docusaurus/src/server/routes.ts @@ -24,6 +24,7 @@ function getModulePath(target: Module): string { } export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) { + const isProd = process.env.NODE_ENV === 'production'; const routesImports = [ `import React from 'react';`, `import ComponentCreator from '@docusaurus/ComponentCreator';`, @@ -82,7 +83,7 @@ export async function loadRoutes(pluginsRouteConfigs: RouteConfig[]) { } 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( modulePath, )})`; diff --git a/packages/docusaurus/src/webpack/base.ts b/packages/docusaurus/src/webpack/base.ts index 866071e858..bbbca0c383 100644 --- a/packages/docusaurus/src/webpack/base.ts +++ b/packages/docusaurus/src/webpack/base.ts @@ -32,8 +32,8 @@ export function createBaseConfig( output: { pathinfo: false, path: outDir, - filename: isProd ? '[name].[contenthash].js' : '[name].js', - chunkFilename: isProd ? '[name].[contenthash].js' : '[name].js', + filename: isProd ? '[name].[contenthash:8].js' : '[name].js', + chunkFilename: isProd ? '[name].[contenthash:8].js' : '[name].js', publicPath: baseUrl, }, // Don't throw warning when asset created is over 250kb @@ -157,8 +157,8 @@ export function createBaseConfig( }, plugins: [ new MiniCssExtractPlugin({ - filename: isProd ? '[name].[contenthash].css' : '[name].css', - chunkFilename: isProd ? '[name].[contenthash].css' : '[name].css', + filename: isProd ? '[name].[contenthash:8].css' : '[name].css', + chunkFilename: isProd ? '[name].[contenthash:8].css' : '[name].css', }), ], };