文件处理
webpack仅⽀持 .js .json ⽂件, 如果需要处理其他类型的文件,需要借助loader来进行解析
css
css对应的loader版本需要匹配,否则会报错: this.getOptions is not function等
npm install css-loader -D
若需要对css进行模块化打包处理,webpack无法解析css/scss/less等文件类型,需要借助css相关的loader进行解析。
首先需要安装css-loader,若是 .scss文件则还需要安装node-sass、sass-loader、sass-loader; .less文件需要安装 less-loader/less。如想对css进行进一步的优化, 则可使用到postcss-loader,postcss-loader的功能比较齐全: 可以对css进行自动化补全浏览器(autoprefixer)、压缩css文件(cssnano)等;
loader&plugin
mini-css-extract-plugin和style-laoder不可一起使用。mini-css-extract-plugin将css打包成文件以外联src进行引入,而style-loader则将css内联方式插入dom中
| loader/plugin | 作用 |
|---|---|
css-loader | 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样 |
style-loader | 把CSS以内联的方式插入到DOM中 |
sass-loader | 加载 Sass/SCSS 文件并将他们编译为 CSS,需要搭配node-sass/sass |
less-loader | 将 Less 编译为 CSS 的 loader, 需搭配less |
postcss-loader | 对css进行处理需搭配postcss,可安装postcss自身的插件去支持功能的实现 |
mini-css-extract-plugin | 将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载 |
purify-css | 删除未被使用的css,搭配purgecss-webpack-plugin |
项目优化
分析工具
进度分析 progress-bar-webpack-plugin
显示打包的进度
体积分析 webpack-bundle-analyzer
安装: npm install webpack-bundle-analyzer -D
// webpack.config.js
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); // 每个包的体积分析
plugins = [
new BundleAnalyzerPlugin()
]
耗时分析 speed-measure-webpack-plugin
安装: npm install speed-measure-webpack-plugin -D
speed-measure-webpack-plugin帮助我们分析整个打包过程中的总耗时,以及只管测量每一个loader 和每一个 plugins 构建所耗费的时间。
//webpack.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const SpeedMeasure = new SpeedMeasurePlugin();
const config = {
// webpack的所有配置配置
}
module.exports = SpeedMeasure.wrap(config);
common共用
文件清除 clean-webpack-plugin
webpack每次打包生产的文件都放在 dist 目录中,如果重新进行打包,webpack都会生成新的文件放入dist目录中,且dist目录中的旧文件不会被删除。这样会导致文件冗余。
clean-webpack-plugin就是用来帮助在每次打包时先清空dist目录,这样每次打包后dist中总是最新打包生成的文件。
加快带包速度
缓存 HardSourceWebpackPlugin
npm install hard-source-webpack-plugin -D
webpack4中需要自己进行配置,webpack5将内置此插件。HardSourceWebpackPlugin在第一次构建时写入缓存中,第二次构建可从缓存读取。加快打包速度--极速前进了
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
plugins: [ new HardSourceWebpackPlugin() ]
}
CopyWebpackPlugin
安装: npm install copy-webpack-plugin -D
CopyWebpackPlugin将单个文件或整个目录复制到构建目录
const CopyPlugin = require('copy-webpack-plugin');
// 复制文件 webpack4 匹配的是6.2.0版本,4以下及最新版报错
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, "./src/static"),
to: path.resolve(__dirname, "./dist/static"),
},
],
}),
css
删除无用代码 purifycss-webpack
安装: npm install purifycss-webpack purify-css -D
这个插件会删除你没有使用的css样式,需要注意的是 如果是多页面打包,指定paths时不要明确进行指定 避免其他页面的css被当做无效css擦除了
// webpack.config.js
const PurifyCssPlugin = require('purifycss-webpack');
const glob = require('glob');
// 删除未被使用的css 删除所有xx.html下多余css, 不需指定index.html 避免多页面打包时有效css未被打包
new PurifyCssPlugin({
paths: glob.sync(path.join(__dirname, "/*.html")),
}),
代码压缩&添加前缀
postcss实际做事的是它的插件。postcss 有自己的专属配置文件,可新建一个postcss.config.js文件配置postcss插件等信息。
-
autoprefixer: 添加了 vendor 浏览器前缀,它使用 Can I Use 上面的数据。
autoprefixer 插件指定生效浏览器范围才能生效。可设置 overrideBrowserslist 属性,去指定需要生效的浏览器范围,若不设置该属性,也可自行定义一个 .browserslistrc文件或 在package.json文件中添加 browserslist属性来指定生效浏览器范围.
-
cssnano:cssnano 是一个模块化的 CSS 压缩器,需要注意的是当前插件的版本需要与
postcss-loader一致 -
postcss-preset-env: 允许你使用未来的 CSS 特性
js
代码压缩 terser-webpack-plugin
安装: npm install terser-webpack-plugin -D
terser-webpack-plugin压缩js,删除js中的 console.log和代码注释
const TerserPlugin = require("terser-webpack-plugin");
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
minify: TerserPlugin.uglifyJsMinify,
extractComments: true,
// terserOptions的属性会被传递给TerserPlugin.uglifyJsMinify
terserOptions: {
// compress - 压缩的属性设置
compress: {
warnings: false,
drop_console: true, // 移除console.log
drop_debugger: true, // 移除debugger
pure_funcs: ["console.log"], //移除console
},
},
}),
],
},
图片/字体等
文件抽离
我们可以使用url-loader来处理图片、第三方字体等静态资源。url-loader的工作原理与file-loader一致(url-loader依赖了file-loader),只是添加了一个limit属性,若文件小于该属性值则会返回一个dataUrl。如果文件大小大于限定的limit,则会输出图片
url-loader可以自定义输出图片的名称,位置等信息
| 属性 | 功能 |
|---|---|
| name | 打包后资源文件的名称 |
| outputPath | 打包后的存放位置 |
| publiPath | 静态资源访问的基础路径 |
// webpack.config.js
rules:[{
test: /\.(png|jpe?g|gif|svg)$/,
loader: 'url-loader',
options: {
// 小于当前limit大小的文件将不会被打包,直接以base64方式引入
limit: 1024 * 3,
// 直接在name前面加一个目录名也会自动生成一个目录
name: '/img/[name].[contenthash:8].[ext]'
}
},
{
test: /\.(eot|woff|ttf)$/,
loader: 'url-loader',
options: {
limit: 1024 * 3,
name: '/fonts/[name].[contenthash:8].[ext]'
}
}]
image-webpack-loader
图片压缩,但会影响打包的速度。可现在tiny压缩网站将图片先一步进行压缩,或者将图片放置在自己的cdn上。也可以将部分图片放在static中 直接使用copy-webpack-plugin复制一份
// webpack.config.js
rules:[{
test: /\.(png|jpe?g|gif|svg)$/,
use: [{
loader: 'url-loader',
options: {
// 小于当前limit大小的文件将不会被打包,直接以base64方式引入
limit: 1024 * 3,
// 直接在name前面加一个目录名也会自动生成一个目录
name: '/img/[name].[contenthash:8].[ext]'
}
}, {
loader: 'image-webpack-loader',
options: {
// 压缩 jpeg 的配置
mozjpeg: {
progressive: true,
quality: 65
},
// 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
optipng: {
enabled: false,
},
// 使用 imagemin-pngquant 压缩 png
pngquant: {
quality: '65-90',
speed: 4
},
// 压缩 gif 的配置
gifsicle: {
interlaced: false,
},
// 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
webp: {
quality: 75
}
}
}
}]
抽离第三方模块
DllPlugin 和 DllReferencePlugin
一些第三方库是不怎么变动的静态依赖文件,比如: element-ui、vue等。如果不抽离第三方模块,这些第三方都会打包到bundle入口文件中。这将会导致入口文件的主包格外大,减缓了打包速度,也增大了主文件的体积。
我们可以使用webpack内置的DllPlugin 和 DllReferencePlugin插件,实现了拆分 bundles,同时大幅度提升了构建的速度。我们需要单独配置一个webpack.dll.js文件来处理抽离第三方模块
// webpack.dll.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
vendor: ['vue', 'vue-router', 'element-ui', 'moment', 'axios'],
},
output: {
path: path.resolve(__dirname, 'static/js'), // 打包后文件输出的位置, 再由copy复制
filename: '[name].dll.js',
// 需要和webpack.DllPlugin中的name保持一致。
library: '[name]_library'
},
performance: {
maxAssetSize: 1024 * 10000,
maxEntrypointSize: 1024 * 10000,
hints: false
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, '[name]-manifest.json'),
name: '[name]_library',
context: __dirname
})
]
};
webpack.dll.js文件配置完成后,我们需要在package.json文件中添加如下命令来生成[name]-manifest.json以供DllReferencePlugin插件使用
// package.json
script: {
"dll": "webpack --config build/webpack.dll.config.js"
}
最后还需要在webpack.base.js文件中进行配置DllReferencePlugin和CopyWebpackPlugin两个插件。将第三方文件引入index.html中
// index.html
<script src="static/js/vendor.dll.js"></script>
// webpack.base.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
}),
new CopyWebpackPlugin([{ from: 'static', to: 'static' }])
使用: 先执行npm run dll生成对用的manifest.json文件 再去进行npm run dev或者npm run build。整个使用费过程中 只需要执行一次npm run dll即可,执行完后dllPlugin已经生成了第三方模块
替代方案
autodll-webpack-plugin综合了DllPlugin 和 DllReferencePlugin的功能,精简配置。但是需要和htmlWebpackPlugin综合使用,两者的inject属性需要为true,这样生成的第三方库 vendor.js 会自动被引入html中
const path = require('path');
const AutoDllPlugin = require('autodll-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
plugins: [
new HtmlWebpackPlugin({
inject: true, // will inject the main bundle to index.html
template: './src/index.html',
}),
new AutoDllPlugin({
inject: true, // will inject the DLL bundle to index.html
debug: true,
filename: '[name]_[hash].js',
path: './dll',
entry: {
vendor: [
'react',
'react-dom'
]
}
})
]
};
开发环境
// webpack.de.config
const webpack = require('webpack');
plugins: [
new webpack.HotModuleReplacementPlugin()
]
生产环境
css
文件抽离 mini-css-extract-plugin
这个插件应该只在生产环境构建中使用!! 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载,但是并不会压缩css。此插件有匹配的一个处理css的loader(MiniCssExtractPlugin.loader)。
如果想将css打包放置目标目录下的同一个文件夹中,可将mini-css-extract-plugin插件可设置属性filename时在css的名称前添加一个目录名。
怎么为每一个js文件生一个css文件???
2.4.2版本运行报错?? "webpack": "^4.43.0",重新安装 0.9.0版本无报错
指纹策略
webpack中有三种指纹策略,使用指纹策略的情景:
项目发布的时候,用户的电脑访问没有任何变化,还是旧的样式。或者js修改完后但是无法生效的根本原因在于浏览器依然在使用缓存。浏览器的工作流程: 若是第一次访问 则先去询问服务器获取文件等数据。但是如果非第一次,浏览器将会在本地缓存中读取文件,如果服务器更新之后的文件名与上一次的文件名相同,浏览器则会优先读取本地缓存的数据。这样会网站导致更新之后但是看不到效果。为了解决这个问题,我们需要用到webpack的指纹策略,在文件名后加上 hash、 chunkhash、 contenthash 中的其中一种
| 指纹策略 | 解析 |
|---|---|
| hash | 和整个项目相关,只要项目文件改变,整个项目构建的hash值都会改变 |
| chunkhash | 和webpack打包的chunk有关,不同的entry会生成不同的chunkhash |
| contenthash | 根据文件内容来定义hash,文件内容不变,则contenthash不变 |
优化策略
构建速度
优化webpack构建的方式有很多,主要可以从优化搜索时间、缩小文件搜索范围、减少不必要的编译、多线程执行、缓存等方面入手
优化 loader 配置合理使用 resolve.extensions优化 resolve.modules优化 resolve.alias使用 DLLPlugin 插件使用 cache-loaderterser 启动多线程合理使用 sourceMaphardSourceWebpackPlugin 缓存CopyWebpackPlugin 静态文件复制
性能优化
关于webpack对前端性能的优化,可以通过各种文件体积大小入手,其次还可通过分包的形式、减少http请求次数等方式,实现对前端性能的优化
JS代码压缩CSS代码压缩Html文件代码压缩文件大小压缩图片压缩Tree Shaking代码分离内联 chunk