基本概念与配置
-
什么是loader?什么是plugin
loader
是模块转换器,使wenbpack
拥有加载和解析非js文件的能力,是在module.rules
中进行配置plugin
可以扩展webpack
的功能,使得webpack
更加灵活。可以在构建的过程中通过webpack
的api
改变输出的结果,在plugins
中进行配置
-
module, chunk, bundle
module
是开发中的单个模块,我们直接写出来的是module
chunk
是指webpack
在进行模块的依赖分析的时候,代码分割出来的代码块,是由多模块合并而成的,如entry
,import()
,splitChunk
bundle
是由webpack
打包出来的文件,最后生成浏览器可以直接运行的bundle
-
常见的loader与plugins
babel-loader
:可以将ES6代码转化为ES5代码vue-loader
:解析vue代码css-loader
:加载css,支持模块化,压缩,文件导入style-loader
:将css代码注入到js中,通过dom加载cssfile-loader
:文件的解析,在代码中通过相对url引入文件url-loader
:与file-loader类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
HtmlWebpackPlugin
:简化了HTML文件的创建;使用模板,通过webpack生成html文件,并为html文件引入外部资源CleanWebpackPlugin
:在进行打包之前清空原来文件的打包内容MiniCssExtractPlugin
:抽离压缩css文件webpack.HotModuleReplacementPlugin
:热更新插件ParalleUglifyPlugin
:多进程打包js文件
-
webpack 构建流程
初始化参数
,将配置文件和shell语句中的参数进行合并,得到最后的参数开始编译
:用得到的参数初始化Compiler对象,加载所有配置的插件,执行对象的run方法开始编译确定入口
:根据entry找到所有入口文件编译模块
:从入口文件出发,调用所有的loader对模块进行编译,且对模块所依赖的模块进行编译完成模块编译
:得到每个模块编译后的内容和依赖关系输出资源
:根据模块之间的依赖关系,组装成一个个包含多个模块的chunk,再把每个chunk转换成一个单独的文件(这里是修改输出的最后机会)输出完成
:确定输出的路径和文件名,把内容写到文件系统中
-
模块热更新
- 自动刷新: 整个网页全部刷新,速度较慢,且会丢失状态
- 热更新使得新代码生效,网页不刷新,状态不丢失
- 只在开发环境下使用,不要在生产环境中使用
- 通过配置
new webpack.HotModuleReplacementPlugin()
实现热更新
-
懒加载
- 使用
import
语法实现懒加载,对比vue,react中路由及组件懒加载
- 使用
-
多页面打包配置
- 修改
enter
入口:将entry修改为多个入口 - 修改output的输出:
filename: '[name].[contentHash:8].js'
- 创建
HtmlWebpackPlugin
, 也可以通过js来进行动态push到plugins - 也可以使用webpack的
AutoWebPlugin
来完成自动化构建
- 修改
-
公共代码提取
- 使用
optimization.splitChunk
进行公共代码提取
splitChunks: { // 分割代码块(多页应用才会用到) cacheGroups: { //缓存组 common: { // 公共的模块 chunks: "initial", // 从开始处抽离,有多种配置,像异步模块什么的 minSize: 0, // 最小大小 minChunks: 2 // 引用次数 }, vendor: { // 此处为了抽离第三方的公共模块,比如jquery(前提是index和other都引入jquery了) priority: 1, //权重, 如果不给这个字段,那么就此例来说,会先走上边的“common”,会把jquery和a.js,b.js合并在一个文件中。 //如果还有别的入口只使用jquery了,但是a和b对于它来说就是无用的。加上权重之后,会将第三方模块单独抽离 test: /node_modules/, minSize: 0, // 最小大小 chunks: "initial", minChunks: 2 // 引用次数 } } }
- 使用
-
DllPlugin动态链接库插件
- 使用场景:有依赖包较大时,因依赖包不常改动(一般基本不会去改),如:
react
,axios
,antd
等,如果不将其分离打包,则每次打包时均会被打包,影响打包速度 DllPlugin
——打包出dll
文件DllReferencePlugin
——使用dll
文件
- 配置
webpack.dll.js
,将第三方模块单独进行打包,生成一个dll
的打包结果,所有第三方模块都在这里 - 通过
library
将第三方模块通过全局变量的方式暴露出去 - 借助
dllPlugin
对暴露的模块进行代码分析生成mainfest.json
文件,当发现引入lodash
或者jquery
就会从打包好的库的拿去,如果没有才从node_modules
中取模块进行打包 AddAssetWebpackPlugin
是将打包生成的库文件引入到html
文件中,并导出全局变量vendor
new AddAssetWebpackPlugin({ // 将path.resolve(__dirname, '../dll/render.dll.js')静态资源文件引入html中 filepath: path.resolve(__dirname, '../dll/render.dll.js') }), new webpack.DllReferencePlugin({ // 当发现引入lodash或者jquery就会从打包好的库的拿去,如果没有才从node_modules中取模块进行打包 mainfest: this.resolve(__dirname, '../dll/vendors.mainfest.json') }) // webpack.dll.js let path = require('path'); let webpack = require('webpack'); module.exports = { entry: { vendors: ['lodash', 'jquery'] }, output: { filename: '[name].dll.js', path: path.resolve(__dirname, '../dll'), library: '[name]' }, plugins: [ new webpack.DllPlugin({ // 生成打包分析文件 name: '[name]', path: path.resolve(__dirname, '../dll/[name].mainfest.json') }) ] }
- 使用场景:有依赖包较大时,因依赖包不常改动(一般基本不会去改),如:
-
抽离压缩css代码
MiniCssExtractPlugin
对css文件进行代码分割,OptimizeCSSAssetsPlugin
对css代码进行压缩
{ test:/\.less$/, loader: [ MiniCssExtractPlugin.loader, // 为css提取独立的文件的插件,不使用style-loader 'css-loader', 'less-loader' ] } plugins: [ // 如果css文件被页面直接引用那么会走filename,如果被页面间接引用,会走chunkFilename new MiniCssExtractPlugin({ filename: '[name].[contentHash:8].css', chunkFilename: '[id].css', }) ] // 对css代码进行压缩 optimization: { minimizer: [new OptimizeCSSAssetsPlugin({})], }
-
webpack-dev-server和http服务器如nginx有什么区别?
- webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效。
性能优化
-
优化产出代码
- 小图片进行base64编码
bundle
加hash
- 懒加载
- 提取公共代码
- 使用cdn加速(可以将静态文件之类的放于cdn)
IgnorePlugin
- 使用
production
(该模式下,会进行代码压缩,tree-shaking
[将没用的代码删除],scope-hosting
[作用域提升])
-
webpack优化构建速度(生产环境)
- 优化
babel-loader
(加缓存,加hash) noParse
(不去解析属性值代表的库的依赖)IgnorePlugin
(忽略本地化内容,如引入了一个插件,只用到了中文语言包,打包的时候把非中文语言包排除掉)happyPack
(多进程进行打包)parallelUglifyPlugin
(多进程打包js,压缩,优化js)
- 优化
-
webpack优化构建速度(开发环境)
- 自动刷新,热更新
DllPlugin
-
为何要进行打包和构建
- 体积更小(
tree-shaking
, 压缩,合并), 加载更快 - 编译高级语言和语法
- 兼容性和错误检查(
postcss
,eslint
)
- 体积更小(