缩小文件的搜索范围
优化loader配置
有三个配置项来缩⼩loader的处理范围:
- include:引入符合以下任何条件的模块,也就是说去哪些个模块搜索精准搜索(官方推荐使用)
- exclude:排除所有符合条件的模块
include和exclude可以是字符串也可以是数组,甚至还可以是函数、正则及对象。
示例:
include: path.resolve(__dirname, "./src"),
include: [
path.resolve(__dirname, 'app/styles'),
path.resolve(__dirname, 'vendor/styles'),
],
resolve
resolve.alias
resolve.alias配置通过别名来将原导⼊路径映射成⼀个新的导⼊路径。
resolve: {
alias: {
"@": path.resolve(__dirname, "./src/"),
}
}
注意: 在html、css中使用的时候,需要加上~
background: url(~@/imgs/1.jpg); // 注意不要加引号
js中:
import '@/styles/index.less';
resolve.modules
resolve.modules⽤于配置webpack去哪些⽬录下去寻找第三⽅模块,默认是在当前项⽬⽬录下的node_modules⾥⾯去找,如果没有找到,就会去上⼀级⽬录的node_modules找,再没有会去上上级目录的node_modules中找,以此类推,和Node.js的模块寻找机制很类似。
如果我们的第三⽅模块都安装在了项⽬根⽬录下,就可以直接指明这个路径。
module.exports={
xxxxx,
resolve:{
// 定义第三方依赖的位置,支持单个和多个
// modules: path.resolve(__dirname, "./node_modules")
modules: [path.resolve(__dirname, "./node_modules")]
}
}
resolve.extensions
extensions在导⼊语句但没带后缀时,webpack会⾃动带上后缀后,去尝试查找⽂件是否存在。默认有.js
、.json
。
extensions: ['.js', '.json', '.ts', '.jsx']
注意:
- 这个列表的值越多,需要匹配的时间就越久,因为会为每一个省略后缀的文件都挨个加上后缀,然后再去查找是否存在,所以尽量都带上后缀。
- 加入同一个目录下同时有a.js和a.ts文件,当省略了后缀的时候,系统会从左往右依次找寻,找到了满足条件的a.js就结束了不再继续往后匹配,即使a.ts也满足。
压缩html
new htmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
minify: { // 压缩
removeComments: true, // 去掉注释
collapseWhitespace: true, // 删除换⾏符与空⽩符
minifyCSS: true // 压缩内联的css
}
}),
分离css文件
mini-css-extract-plugin
之前我们说到了,style-loader是通过js动态生成css直接打包进js⾥的,但是我们希望能单独生成css文件,因为这样就可以和js并行下载提高页面加载效率,缺点就是会增加请求。
下载
npm i mini-css-extract-plugin -D
引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
配置使用
module.exports = {
module: {
rules: [
// 打包 css
{
// test 用于配置当前打包规则要匹配的文件名
test: /\.less$/,
// use 用于配置当前打包规则所使用的 loader
// 使用MiniCssExtractPlugin.loader来替代style-loader
// 但是需要注意的是,抽离了css成文件夹之后,引用层级问题,需要使用../
// use: [ MiniCssExtractPlugin.loader, 'css-loader', "postcss-loader", 'less-loader'],
use: [ {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}, 'css-loader', "postcss-loader", 'less-loader'],
// include用于引入符合以下任何条件的模块
include: path.resolve(__dirname, './src')
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name]_[contenthash:4].css",
chunkFilename: "[id].css"
})
]
}
压缩css
- cssnano:是一个基于node开发的缩减器,也 是一个 postcss插件,可以添加到构建流程中,用于确保最终生成的用于生产环境的 CSS 样式表文件尽可能的小。
- optimize-css-assets-webpack-plugin
安装:
// webpack4.x版本就需要使用这两个的4.0版本,否则cssnano.process会报错
npm i optimize-css-assets-webpack-plugin@4.0.0 cssnano@4.0.0 -D
引入:
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
使用:
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/g, // 此插件压缩的对象是由mini-css-extract-plugin插件输出的css文件,而不是css源文件
cssProcessor: require("cssnano"), // 压缩css的处理器,返回promise对象
cssProcessorOptions: { // 传递给cssProcessor的配置对象
// 移除所有的空格和引号
discardComments: { removeAll: true }
},
canPrint: true // 配置插件是否可以将消息打印到控制台
})
tree Shaking清除无用css、js
Tree Shaking 通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code),依赖于 ES2015 模块语法的静态解构特性,如import和export。这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。webpack 4 ,通过 package.json
的 "sideEffects"
属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯正的ES2015 模块)",由此可以安全地删除文件中未使用的部分。
注意:只有mode是production才会⽣效,develpoment的tree shaking是不⽣效的,因为webpack为了⽅便我们调试。
css tree shaking
安装:
npm i purify-css purifycss-webpack glob-all -D
使用:
const PurifyCSS = require('purifycss-webpack');
const glob = require('glob-all');
plugins: [
// xxxxx
new PurifyCSS({ // 清除⽆⽤ css
paths: glob.sync([
// 匹配要清除的路径⽂件
path.resolve(__dirname, './src/*.html'), // 我们也需要对html⽂件进⾏清除
path.resolve(__dirname, './src/*.js')
])
})
],
JS tree shaking
注意:只⽀持import⽅式引⼊,不⽀持commonjs的⽅式引⼊,所以需要确保没有编译器将ES6模块语法转换为 CommonJS 。
//webpack.config.js
optimization: {
usedExports: true // 哪些导出的模块被使⽤了,再做打包
}
sideEffects
如果所有代码都不包含 side effect,可以简单地将该属性标记为 false
,来告知 webpack,它可以安全地删除未用到的 export。
// package.json中:
"sideEffects":false //对所有模块进⾏tree shaking , 仅⽣产模式有效,需要配合usedExports
但是这样所有导入文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似 css-loader
并 import 一个 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除。也就是说,如果代码确实有一些副作用,可以改为提供一个数组:
// package.json中:
"sideEffects": [
"**/*.css",
"**/*.scss",
"./esnext/index.js",
"./esnext/configure.js"
],
作⽤域提升
作⽤域提升Scope Hoisting是webpack通过ES6语法的静态分析,分析出模块之间的依赖关系,尽可能地把模块放到同⼀个函数中。从而可以让打包出来的代码⽂件更⼩运⾏更快。
用法:
optimization: {
concatenateModules: true // 开启Scope Hoisting
}
作用:
例如:
// a.js
export default '嘿嘿嘿';
// index.js
import a from './a.js';
console.log(a);
配置了Scope Hoisting之后,打包之后我们可以发现a.js和index.js的内容合并在一起了。
代码切割
split-chunks-plugin
当我们打包完成后,只生成一个bundleJs,这个时候就可能代码体积过大,下载时间需要也长。webpack中提供了⼀种⽅便的⽅法供我们实现代码分割:
配置项说明:
optimization: {
splitChunks: {
chunks: 'all',// async异步(默认) initial同步 all所有的模块有效
minSize: 20000,//最⼩尺⼨,当模块⼤于20kb
maxSize: 0,//对模块进⾏⼆次分割时使⽤,不推荐使⽤
minChunks: 1,//打包⽣成的chunk⽂件最少有⼏个chunk引⽤了这个模块
maxAsyncRequests: 30,//最⼤异步请求数,默认5
maxInitialRequests: 30,//最⼤初始化请求数,默认3
automaticNameDelimiter: '-',//打包分割符号
name: true,//打包后的名称
cacheGroups: {//缓存组
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
name: "defaultVendors", // 要缓存的、分隔出来的chunk名称
priority: -10,//缓存组优先级 数字越⼤,优先级越⾼
reuseExistingChunk: true//是否重⽤该chunk
},
other: {
chunks: "initial", // initial| all | async(默认)
test: /react|lodash/, // 正则规则验证,如果符合就提取chunk,
name: "other",// 要缓存的、分隔出来的chunk名称
minSize: 20000,//最⼩尺⼨,当模块⼤于20kb
minChunks: 1,//打包⽣成的chunk⽂件最少有⼏个chunk引⽤了这个模块
},
default: {
minChunks: 2,//打包⽣成的chunk⽂件最少有⼏个chunk引⽤了这个模块
priority: -20,//缓存组优先级 数字越⼤,优先级越⾼
reuseExistingChunk: true//是否重⽤该chunk
}
}
}
}
帮我们⾃动做代码分割的简洁方式:
optimization:{
splitChunks:{
chunks:"all"
}
}
压缩图片
安装:(推荐使用cnpm安装,使用yarn和npm安装依赖下载不完全)
cnpm install image-webpack-loader -D
使用:
rules: [{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
},
],
}]
注意事项:
-
一些OSX系统可能会报错:
Module build failed: Error: dyld: Library not loaded: /usr/local/opt/libpng/lib/libpng16.16.dylib
这个时候,需要翻墙安装libpng
brew install libpng
-
如果报:
Cannot find module 'mozjpeg'
、Cannot find module gifsicle
等模块,是下载依赖不完全,删除node_modules,使用cnpm i
重新下载依赖。