webpack 基础知识点
一、概念
- 入口 entry:入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。入口文件个数不限。
- 输出 output:可以通过配置 output 选项,告知 webpack 如何向硬盘写入编译文件。注意,即使可以存在多个 entry 起点,但只能指定一个 output 配置。
- loader:loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加载)" 模块时预处理文件。
- 插件 plugin:插件 是 webpack 的 支柱 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!插件目的在于解决 loader 无法实现的其他事。
- 模式 mode 生产环境下会自动压缩js代码
- 浏览器兼容性 browser compatibility
- 环境 environment
二、loader
- loader的配置方式: 在webpack.config.js文件中指定loader
- module.rules 允许你在 webpack 配置中指定多个 loader。 这种方式是展示 loader 的一种简明方式,并且有助于使代码变得简洁和易于维护。
- loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。
- 内联方式: 在每个 import 语句中显式指定 loader
- 特性 loader 支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 所期望的 JavaScript。
- loader 可以是同步的,也可以是异步的。
- loader 运行在 Node.js 中,并且能够执行任何操作。
- loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
- 除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
- 插件(plugin)可以为 loader 带来更多特性。
- loader 能够产生额外的任意文件
三、plugin 的用法
由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入一个 new 实例。
取决于你的 webpack 用法,对应有多种使用插件的方式。
module.exports={
...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
})
]
}
常用loader:
style-loader: 将css样式嵌入html页面的head中
css-loader: css-loader 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样。
less-loader: webpack 将 Less 编译为 CSS 的 loader。
postcss-loader: 使用 PostCSS 处理 CSS 的 loader。(PostCSS:是一个用 JavaScript 工具和插件转换 CSS 代码的工具,利用从 Can I Use 网站获取的数据为 CSS 规则添加特定厂商的前缀。 Autoprefixer 自动获取浏览器的流行度和能够支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。)
babel-loader: js兼容性问题处理,基本的js兼容性问题处理可以使用@babel/preset-env,全部的js兼容性处理使用@babel/polyfill,按需加载的兼容性处理使用core-js
常用插件:
HtmlWebpackPlugin: 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。你可以让该插件为你生成一个 HTML 文件,使用 lodash 模板提供模板,或者使用你自己的 loader。
html文件压缩需要在options丽里面增加minify的配置,minify配置折叠空格,移除注释{collapseWhitespace:true,removeComments:true})
MiniCssExtractPlugin: 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。本插件基于 webpack v5 的新特性构建,并且需要 webpack 5 才能正常工作。
CssMinimizerWebpackPlugin: 这个插件使用 cssnano 优化和压缩 CSS。就像 optimize-css-assets-webpack-plugin 一样,但在 source maps 和 assets 中使用查询字符串会更加准确,支持缓存和并发模式下运行。
EslintWebpackPlugin: 该插件使用 eslint 来查找和修复 JavaScript 代码中的问题。新版使用时需要在项目根目录增加.eslintrc文件配合使用。
四、 webpack性能优化
开发环境性能优化
- 优化打包构建速度
- HMR: hot module replacement 热模块替换【作用:一个模块发生变化,只会重新打包这一个模块,极大提升构建速度】
- 样式文件:可以使用HMR功能:因为在style-loader内部实现了
- js文件:默认不能使用HMR功能,需要修改js代码,添加支持
HMR功能的代码【注意:HMR功能对js的处理,只能处理非入口文件的其他文件】
- HTML文件:默认不能使用HMR功能,同时会导致html文件不能热更新。解决:修改entry的入口,将html文件引入
- 优化代码调试
- sourcemap: 一种提供源代码到构建后代码映射关系的技术
生产环境性能优化
-
优化打包构建速度
- oneof: 提高构建速度,一种类型的文件只匹配一种loader,需要注意的是内部配置的loader不能存在同时有多个loader处理一种类型文件的情况。
- 开启babel缓存:cacheDirectory,第二次构建时会读取之前的缓存
- 多进程打包:thread-loader,一般使用在babel中,进程启动大概需要600ms,进程通信也有开销,只有消耗时间比较长的,才需要多进程打包
-
优化代码运行的性能
-
文件缓存:
- hash【webpack每次打包会生成的唯一的hash值,文件不管变不变化,hash值一定会变】
- chunkhash【来自于同一个chunk,生成chunkhash值,如果js文件中引入css文件,那么两个文件的chunkhash值会相同】
- contenthash【根据文件内容生成不一样的contenthash值,文件不变,contenthash值不变,第二次打包速度会提升】
-
tree shaking:树摇 ,去除无用的代码,减少代码提及,提高加载速度。前提:必须使用es6模块,必须是在production环境
-
code split
- 多入口
- 配置optimization,设置splitChunks:{chunks:'all'}
- import动态引入
-
懒加载与预加载:
- 懒加载为异步加载,等到触发后才去加载相应内容,优化初次渲染速度
- 预加载是再不影响页面渲染的效率的情况下,会在使用之间加载下相应文件
-
PWA:渐进式网络开发应用程序(离线可以访问) workbox-->workbox-webpack-plugin
-
externals:拒绝将某些包参与打包
-
dll:使用dll技术,对某些库机型单独打包
-
webpack配置详解
entry
入口起点
-
string:'./src.index.js' 此时形成一个chunk,输出一个bundle文件,此时chubk默认的名称是main
-
array:['./src/index.js','./src/add.js'] 多入口文件,所有的入口文件最终只会形成一个chunk文件,输出出去只有一个bundle文件,只有在HMR功能中让html热更新生效
-
object:多入口,有几个入口文件就形成了几个chunk,输出几个bundle文件,此时chunk的文件名称是key。
【object 形式特殊用法】
module.exports = {
entry: {
index: ['./src/index.js', './src/add.js'], // 合并使用倒出在同一个chunk中
test: './src/count.js',
},
output: {
filename: '[name].js',
path: resolve(__dirname, 'build'),
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
output
module.exports = {
entry: './src/index.js',
output: {
// 文件名称(指定名称+目录)
filename: '[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
// 所有资源引入公共路径前缀
publicPath: '/',
// 非入口chunk的名称
chunkFilename: 'js/[name]_chunke.js',
library: '[name]', //整个库向外暴露的名称
libraryTarget: 'window', // 变量名添加到那个上
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
module
- exclude: 排除某个文件夹路径下的对应文件
- include: 只检查某个文件夹路径下对应的文件
- enforce:pre优先执行,post延后执行
- oneof:配置只会生效一个
resolve
作用: 解析模块的规则
- alias:配置解析模块路径别名 ,优点简写路径,缺点没有路径没有提示
- extensions:配置省略文件路径的后缀名
- modules: 告诉webpack解析模块是去哪个目录
devServer
- contentBase:运行代码的目录
- compress:启动gzip压缩
- port: 端口号
- host: 域名
- open:true 自动打开浏览器
- hot: 开启HMR功能
- watchContentBase: 监视contentBase目录下的所有文件,一旦文件变化就会reload
- clientLogLevel: 启动服务器日志信息
- quiet: s是否不显示除了基本启动信息以外的信息
- watchOptions:不监视那些错误
- overlay:如果出错是否不要全屏提示
- proxy:服务器代理,解决开发环境跨域问题
optimization
splitchunks chunks
- maxSize 最大没有限制
- miniSize 分割的chunk最小值
- minChunks 要提起的chunk最少引用次数
- maxAsyncRequests 按需加载时并行加载的文件最大数量
- maxInitialRequests 入口js文件最大并行请求数量
- automaticNameDelimiter 名称连接符
- name 是否可以使用命名柜子
- cacheGroups 分割chunk的组
runtimeChunk
- 将当前模块的记录其他模块的其他模块的hash单独打包成一个文件runtime,
- 解决a 文件导致b文件contenthash变化所产生大冗余打包问题
- minimizer 配置生产环境的压缩方案
webpack5 与webpack4 区别
- webpack4 tree shaking 嵌套多层的未使用属性不能并不会被忽略,继续残存在打包后的文件上,webpacl5在这里做了优化
- webpack5 采用默认配置,只需要配置最基础的mode模式即可
- webpack5 打包效率更加强大,打包体积会更加小
webpack5 重点关注的问题
- 通过持久缓存提高构建性能
- 使用更好的算法和默认值来改善长期缓存
- 通过更好的树摇和代码生成来改善捆绑包大小
- 清除处于怪异状态的内部结构,同时在v4 中实现功能而不引入任何重大更改
- 通过引入重大更改为将来更多功能做准备,以使我们能够尽可能长时间的使用v5