webpack
webpack需要了解其构建过程,以及常用的loader、plugin,热更新原理,配置等等
webpack配置大致的组成部分
- mode: prodcution、development
- entry: 入口文件
- output: 输出形式
- loaders: 加载常见的loader有 css-loader、style-loader、scss/less-loader、vue-loader
- plugin: 插件,常见的plugin:html-webpack-plugin、clean-webpack-plugin
说一下webpack的构建过程
- 初始化配置,包含命令行的参数,webpack.config.js等参数组合形成的配置数据
- 根据入口不同有不同的chunk,每一个chunk的构建过程是:
md
检查当前是否已经被依赖而构建了
将文件形成AST抽象语法树
根据AST分析出依赖文件
替换依赖函数,require换成_webpack_require,并把相对路径转为绝对路径这个过程并没有改变文件本身
保存转换后的代码,并添加到依赖表中去,表中key为chunkname,value是转换后的文件
根据依赖表循环以上过程,直到文件没有依赖或者都已经构建过了的依赖
完成后生成当前的chunkid、chunkname、hash
- 多个chunk包,合并生成bundle文件输出,并形成一个hash到名字中
webpack热更新原理
- 本地修改代码保存
- webpack编译,文件hash修改了
- HMR服务知道文件已经修改,通过websocket通知浏览器文件发生变化
- runtime运行时,重新读取minifest来下载和更新页面
webpack proxy原理,为什么可以解决跨域
过程是:将开发环境的数据请求,代理到指定的服务器上,返回数据
解决跨域:因为跨域是浏览器为了保护站点安全的设计,服务端请求服务端是没有跨域的
编写loader和plugin的思路(loader、plugin原理)
loader和plugin的区别
- loader是文件加载器,重在转换;运行在输出文件之前
- plugin是webpack扩展能力,目的是为了解决loader无法解决的事情,可以在整个编译周期中生效
编写loader的思路
loader的本质是一个函数,对于函数:
- 函数的入参是对应的源文件
- 函数的this指向webpack实例,所以loader函数最好不要使用箭头函数
- loader配置的参数通过this.query拿到
- 函数的返回值为目标文件
编写plugin思路
- plugin通常会输出一个构造函数(类),且必须包含apply方法
- apply的参数是compiler,compiler包含webpack所有的配置信息,如loader,plugin
- 通过complier钩子去监听对应的状态,再执行回调
- 在回调中compilation作为参数做一系列的事情,如addEntry添加编译入口
- webpack给compilation对象提供了一系列的方法来让开发者更好的定制开发需求
compiler钩子
compiler支持监听机制,在文件修改重新编译时可以拿到实例上的所有配置
compilation钩子
compilation实例能够访问所有的模块和他们的依赖由compiler创建
如何通过webpack优化性能
- html、css、js、文件、静态资源等压缩
js
const TerserWebpackPligin = require('terser-webpack-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
optimization: {
minimize: true,
minimizer: [
new TerserWebpackPligin({ // js去空格
parallel: true // 启动多核压缩
}),
new CssMinimizerWebpackPlugin({ // css去空格
parallel: true
})
]
},
plugin: [
new HtmlWebpackPlugin({
minify: {
minifyCss: false, // 是否压缩css
collapseWhiteSpace: true // 是否折叠空格
removeComments: true // 是否移除注释
}
}),
new CompressionWebpackPlugin({ // 压缩
test: /\.(css|js)$/, // 哪些文件需要压缩
threshold: 500, // 设置文件大小
miniRatio: 0.7, // 压缩比例
algorithm: 'gzip' // 使用什么算法
})
]
- tree shaking 将没用的模块过滤掉(tree shaking)
- 代码分离:使用webpack的splitChunksPlugin这个被webpack内置的插件,
css
module.exports = {
optimization:{
splitChunks:{
/*
* all: 全部分离
* initial: 同步包分离
* async: 异步包分离
*/
chunks:"all"
}
}
}
如何提升webpack的构建速度
- 根据不同的项目复杂度开启多进程,使用的loader是thread-loader
- webpack5开启缓存
- 并行压缩使用的是terser-webpack-plugin
- 复杂业务根据不同的业务场景打包不同的包
其他的构建工具有哪些,优缺点有哪些
工具 | webpack | vite | rollup |
---|---|---|---|
优点 | 生态完整、丰富的loader和plugin支持几乎你可能遇到的所有的问题 | 按需编译、速度快、HMR更新更快 | 打包产物干净、生成包体积更小 |
缺点 | 大型项目打包会慢,限制webpack5支持缓存之后好一些了 | prod仍然时候的rollup在打包,对css支持不太好、相对年轻还需要大量的使用者来验证 | 不支持HMR、工具函数少 |
适用场景 | 项目类型 | 第三方库、项目类型 | 第三方库 |