提升开发体验
-
使用Webpack进行打包后js文件,是经过编译的代码,看起来很不直观,不方便开发人员进行检查和纠错
-
可以使用SourceMap(源代码映射)进行优化
js
// 开发模式下配置 - 只有行映射,更省时
devtool:"cheap-module-source-map"
// 生产模式下配置 - 包含行列映射,更精准
devtool:"source-map"
提升打包速度
-
开发时修改了其中一个模块的代码,Webpack默认会全部重新打包编译,速度很慢
-
可以使用HotModuleReplacement(HMR/热模块替换),在程序中替换、添加或删除模块,不用全量重载
js
// devServer配置 - 默认对css起作用,js不起作用
hot: true
// js支持hot
if (module.hot) {
module.hot.accept("./js/count", function (count) {
console.log(count);
}) // 配置支持hot的js,第二个参数是模块内容变化后的处理逻辑,可以去掉
}
include、exclude
- 配置包含和排除的文件,提升处理效率,只能配置一种
js
// 只处理src文件夹下的文件
include: path.resolve(__dirname, '../src')
// 排除node_modules
exclude: /node_modules/,
Cashe
-
每次打包时js文件都需要经过Eslint和Babel的编译,速度较慢
-
可以缓存之前的Eslint检查和Babel的编译结果,提升打包速度
js
cacheDirectory: true, // 开启babel缓存
cacheCompression: false // 关闭缓存文件压缩
Thread多进程
-
当项目越来越庞大时,打包速度回越来越慢,js的打包涉及到eslint、babel、Teser(Webpack默认配置使用)想要提升打包速度就是提升js的打包速度
-
可以采用多进程同时处理js文件的方式来进行优化,要比单进程打包快多了
js
{
test: /\.js$/,
include: path.resolve(__dirname, "../src"),
use: [
{
loader: 'thread-loader',
options: {
works: threads
}
},
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false
}
}
]
}
plugins: [
new ESLintPlugin({
context: path.resolve(__dirname, '../src'),
cache: true,
cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'),
threads, // eslint启用多进程
})
]
optimization: {
minimizer: [
new Terser({
parallel: threads
})
]
},
Tree Shaking减少代码体积
-
开发时我们定义了一些工具函数库,或者引入第三方工具函数库或组件库,如果没有做特殊处理,打包时会引入整个库,实际上却只需要极小部分的功能
-
可以使用TreeShaking来移除Javascript中没有使用上的代码,它依赖ES Module
-
Webpack默认开启了这个配置,不需要额外操作
Babel
-
Babel为编译的每个文件都插入了辅助代码,使体积过大,Babel对一些公共方法使用了非常小的辅助代码,比如_extend。默认情况下会被添加到每一个需要它的文件中
-
可以将这些辅助代码作为一个独立模块,来避免重复引入
ImageMinimizer
-
项目引入了较多图片时,图片体积过大,未来请求速度比较慢
-
可以使用image-minimizer-webpack-plugin 对图片进行压缩,减少图片体积
shell
npm i image-minimizer-webpack-plugin -D
npm i imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
Code Split优化代码运行性能
-
打包代码会将所有的js文件打包到一个文件中,体积太大了。
-
可以对将打包生成的文件进行代码分割,生成多个js文件,渲染哪个页面,只加载某个js文件,这样加载的资源少,速度就更快。
-
多入口
js
entry: {
app: './src/app.js',
main: './src/app.js',
},
output: {
path: undefined, // 开发模式没有输出
filename: '[name].js', // webpack命名方式,【name】为文件配置名称
},
- 提取公共模块
js
optimization: {
splitChunks: {
chunks: "all"
}
}
cacheGroups: {
default: {
minSize: 0,
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
}
}
- 按需加载动态引入 - 路由懒加载就是这样实现的
javascript
// 修改引入方式,会把引入的js文件切割成单独的文件,按需加载
import('./count')
.then(module =>
// 加载成功
console.log(module);
)
.catch(error =>
// 加载失败
)
- 给模块命名
javascript
// 使用webpack魔法命名
import(/* webpackChunkName: "xxx" */ './count')
.then(module =>
// 加载成功
console.log(module);
)
.catch(error =>
// 加载失败
)
// webpack配置文件
output: {
chunkFilename: "static/js/[name].js" // 必须和webpack魔法命名保持一致
}
- 统一命名配置
js
filename: 'static/js/[name].js' // 最重要的是[name].js
// 资源类文件统一地址
assetModuleFilename: 'static/media/[hash:10][ext][query]'
Preload(立即加载资源)/ Prefetch(浏览器空闲时才开始加载资源)
-
共同点是只加载不执行,但是兼容性有问题,具体可以查询插件官网
-
一般使用Prefetch比较,但是兼容性问题太严重了,所以酌情使用
Network Cache
-
js文件最终编译打包为多个文件,文件相互以来会导致编译时未变化的js文件也重新编译,因为文件名称内的hash值变化了
-
可以使用runtimeChunk进行hash名称的记录,未变化的js文件不再次参与编译
js
contentHash:10 // 配置文件hash值
optimization: {
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}.js`,
}
}
Core-js
-
babel对js的兼容性处理使用了@babel、preset-env智能预设来处理,它能将ES6的一些语法进行编译转换,比如箭头函数和...运算符等,但是如果是async函数、promise对象和数据的一些方法等,它没办法处理
-
此时可以使用core-js来做ES6以及以上API的polyfill,彻底解决兼容性问题
js
npm i core-js
// 直接引用
import "core-js";
// 按需引入
import "core-js/es/promise";
// 自动按需引入 - babel.config.js文件
presets: [
['@babel/preset-env', {
useBuiltIns: "usage",
corejs: 3
}]
],
PWA技术
-
断网后网页无法访问
-
可以采用渐进式网络应用程序,是一种类型与native app体验的Web app技术
-
其中最重要的是在离线时应用程序能够继续运行的功能,内部通过Service Workers技术实现
shell
npm i workbox-webpack-plugin -D
- 清除console.log语句的loader
js
modeule.exports = function(content) {
return content.replace(/console\.log\(.*\);?/g, "");
}
- 使用loader的this.getOptions方法时需要传入schema配置json
js
// schema.json
{
'type': 'object',
'properties': {
'author': {
'type': 'string'
}
}
addtionalProperties: false,
}
// xx-loader.js
const schema = require('./schema.json');
// 使用schema配置的规则进行验证,验证通过获取options,否则程序 会报错
const options this.getOptions(schema);
- 在资源文件的处理loader配置中添加以下语句,可以防止使用webpack默认处理,只使用指定的loader进行处理
js
{
test: /xxx/,
loader: './loaders/xxx-loader',
type: 'javascript/auto' // 添加该配置
}
- 自定义的style-loader可以实现css代码插入页面的处理,但是无法对css引入的其他资源进行处理,所以还是需要使用css-loader进行处理
js
{
test: /\.css/,
loader: ['./loaders/style-loader', 'css-loader'],
}
- 定义debug命令
js
"scripts": {
"debug": "node --inspect-brk ./node_modules/webpack-cli/bin/cli.js"
}
PS:如果有需要补充的内容,请在评论区留言
转载时请注明"来自掘金 - EvenZhu"