webpack5 文档 webpack.docschina.org/concepts/#e…
十六、优化16:将npm的依赖打成公共的vendor
// ... existing code ...
optimization: {
// ... existing optimization settings ...
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 中的所有依赖
name: 'vendor', // 输出的文件名称
chunks: 'all', // 适用于所有类型的 chunk
},
minSize: 0, // 最小大小为 0,确保打包所有的 chunk
reuseExistingChunk: true, // 重用已存在的 chunk
},
},
},
十七、难点亮点17: 对vendor打包的进一步优化
vendor还可以继续分类。
按需加载的vendor1分一个类型(and)
全量打包的vendor2划分一个类型(react redux)
十八、极致优化18: reuseExistingChunk复用已存在的chunk
对npm的依赖,有使用到的相同代码进行进一步复用。
遇到了什么问题: npm的依赖可能有相同的代码
解决思路: 公共部分抽离复用
怎么解决的:reuseExistingChunk 配置
十九、优化19: webpack5带来的编译优化
webpack首次打包都很慢,从头编译
利用缓存。
webpack5新版本默认是带缓存的。
编译时间:从60s=>1s
我们以前是基于webpack4的,webpack4没有这个特性,所有编译很慢
面试官追问:webpack4可以缓存吗?
可以利用插件,但是不是原生的。性能不如webpack5要好
二十、优化20:Tree shaking树摇,删除多余代码
- 删除没用到的模块
- 要用es6 module
追问?
你的webpack怎么配置tree shaking?
1.usedExports
优化(Optimization) | webpack 中文文档
2.sideEffects
SideEffect就是手动指定告诉webpack哪些模块肯定是es6,你放心的删除没用用到的模块, 如果没使用配置sideEffect,可能有些代码删不掉。
二十一、优化21: ts编译是存在瓶颈,使用多线程来优化
Ts-loder
使用ForkTsCheckerwebpackPlugin插件来开启ts的多线程编译
module: {
rules: [
// ... existing rules
{
test: /\.(ts|tsx)$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true, // 只进行转译,不进行类型检查
// 可能还有其他选项,但图片中未显示
},
exclude: /node_modules/, // 排除node_modules目录中的文件
},
// 可能还有其他loader,但图片中未显示
],
// 可能还有其他规则配置,但图片中未显示
},
// ... other existing rules
],
plugins: [
// ... existing plugins
new ForkTsCheckerWebpackPlugin({
async: true, // 启用异步检查
typescript: {
configFile: './tsconfig.json', // 指定tsconfig文件
// 可能还有其他typescript配置,但图片中未显示
},
// 可能还有其他插件配置,但图片中未显示
}),
// ... other existing plugins
],
// 可能还有其他module配置,但图片中未显示
},
优化的时候,要结合speed插件,去观测具体优化的效果
Ts => 1s
多线程 =>2s
开启多线程本身就具有性能损耗
TS => 50s
多线程 => 15s
二十二、难点22: 如何选择哪些资源可以开启多线程优化性能。
比如: js、ts、代码的混淆(terser)输出。
比如css的编译,less-loader =>css-loader => stye-loader,互相有依赖不能开启多线程的优化
图片处理:可能可以 图片A=>图片A1
二十三、难点亮点23: TS类型检查优化(非常推荐说这个)
项目webpack编译过程
1.ts类型检查
2.对TS进行编译
很多项目,类型检查实际上是很消耗性能
为什么可以不进行类型检查?
因为我们本地的编辑器插件可以进行检查。
在使用 ts-loader 时,可以设置 transpileOnly: true,这样 TypeScript 只会进行转译,而不进行类型检查。类型检查可以通过 ForkTsCheckerWebpackPlugin 异步进行
{
test: /\.(ts|tsx)$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true, // 只进行转译,不进行类型检查(注意:原文本中的“transpile0nly”应为“transpileOnly”)
exclude: /node_modules/ // 排除node_modules目录中的文件
// 注意:原文本中出现了“10,11”这样的数字,它们看起来像是无意义的文本或者识别错误,我在此将其忽略
}
// 注意:原文本中的排除路径重复了两次"/node_modules/",我保留了一个作为示例
}
// 注意:原文本中的use数组后面多了一个逗号,这在JavaScript对象中是无效的,我将其移除(但在提供的文本片段中由于格式问题未直接显示)
]
// 注意:原文本可能是一个对象的一部分,但我没有足够的上下文来确定是否还有其他属性或键值对
}
使用ForkTsCheckerWebpackPlugin, 对ts的类型检查在单独的进程进行
plugins: [
new ForkTsCheckerWebpackPlugin({
async: true, // 启用异步检查
typescript: {
configFile: './tsconfig.json', // 指定tsconfig文件
// 注意:原文本中的“1.,1)”看起来像是无意义的文本或者识别错误,我在此将其忽略
}
// 注意:原文本中的逗号、冒号和点可能由于识别问题而出现了错误的位置或格式,我已经进行了修正
})
// 注意:原文本中的plugins数组后面可能还有其他插件,但我没有足够的信息来确定,所以我在此保留了数组的开放格式
]
优化 tsconfig.json:
skipLibCheck:设置为 true,跳过库文件的类型检查
noEmit:在开发模式下可以设置为 true,避免生成输出文件。
incremental:启用增量编译,TypeScript 会缓存上次编译的结果。
plugins: [
new ForkTsCheckerWebpackPlugin({
async: true, // 启用异步检查
typescript: {
configFile: './tsconfig.json', // 指定tsconfig文件
// 注意:原文本中的“1.,1)”看起来像是无意义的文本或者识别错误,我在此将其忽略
}
// 注意:原文本中的逗号、冒号和点可能由于识别问题而出现了错误的位置或格式,我已经进行了修正
})
// 注意:原文本中的plugins数组后面可能还有其他插件,但我没有足够的信息来确定,所以我在此保留了数组的
]
减少类型检查的范围:
确保只在需要的文件夹中进行类型检查,避免不必要的文件,
使用 include 和 exclude 选项来限制检査的文件范围。
二十四、优化24: 组件分包到底解决的是什么问题?
const module = await import('./cpA');
最终打包的产物 Cpa.sadasdsd.js
项目有5个页面,A、B、C、D、E
不分包,加载index.asdsadsd.js 大小500k
首屏加载500k的js
A.adsds.js 100k
b.adasd.js 100k
......
二十五、难点亮点25: webpack中loader的配置优化
反面教材:
将所有的js,包括node modules中的文件内容都进行babel的编译
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
// 可能还有其他规则,但图片中的文本没有提供
]
}
// 图片中的文本有一个属性"//.",但具体内容未给出,且格式不正确,我将其忽略了
// 如果该属性是重要的,您需要根据实际上下文来补充完整的内容
};
正面教材:
const path = require('path');
module.exports = {
// 图片中的文本有一个注释"//..",但具体内容未给出,且格式看起来不完整,我将其保留了原样
// 但通常注释应该提供有意义的信息或者用于临时禁用代码,这里可能是一个占位符或者识别错误
//..,
module: {
rules: [
{
test: /\.js$/, // 用于匹配所有的.js文件
include: path.resolve(__dirname, 'src'), // 指定只包括src目录下的文件
loader: 'babel-loader' // 使用babel-loader来处理匹配到的文件
// 图片中的文本在loader属性后面有一些数字(如10, 1.1.1等),这些看起来像是无意义的文本或者识别错误
// 我已经将它们忽略了,因为它们在JavaScript对象语法中是无效的
}
// 可能还有其他规则,但图片中的文本没有提供
]
}
};
二十六、极致难点26: 极致优化webpack的模块解析时间
resolve:['js','jsx,'tsx']
import A from 'src/a'
推荐尽量准确引用的依赖
import A from 'src/a.js'
1.从src下面去寻找所有的文件,找a,找后缀是否有['js'jsx','ts'tsx"]中的一个,a.js
二十七、难点亮点27: DLL编译优化
类似操作系统的DLL文件
通用的,经常不变化的库react、redux
webpack.config.js(业务代码)
Webpack.dll.js(第三方库)
vendor.dll.js
// webpack.dll.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production',
entry: {
vendor: ['react', 'react-dom'] // 这里可以添加你需要的库
},
output: {
path: path.resolve(__dirname, 'dll'),
filename: '[name].dll.js',
library: '[name]_lib' // 这个名称会在DLL中使用
},
plugins: [
new webpack.DllPlugin({
name: '[name]_lib',
path: path.join(__dirname, 'dll', '[name]-manifest.json') // 生成的manifest文件
})
]
};
dI和前面的vendor有啥区别呢?
d只编译一次,后面没用变化就不用再编译了。
二十八、优化28: js编译开启多线程
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'thread-loader', // 注意这里可能是'thread-loader',但图片中的文本识别有误
options: {
workers: 2 // 设置工作线程的数量
}
},
// 这里可能还有其他配置,但图片中的文本没有提供完整信息
// 例如,可能还有一个使用babel-loader的规则,但图片中的文本格式混乱,无法直接还原
// 假设有一个使用babel-loader的规则,它可能看起来像这样:
/*
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
*/
// 由于图片中的文本没有提供这个规则的完整信息,所以我将它注释掉了
// 如果您确实需要这个规则,请根据您的项目配置来添加它
exclude: /node_modules/ // 这个排除规则可能属于上面的babel-loader规则,但在这里被错误地放置了
}
// 注意:图片中的数字(如1, 10, 11, 12, 13等)和逗号可能是识别错误或占位符,我已经根据上下文进行了适当的删除和整理
]
}
};
开多线程,一定要谨慎,要配和speed插件,看是否真的提升了。
开多线程,自身消耗也不小。
二十九、细节优化29: 删除webpack的进度条显示
微乎其微的提升。
将 ProgressPlugin 从 webpack 中删除可以缩短构建时间。请注意,ProgressPlugin 可能不会为快速构建 提供太多价值,因此请权衡利弊再使用。
三十、优化30: 在webpack中避免在开发环境使用生产环境才需要的内容
- TerserPlugin 代码压缩
- [chunkhash]/[contenthash]