wabpack 是做什么的?
概念:webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容
原理: 从入口开始递归的开始读取模块所依赖的的文件内容,生成 AST 树,然后遍历 AST 树,输出让浏览器能够运行的代码到 dist 文件夹
loader 与 plugin 的区别
webpack 将一切都视为模块,但是 webpack 原生只能解析 js 文件和 json 文件,如果要解析其他类型的文件就要用到 loader,所以loader 相当于翻译官的作用,将其他类型的文件进行预处理
Plugin 为插件的意思,Plugin 可以扩展 webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,帮助 webpack 做一些事情。
loader 有些什么注意事项
- 单一原则,一个 loader 只能做一个事情
- 多个 loader 会按照从右至左的顺序执行
例如:
['css-loader', 'vue-style-loader'] // 会先执行vue-style-loader然后再执行css-loader
常用的 plugin
- html-webpack-plugin 这个插件会创建一个 html 文件,并且会自动的引入打包好的文件资源
- mini-css-extract-plugin 打包过后的 css 在 js 文件里,该插件可以把 css 单独抽出来
怎么利用 webpack 来优化网页性能
- 资源文件压缩
- Tree Shaking
- 代码分离
- 动态导入代码(懒加载、预获取)
- 缓存
资源文件压缩
webpack 默认在生产模式中的就会压缩 js 代码,css 压缩可以使用 CssMinimizerWebpackPlugin 这个插件
Tree Shaking
Tree Shaking
中文含义是摇树,在 webpack 中指的是打包时把无用的代码摇掉,以优化打包结果,而webpack5
已经自带了这个功能了,当打包环境为production
时,默认开启tree-shaking
功能。
代码分离
将公共资源提取出来,打包成一个文件,optimization 中进行如下配置
optimization: {
splitChunks: {
chunks: 'all'
}
}
动态导入代码(懒加载、预获取)
懒加载:当用到某个模块的时候才加载
预获取:当浏览器空闲的时候采取获取资源
缓存
浏览器具有缓存机制,当不更改文件名的时候,浏览器会认为你没有更新,就会使用缓存版本
具体实现:
- 缓存第三方库,将第三方库提取到单独的 Vendorchunks 的文件中,利用浏览器的长效缓存机制,命中缓存来消除请求,在 optimization.splitChunks 添加 cacheGroups 参数
- 业务代码文件不缓存,在 output 中的 filename 设置为[name][contenthash].js,contenthash 会根据文件的内容生成一个 hash 的字符串
如何提高代码构建速度
- 优化 loader 配置,缩小处理范围:合理利用这两个属性 exclude:不需要处理的文件 和 include:需要处理的文件
- HMR(Hot Module Replacement) 模块热替换只重新构建发生变化的模块
- babel 缓存 第二次构建时,会读取之前的缓存,只重新构建变化的文件
- 使用 Dll 进行分包
- 多进程打包
优化 loader 配置
在使用loader
时,可以通过配置include
、exclude
、test
属性来匹配文件,接触include
、exclude
规定哪些匹配应用loader
在配置 babel-loader
时,如下:
module.exports = {
module: {
rules: [
{
// 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能
test: /\.js$/,
// babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启
use: ['babel-loader?cacheDirectory'],
// 只对项目根目录下的 src 目录中的文件采用 babel-loader
include: path.resolve(__dirname, 'src'),
},
]
},
};
模块联邦
我们知道 webpack 可以通过 dll 实现对同一个项目的公共组件模块,做成代码共享 common chunk,但是如果是要实现跨项目针对不同的应用就变得非常的困难不易实现。几乎没办法做到不同应用之间进行插拔式的热更新。那怎么样去实现这种跨应用间的共用模块运用呢?于是乎 webpack5 内置了一个模块联邦的功能特性,这个功能可以让跨应用间做到模块共享真正的插拔式的便捷使用。比如 a 应用如果想使用 b 应用中 list 的组件,通过模块联邦可以直接在 a 中进行 import('b/list')非常的方便
模块联邦配置使用
new ModuleFederationPlugin({
// 当前应用的名称, 需要唯一性
name: "main_app",
// 入口文件名称, 用于对外提供模块时候的入口文件名
filename: "remoteEntry.js",
// 需要导出的模块, 用于提供给外部其他项目进行使用
exposes: {
"./search": "./src/search/search.vue"
},
// 需要依赖的远程模块, 用于引入外部其他模块
remotes: {
lib_remote: "lib_remote@http://localhost:8085/remoteEntry.js",
},
// 配置共享的组件, 一般是对第三方库做共享使用
shared: {
vue: {
eager: true,
singleton: true,
}
}
})
网友评论