From 4112ab62e9095dc27f01f420067e7f41dd7bd828 Mon Sep 17 00:00:00 2001 From: xierenyuan Date: Thu, 24 Nov 2022 21:08:30 +0800 Subject: [PATCH 1/4] feat(preset-umi): codeSplitting support auto load chunk --- examples/ant-design-pro/config/config.ts | 3 + examples/max/.umirc.ts | 3 + packages/preset-umi/src/commands/build.ts | 11 +-- .../src/commands/dev/getAssetsMap.ts | 11 +-- .../features/codeSplitting/codeSplitting.ts | 93 ++++++++++++++++++- 5 files changed, 99 insertions(+), 22 deletions(-) diff --git a/examples/ant-design-pro/config/config.ts b/examples/ant-design-pro/config/config.ts index bebee2cebe6a..217378fdd27d 100644 --- a/examples/ant-design-pro/config/config.ts +++ b/examples/ant-design-pro/config/config.ts @@ -335,4 +335,7 @@ export default defineConfig({ // type: 'none', // }, // exportStatic: {}, + codeSplitting: { + jsStrategy: 'granularChunks', + }, }); diff --git a/examples/max/.umirc.ts b/examples/max/.umirc.ts index 11d3e8deb73f..9c730a0d94a4 100644 --- a/examples/max/.umirc.ts +++ b/examples/max/.umirc.ts @@ -101,4 +101,7 @@ export default defineConfig({ // vite: {} // esmi: { cdnOrigin: 'https://npmcore-pre.alipay.com' }, // lowImport: {}, + codeSplitting: { + jsStrategy: 'granularChunks', + }, }); diff --git a/packages/preset-umi/src/commands/build.ts b/packages/preset-umi/src/commands/build.ts index 2f023dcbd4b5..f2f7a7fabd5c 100644 --- a/packages/preset-umi/src/commands/build.ts +++ b/packages/preset-umi/src/commands/build.ts @@ -167,18 +167,11 @@ umi build --clean styles: markupArgs.styles.concat( api.config.vite ? [] - : [ - ...(assetsMap['framework.css'] || []).map((src) => ({ src })), - ...(assetsMap['umi.css'] || []).map((src) => ({ src })), - ], + : [...(assetsMap['umi.css'] || []).map((src) => ({ src }))], ), scripts: (api.config.vite ? [] - : [ - // framework 先写死,后续考虑通过插件的方式注入 - ...(assetsMap['framework.js'] || []).map((src) => ({ src })), - ...(assetsMap['umi.js'] || []).map((src) => ({ src })), - ] + : [...(assetsMap['umi.js'] || []).map((src) => ({ src }))] ).concat(markupArgs.scripts), esmScript: !!opts.config.esm || vite, path: '/', diff --git a/packages/preset-umi/src/commands/dev/getAssetsMap.ts b/packages/preset-umi/src/commands/dev/getAssetsMap.ts index 7c7ea6f7a36b..b92b9f0f7f4b 100644 --- a/packages/preset-umi/src/commands/dev/getAssetsMap.ts +++ b/packages/preset-umi/src/commands/dev/getAssetsMap.ts @@ -2,10 +2,7 @@ const UMI_ASSETS_REG = { js: /^umi(\..+)?\.js$/, css: /^umi(\..+)?\.css$/, }; -const FRAMEWORK_ASSETS_REG = { - js: /^framework(\..+)?\.js$/, - css: /^framework(\..+)?\.css$/, -}; + const HOT_UPDATE = '.hot-update.'; export function getAssetsMap(opts: { stats: any; publicPath: string }) { @@ -20,16 +17,10 @@ export function getAssetsMap(opts: { stats: any; publicPath: string }) { if (UMI_ASSETS_REG.js.test(asset)) { ret['umi.js'] = [`${displayPublicPath}${asset}`]; } - if (FRAMEWORK_ASSETS_REG.js.test(asset)) { - ret['framework.js'] = [`${displayPublicPath}${asset}`]; - } } if (UMI_ASSETS_REG.css.test(asset)) { ret['umi.css'] = [`${displayPublicPath}${asset}`]; } - if (FRAMEWORK_ASSETS_REG.css.test(asset)) { - ret['framework.css'] = [`${displayPublicPath}${asset}`]; - } } return ret; } diff --git a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts index 5a27b4930d7f..f5d0100af5bf 100644 --- a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts +++ b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts @@ -1,4 +1,5 @@ import crypto from 'crypto'; +import type webpack from '@umijs/bundler-webpack/compiled/webpack'; import { IApi } from '../../types'; export default (api: IApi) => { @@ -18,7 +19,12 @@ export default (api: IApi) => { }); }, }, - enableBy: api.EnableBy.config, + enableBy() { + if (api.env !== 'production' || !!api.config.vite) { + return false; + } + return 'codeSplitting' in api.config; + }, }); api.chainWebpack((memo) => { @@ -114,7 +120,6 @@ export default (api: IApi) => { priority: 30, minChunks: 1, reuseExistingChunk: true, - chunks: 'async', }, shared: { name(_module: any, chunks: any) { @@ -133,7 +138,6 @@ export default (api: IApi) => { .replace(/=/g, '_'); return `shared-${cryptoName}`; }, - chunks: 'async', priority: 10, minChunks: 2, reuseExistingChunk: true, @@ -146,4 +150,87 @@ export default (api: IApi) => { } return memo; }); + + // html 处理逻辑 + const assets: { js: string[]; css: string[]; [key: string]: string[] } = { + // Will contain all js and mjs files + js: [], + // Will contain all css files + css: [], + }; + + class HtmlWebpackPlugin { + apply(compiler: webpack.Compiler) { + compiler.hooks.emit.tapPromise( + 'UmiHtmlGeneration', + async (compilation) => { + const entryPointFiles = compilation.entrypoints + .get('umi')! + .getFiles(); + + // Extract paths to .js, .mjs and .css files from the current compilation + const entryPointPublicPathMap: Record = {}; + const extensionRegexp = /\.(css|js|mjs)(\?|$)/; + + const UMI_ASSETS_REG = { + js: /^umi(\..+)?\.js$/, + css: /^umi(\..+)?\.css$/, + }; + + entryPointFiles.forEach((entryPointPublicPath) => { + const extMatch = extensionRegexp.exec(entryPointPublicPath); + // Skip if the public path is not a .css, .mjs or .js file + if (!extMatch) { + return; + } + + if (entryPointPublicPath.includes('.hot-update')) { + return; + } + + // Skip if this file is already known + // (e.g. because of common chunk optimizations) + if (entryPointPublicPathMap[entryPointPublicPath]) { + return; + } + + // umi html 默认会注入 不做处理 + if ( + UMI_ASSETS_REG.js.test(entryPointPublicPath) || + UMI_ASSETS_REG.css.test(entryPointPublicPath) + ) { + return; + } + + entryPointPublicPathMap[entryPointPublicPath] = true; + // ext will contain .js or .css, because .mjs recognizes as .js + const ext = extMatch[1] === 'mjs' ? 'js' : extMatch[1]; + assets[ext].push(entryPointPublicPath); + }); + }, + ); + } + } + + api.modifyWebpackConfig((config) => { + config.plugins?.push(new HtmlWebpackPlugin()); + return config; + }); + + api.addHTMLStyles(() => { + const { publicPath } = api.config; + const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; + return assets.css.map((css) => { + return `${displayPublicPath}${css}`; + }); + }); + + api.addHTMLHeadScripts(() => { + const { publicPath } = api.config; + const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; + + return assets.js.map((js) => { + return `${displayPublicPath}${js}`; + }); + }); }; From 94139fbab3356c9ecaf187a23714b3ac60ce33f1 Mon Sep 17 00:00:00 2001 From: xierenyuan Date: Thu, 24 Nov 2022 21:34:16 +0800 Subject: [PATCH 2/4] feat(preset-umi): codeSplitting config update --- packages/preset-umi/src/features/codeSplitting/codeSplitting.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts index f5d0100af5bf..7cbf58ee79f4 100644 --- a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts +++ b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts @@ -120,6 +120,7 @@ export default (api: IApi) => { priority: 30, minChunks: 1, reuseExistingChunk: true, + chunks: 'async', }, shared: { name(_module: any, chunks: any) { @@ -141,6 +142,7 @@ export default (api: IApi) => { priority: 10, minChunks: 2, reuseExistingChunk: true, + chunks: 'async', }, }, }); From 86fee3402707c2345c8440f7f2ebfc910c72b8aa Mon Sep 17 00:00:00 2001 From: xierenyuan Date: Fri, 25 Nov 2022 18:24:20 +0800 Subject: [PATCH 3/4] feat(preset-umi): add custom htmlWebpackPlugin --- .../features/codeSplitting/codeSplitting.ts | 91 +----------------- .../src/features/webpack/webpack.ts | 92 +++++++++++++++++++ packages/preset-umi/src/index.ts | 1 + 3 files changed, 94 insertions(+), 90 deletions(-) create mode 100644 packages/preset-umi/src/features/webpack/webpack.ts diff --git a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts index 7cbf58ee79f4..b513e75f939a 100644 --- a/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts +++ b/packages/preset-umi/src/features/codeSplitting/codeSplitting.ts @@ -1,5 +1,4 @@ import crypto from 'crypto'; -import type webpack from '@umijs/bundler-webpack/compiled/webpack'; import { IApi } from '../../types'; export default (api: IApi) => { @@ -19,12 +18,7 @@ export default (api: IApi) => { }); }, }, - enableBy() { - if (api.env !== 'production' || !!api.config.vite) { - return false; - } - return 'codeSplitting' in api.config; - }, + enableBy: api.EnableBy.config, }); api.chainWebpack((memo) => { @@ -152,87 +146,4 @@ export default (api: IApi) => { } return memo; }); - - // html 处理逻辑 - const assets: { js: string[]; css: string[]; [key: string]: string[] } = { - // Will contain all js and mjs files - js: [], - // Will contain all css files - css: [], - }; - - class HtmlWebpackPlugin { - apply(compiler: webpack.Compiler) { - compiler.hooks.emit.tapPromise( - 'UmiHtmlGeneration', - async (compilation) => { - const entryPointFiles = compilation.entrypoints - .get('umi')! - .getFiles(); - - // Extract paths to .js, .mjs and .css files from the current compilation - const entryPointPublicPathMap: Record = {}; - const extensionRegexp = /\.(css|js|mjs)(\?|$)/; - - const UMI_ASSETS_REG = { - js: /^umi(\..+)?\.js$/, - css: /^umi(\..+)?\.css$/, - }; - - entryPointFiles.forEach((entryPointPublicPath) => { - const extMatch = extensionRegexp.exec(entryPointPublicPath); - // Skip if the public path is not a .css, .mjs or .js file - if (!extMatch) { - return; - } - - if (entryPointPublicPath.includes('.hot-update')) { - return; - } - - // Skip if this file is already known - // (e.g. because of common chunk optimizations) - if (entryPointPublicPathMap[entryPointPublicPath]) { - return; - } - - // umi html 默认会注入 不做处理 - if ( - UMI_ASSETS_REG.js.test(entryPointPublicPath) || - UMI_ASSETS_REG.css.test(entryPointPublicPath) - ) { - return; - } - - entryPointPublicPathMap[entryPointPublicPath] = true; - // ext will contain .js or .css, because .mjs recognizes as .js - const ext = extMatch[1] === 'mjs' ? 'js' : extMatch[1]; - assets[ext].push(entryPointPublicPath); - }); - }, - ); - } - } - - api.modifyWebpackConfig((config) => { - config.plugins?.push(new HtmlWebpackPlugin()); - return config; - }); - - api.addHTMLStyles(() => { - const { publicPath } = api.config; - const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; - return assets.css.map((css) => { - return `${displayPublicPath}${css}`; - }); - }); - - api.addHTMLHeadScripts(() => { - const { publicPath } = api.config; - const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; - - return assets.js.map((js) => { - return `${displayPublicPath}${js}`; - }); - }); }; diff --git a/packages/preset-umi/src/features/webpack/webpack.ts b/packages/preset-umi/src/features/webpack/webpack.ts new file mode 100644 index 000000000000..34d4e6232ae6 --- /dev/null +++ b/packages/preset-umi/src/features/webpack/webpack.ts @@ -0,0 +1,92 @@ +import type webpack from '@umijs/bundler-webpack/compiled/webpack'; +import { IApi } from '../../types'; + +export default (api: IApi) => { + api.describe({ + key: 'preset-umi:webpack', + }); + + // html 处理逻辑 + const assets: { js: string[]; css: string[]; [key: string]: string[] } = { + // Will contain all js and mjs files + js: [], + // Will contain all css files + css: [], + }; + + class HtmlWebpackPlugin { + apply(compiler: webpack.Compiler) { + compiler.hooks.emit.tapPromise( + 'UmiHtmlGeneration', + async (compilation) => { + const entryPointFiles = compilation.entrypoints + .get('umi')! + .getFiles(); + + // Extract paths to .js, .mjs and .css files from the current compilation + const entryPointPublicPathMap: Record = {}; + const extensionRegexp = /\.(css|js|mjs)(\?|$)/; + + const UMI_ASSETS_REG = { + js: /^umi(\..+)?\.js$/, + css: /^umi(\..+)?\.css$/, + }; + + entryPointFiles.forEach((entryPointPublicPath) => { + const extMatch = extensionRegexp.exec(entryPointPublicPath); + // Skip if the public path is not a .css, .mjs or .js file + if (!extMatch) { + return; + } + + if (entryPointPublicPath.includes('.hot-update')) { + return; + } + + // Skip if this file is already known + // (e.g. because of common chunk optimizations) + if (entryPointPublicPathMap[entryPointPublicPath]) { + return; + } + + // umi html 默认会注入 不做处理 + if ( + UMI_ASSETS_REG.js.test(entryPointPublicPath) || + UMI_ASSETS_REG.css.test(entryPointPublicPath) + ) { + return; + } + + entryPointPublicPathMap[entryPointPublicPath] = true; + // ext will contain .js or .css, because .mjs recognizes as .js + const ext = extMatch[1] === 'mjs' ? 'js' : extMatch[1]; + assets[ext].push(entryPointPublicPath); + }); + }, + ); + } + } + + api.modifyWebpackConfig((config) => { + // 处理 代码拆分时, 拆分的 非 入口文件, 自动注入到 html 文件中 + config.plugins?.push(new HtmlWebpackPlugin()); + return config; + }); + + api.addHTMLStyles(() => { + const { publicPath } = api.config; + const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; + return assets.css.map((css) => { + return `${displayPublicPath}${css}`; + }); + }); + + api.addHTMLHeadScripts(() => { + const { publicPath } = api.config; + const displayPublicPath = publicPath === 'auto' ? '/' : publicPath; + + return assets.js.map((js) => { + return `${displayPublicPath}${js}`; + }); + }); +}; diff --git a/packages/preset-umi/src/index.ts b/packages/preset-umi/src/index.ts index 86336f57fd57..717cc8b8e5da 100644 --- a/packages/preset-umi/src/index.ts +++ b/packages/preset-umi/src/index.ts @@ -41,6 +41,7 @@ export default () => { require.resolve('./features/clickToComponent/clickToComponent'), require.resolve('./features/legacy/legacy'), require.resolve('./features/classPropertiesLoose/classPropertiesLoose'), + require.resolve('./features/webpack/webpack'), // commands require.resolve('./commands/build'), From 9700b670ace3cb0d40e3a69ad70163993a136747 Mon Sep 17 00:00:00 2001 From: xierenyuan Date: Fri, 2 Dec 2022 16:43:14 +0800 Subject: [PATCH 4/4] feat(preset-umi): dynamic loading of chunk is only enabled for production --- packages/preset-umi/src/features/webpack/webpack.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/preset-umi/src/features/webpack/webpack.ts b/packages/preset-umi/src/features/webpack/webpack.ts index 34d4e6232ae6..a97a7d73cd9b 100644 --- a/packages/preset-umi/src/features/webpack/webpack.ts +++ b/packages/preset-umi/src/features/webpack/webpack.ts @@ -4,6 +4,7 @@ import { IApi } from '../../types'; export default (api: IApi) => { api.describe({ key: 'preset-umi:webpack', + enableBy: () => api.env === 'production', }); // html 处理逻辑