Table of Contents generated with DocToc
- 静态模块打包器
- 功能:
- 代码转换;
- 文件优化;在生产环境不会压缩 JS、CSS....
- 代码分割;提取多个页面的公共代码,提取首屏不需要执行部分让其异步加载
- 模块合并;模块化的项目里会有多个模块和文件,需要构建功能把模块分类合并成一个文件
- 自动刷新;监听本地更改并刷新页面
- 代码校验;提交到 git 仓库前校验代码
- 自动发布;自动构建线上发布代码并传输给发布系统
- webpack 命令:
- 查看版本号:npx webpack -v
- 安装指定版本:[email protected] webpack-cli
- 开启文件监听模式:webpack --watch (消耗性能,如果想提升开发速度,完全可以使用 webpack-dev-server)
- npm init -y // 生成 package.json 文件
- npm install webpack webpack-cli --save-dev // 生成 node_modules 文件夹
- webpack-cli --mode 可以解析传递参数
- 打包:
- webpack webpack-cli // 默认读取根目录下的 src 文件夹
- npx webpack
- 开发环境 development && 生产环境 production;可以在 package.json 中进行脚本配置
- 打包入口和出口的个性化配置,webpack.config.js
- 配置拆分:通过参数判断当前环境,加载指定配置文件;
- 合并配置文件:npm install webpack-merge
- 生产环境默认打包配置
小记
- hash 命名文件在 webpack 中的几个区别:
- hash:每次打包都会更改文件名,
- chunkhash:每个入口对应 chunk,会根据入口文件中的更改内容决定独立打包某个入口所对应的文件;
- contenthash:根据文件内容是否变化来决定是否打包该文件;
- mode 取值,会将 process.evn.NODE_ENV 的值设置为 production || development
启动本地服务,使用 webpack-dev-server,npm install webpack-dev-server 在内存中打包,不会产生实体文件; devServer 配置;
使用 html-webpack-plugin 自动生成 html 文件并且引入打包后的 js 内容;
使用 clean-webpack-plugin ,在每次打包之前都清除 dist 文件下的目录;
- 前言:webpack 默认配置(零配置),非常弱,灵活性差,所以需要掌握一些配置;
- 开发相关:
-
sourceMap:源代码与打包后的代码的映射关系,通过sourceMap定位到源代码;在dev模式中,默认开启,[devtool](https://webpack.js.org/configuration/devtool/),线上不推荐开启;
- WebpackDevServer:
- 作用:提升开发效率的利器,每次改完代码都需要重新打包一次,打开浏览器,刷新一次,很麻烦。我们可以安装 webpack-dev-server;
- 原理:启动服务后,会发现 dist 目录没有了,这是因为 devServer 把打包后的模块不会放在 dist 目录下,而是放在内存中;
- 配置:通过 devServer 选项指定端口号(port)、内容存放目录(contentBase)、本地代理配置(proxy)等等...
-
- 解析 CSS :需要强调一下loader 的执行顺序,默认是从下往上执行,从右边向左边
- css-loader:解析 css 语法
- style-loader:将解析的 css 变成 style 标签,插入到页面中
- css 预处理器 .scss node-sass sass-loader .less less-loader ...
- 安装:npm install node-sass sass-loader;
- 配置:rules
// 注意在a.css文件中再通过@import引入a.sass文件的配置方式
use: ['style-loader', {
loader: 'css-loader',
options: { // 给loader传递参数
importLoader: 1 // 代表后面参数: sass-loader
}
}, 'sass-loader']
-
css 样式兼容自动填充前缀 附:查看 css 样式兼容性的网址
- postcss-loader ,查找有兼容性要求的 css 属性
- autoprefixer,自动填充 ms-|| webpack-...前缀
- 配置:
{ test: /\.css$/, use: [ 'style-loader'', 'css-loader', 'sass-loader', { loader: 'postcss-loader', options: { // 给loader传递参数 plugins: () => [ require('autoprefixer')({ overrideBrowserslist: ["last 2 versions", ">1%"] }) ] } } ] }
- mini-css-extract-plugin, 抽离 css 样式文件,抽离的好处是 css 文件可以和 js 并行加载
-
解析图片+icon
- file-loader,配置图片格式匹配
{ test: /\.(jpe?g|png|gif)$/, use:'file-loader' }
-
js 相关
-
@babel/core @babel/preset-env babel-loader,
- 用法:babel-loader 是 webpack 与 babel 通信的桥梁(不会把 es6 转 es5) @bebel-preset-env 负责 es6->es5,
test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ["@babel/preset-env"] } }
- @babel/polyfill 的使用: 在入口文件 index.js 中 import
import "@babel/polyfill"
但是会导致 bundle.js 非常庞大,所以我们希望按需引入,useBuiltIns 选项是 babel7 的新功能,告诉 babel 如何配置@babel/polyfill,具体配置见/root/.babelrc 小记 当我们开发组件库时、工具库时,polyfill 就不适合了,因为 polyfill 是注入到全局变量 window 下,会污染全局环境;开发组件库时,推荐闭包方式:@babel/plugin-transform-runtime
- 避免 js 代码 重用:@babel/plugin-transform-runtime
- ts 配置:@babel-preset-typescript
type State = Readonly<typeof initState> // 把initState中的属性拿出来变成只读的
-
terser-webpack-plugin,压缩 js 文件
-
-
react+vue...
-
多入口配置 实践:入口配置为对象,出口配置多个 HTMLWebpackPlugin,通过 chunks 属性定义好对应的入口文件
- 压缩 css mini-css-extract-plugin
- 删除无用 css 样式 purgecss-webpack-plugin
- 查找匹配文件 glob
- 图片压缩插件(降低分辨率 ) image-webpack-loader
- Tree-shaking
- 作用:去除掉 js 无用代码;
- 适用范围:默认只支持 es6 语法,静态导入,只在生产环境使用;
- 配置:
optimization: { usedExports: true }
- 需要注意的是:通过 import 引入的可执行文件代码,但是并未真实使用,需要在 package.json 中配置:"sideEffects": true, l(注意该种办法的副作用:如果引入 css 文件:import 'a.css',也会被去除),可以根据需要指定文件类型:
"sideEffects": [ "**/*.css" // glob语法 ]
- Scope-hoistiong(自带)
- 作用:由于 webpack 打包的每个模块都会生成一个函数,会导致内存过大,所以,引入 scope-hoistiong,作用域提升,减少作用域
- DllPlugin 动态链接库 某种方法实现了拆分 bundles,同时还大大提升了构建的速度(对项目运行优化没有帮助)
- DllReferencePlugin 在项目中可以找到 上一步打包好的 dll 中的指定文件;
new DllReferencePlugin({ manifest: path.resolve(__dirname, '../dll/mainfest.json') })
- 代码分割:即第三方库抽离,不同于 dll 这个是做缓存:生产环境下,自动将第三方库进行抽离:optimization.splitchunks
- 配置:/root/util/webpack.base.js -> optimization.splitChunks,可以通过参数指定什么情况下自动分割代码,
DllPlugin 与 Optimization.splitChunks 的区别
区别比较 | 是否优化页面加载速度? | 执行时机 | 建议使用场景 |
---|---|---|---|
DllPlugin | 否 | 构建之前抽离 | 开发环境提升打包速度 |
Optimization.splitChunks | 是 | 编译过程中抽离 | 生产环境分割第三方代码 |
- 草案语法:import()
- 使用:动态导入,可以实现代码分割,应用在类比、路由懒加载...;
- 原理:JSONP;
- 语法:返回值为 Promise 对象;
- 为动态加载的文件更改文件名的配置:chunkFilename + 魔术字符串
- 定义:模块热替换是 Webpack 提供的最有用的功能之一,它允许在运行时替换、添加、删除各种模块,而无需进行完全刷新重新加载整个页面;了解更多点击进入官网
- 实现:
- 保留在完全重新加载页面时丢失的应用程序的状态;
- 只更新改变内容,节省开发时间;
- 调整样式更加快速,几乎等同于在浏览器调试器中更改样式;
- 配置:
devServer: { hot: true } new webpack.NamedModulesPlugin()
- 让 js 支持热更新:
如果在项目中使用,不用单独配置,配置框架 loader 即可,
import sum from './sum' console.log(sum(1, 2)) if (module.hot) { // 判断是否支持热更新 module.hot.accept() // 当入口文件变化后重新执行当前入口文件,原理是监听到变化后,删除dom再重新将新的添加到文档中; }
happypack多线程打包,将不同的逻辑交给不同的线程来处理
- 意义:webpack 打包出来的都会放到 bundle.js(出口文件)中,bundle.js 会非常庞大,所以我们引入 CDN,拆分 bundle.js
- 使用:bootcnd,找到插件,复制 script 标签,粘贴进模板文件中,但是当文件较多时,不能都在 index.html 中引入,所以可以使用 add-asset-html-cdn-webpack-plugin 插件
plugins: [ new AddCdnPlugin(true, { 'jquery': 'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js' }) ]
- 配置:声明外部文件
externals: { 'jquery': '$' // 引入外部变量,在使用$时,是从外部引入的jq,不去打包代码中的jquery }
忽略 import 和 require 语法
module.noParse,对类似 jq 这类依赖库,内部不会引用其他库,我们在打包的时候没有必要去解析,这样能够增加打包速率
noParse: /jquery/
resolve: {
extensions: [".js", ".jsx", ".json", ".css"],
alias: {},
modules: ['node_modules']
}
在使用 loader 时,可以指定哪些文件不通过 loader,或者指定哪些文件通过 loader
-
打包分析工具:webpack-bundle-analyzer 可以分析打包依赖关系,以及包的大小
-
费时分析:speed-measure-webpack-plugin 可以计算每一步执行的运行速度
- 简单实现一个文件导入,代码转换:见/root/util/bundle.js
- 简单实现一个 loader 官网描述
- 简单编写一个 plugins 官网描述 插件是可以作用在 webpack 打包的整个生命周期中,所以需要了解compiler 钩子 、compilation 钩子
- 梳理 webpack 优化:
- 确定好技术栈;(产品面向 mobile or pc,要兼容哪些浏览器)
- js babel
- hot-module
- 压缩:生产压缩,开发不压缩
- css
- 生产压缩,开发不压缩
- 去重
- js babel
- 确定好技术栈;(产品面向 mobile or pc,要兼容哪些浏览器)
- 如何将代码转换成 AST :推荐文章:webpack 与 rollup 背后的 acorn 代码地址:acornjs