公共库提取
在打包多个页面时,他们会共享一些公共的代码,比如:React、React-DOM 等,默认 webpack 的每个 entry 会把这些依赖的代码都打包到 index.js 文件中去,这就导致如果用户访问了多个这些页面,公共库的代码其实是重复加载的。所以一般会把多页面公用的类库单独提取出来打包成一个 js 文件。
目标
把公共库单独提取出来打包成一个 js 文件,并且把这个 js 文件引入到所有页面中。
提取 shared lib
首先给 webpack 指定一个公共库的 entry:
scripts/getScreens.js#createEntries
...
const createEntries = (screens) => {
/** @type {import('webpack').EntryObject} */
const entryData = {};
entryData['shared'] = ['react', 'react-dom'];
...
};
然后给每个 entry 添加dependOn
以指定公共库依赖,给 HtmlWebpackPlugin 实例的 chunks 添加shared
的 entry:
scripts/getScreens.js#createEntries
const createEntries = (screens) => {
/** @type {import('webpack').EntryObject} */
const entryData = {};
entryData['shared'] = ['react', 'react-dom'];
/** @type {Array<import('html-webpack-plugin')>} */
const htmlEntries = [];
screens.forEach((screen) => {
const screenNameIndex = screen.entryJs.indexOf('screen/');
const entryFileNameBaseDist = screen.entryJs
.substring(screenNameIndex)
.replace(/\.js$/, '');
entryData[entryFileNameBaseDist] = {
import: [screen.entryJs],
filename: '[name].js',
dependOn: ['shared'],
};
htmlEntries.push(
new HtmlWebpackPlugin({
chunks: ['shared', entryFileNameBaseDist],
filename: `${entryFileNameBaseDist}.html`,
template: screen.entryHtml,
})
);
});
return { entryData, htmlEntries };
};
执行下npm run dev
,就会发现 dist 下多了一个 shared.js 文件,并且在 index.html 中引入了 shared.js。
预加载公共配置文件
项目中一般会在各个页面预加载公共配置文件,比如全局配置,全局 css 等等,这就需要在每个 entry 入口文件里都要引用一下这个公共配置,不过我们不想在每个 entry 入口文件里引入,而是通过 webpack 把这个公共文件引入到 entry 中。
首先创建一个公共文件:
src/autoload.ts
console.log('autoload');
修改 getScreens.js:
scripts/getScreens.js@createEntries
const createEntries = (screens) => {
/** @type {import('webpack').EntryObject} */
const entryData = {};
entryData['shared'] = ['react', 'react-dom'];
/** @type {Array<import('html-webpack-plugin')>} */
const htmlEntries = [];
const autoloadFile = path.resolve(__dirname, '../tsc_outputs/src/autoload.js');
screens.forEach((screen) => {
const screenNameIndex = screen.entryJs.indexOf('screen/');
const entryFileNameBaseDist = screen.entryJs
.substring(screenNameIndex)
.replace(/\.js$/, '');
entryData[entryFileNameBaseDist] = {
import: [autoloadFile, screen.entryJs],
dependOn: ['shared'],
};
htmlEntries.push(
new HtmlWebpackPlugin({
chunks: ['shared', entryFileNameBaseDist],
filename: `${entryFileNameBaseDist}.html`,
template: screen.entryHtml,
})
);
});
return { entryData, htmlEntries };
};
执行下npm run dev
,启动 web 服务打开页面,会发现页面会 console.log 出来 autoload。