webpack 配置
初始化webpack
通过npm i -g webpack webpack-cli
下载webpack和webpack的命令行包。
js 配置
我们都知道es6语法在低版本浏览器内是不会被识别的, 另外有一些语法不会被浏览器支持。于是就有了babel
这个工具链: 将 ECMAScript 2015+
(又可称为ES6
,ES7
,ES8
等)版本的代码转换为向后兼容的 JavaScript
语法,以便能够运行在当前和旧版本的浏览器或其他环境中
Babel 主要做了如下三件事:
- 语法转换
- 通过
Polyfill
方式在目标环境中添加缺失的特性 (通过@babel/polyfill
模块) - 源码转换, 比如 JSX 等
关于babel的相关插件和预设(.babelrc是babel的配置文件):
@babel/core
:
babel的核心功能, 没有我下面的插件都别想用@babel/preset-env
:
提供一个预设环境(其实就是各种语法翻译包),是很多语法能够被转换成es5(箭头语法, let, const等)
但是有些es6后面的语法比如(includes等)是不会被翻译的. 另外babel的插件的使用都需要这个预设库
支持。@babel/preset-react
:
对react jsx等语法的翻译处理,另外可以使用js可选链操作@babel/cli
:
一个内置的 CLI 命令行工具,可通过命令行编译文件
比如:babel index.js -o ./dist/index.js
@babel/polyfill
:
包括core-js
和一个自定义的regenerator runtime
模块.
解决了有些浏览器或者低版本NodeJs下(inclues, promise, async, from等)语法不支持的问题@babel/plugin-transform-runtime
:
防止打包后的文件中出现重复声明的函数, 它可以重复使用 Babel 注入的 helpers 函数,达到节省代码大小的目的@babel/runtime
:
@babel/plugin-transform-runtime这个插件需要@babel/runtime配合使用
供业务代码引入模块化的 Babel helpers 函数
babel的运作流程如下:
source code -> @babel/core -> ast ->
@babel/traverse 和 @babel/types -> ast -> @babel/generator -> output
但是babel会把esm的import语法变成CommonJS语法,这是不会被浏览器识别的。所以需要用打包工具处理
另外@babel/polyfill这个包文件很大.
一般会用 babel-polyfill 结合 @babel/preset-env + useBuiltins(entry) + preset-env targets 的方案
@babel/preset-env提供插件需要的预设环境, useBuiltins实现polyfill的按需引用
于是就有了下面的.babelrc配置
1 | { |
先关的js处理在webpack配置如下:
1 | const isProdMode = process.argv.indexOf("--mode=production") !== -1 |
另外有时候在开发公共包的时候,团队协作可能就需要使用typescript了,typescript该怎么处理配置呢?
- webpack的配置文件下添加如下处理:
1 | { |
- 添加ts-loader的配置文件
tsconfig.json
1 | { |
样式配置
关于css的处理,一般要处理各种浏览器的css样式兼容性,支持scss等。下面是各种loader和插件的解释:
require("mini-css-extract-plugin").loder
:
把css拆分出来用外链的形式引入css文件,该插件会将所有的css样式合并为一个css文件style-loader
:
把css插入到style中css-loader
:
对@import
,url()
进行处理sass-loader
:
把scss/sass 翻译成csspostcss-loader
:
使用postcss
处理csspostcss
:
把css解析为一个抽象语法树, 调用插件处理抽象语法树并添加功能autoprefixer
:
添加前缀的,解决浏览器兼容问题. 添加webkit, mozilla前缀postcss-plugin-px2rem
:
根据跟节点fontsize设置,将px装成rem
在webpack中配置如下:
1 | const MiniCssExtractPlugin = require("mini-css-extract-plugin") |
关于sourceMap
通过sourceMap可以查看报错是出自哪个源文件而不是打包后的文件哪里出错
不过使用sourceMap会使得打包速度变慢
另外默认在module: 'development'
环境中sourceMap是默认开启的
下面是各种sourceMap的解释:
- devtool: ‘inline-source-map’ 将对应的map文件放到js文件中
- devtool: ‘cheap-inline-source-map’ 告诉你具体哪一行出问题,不会精确到那一列出问题
- devtool: ‘eval’ eval是打包速度最快的除了你设置
devtool:none
- devtool: ‘cheap-module-eval-source-map’ 推荐development环境使用
- devtool: ‘cheap-module-source-map’ 推荐production环境使用
各种plugin
plugin 可以在webpack运行到某个时刻的时候帮你做一些事情,所以plugin有生命周期这个说法。
下面是一些常用的插件:clean-webpack-plugin
:
打包前清除上一次打包的文件
htmlWebpackPlugin
:
打包结束后,自动生成一个html文件, 并把打包生成的js自动引入到这个html
MiniCssExtractPlugin
:
把css拆分出来用外链的形式引入css文件,该插件会将所有的css样式合并为一个css文件
另外还可以对css进行代码分割
webpack-bundle-analyzer
:
打包分析工具
HappyPack
:
开启多进程Loader转换,不过还是别用,经常听到电脑风扇的转动声
HotModuleReplacementPlugin
:
热更新的模块替换插件
copy-webpack-plugin
:
拷贝静态资源
css-minimizer-webpack-plugin
:
压缩css
terser-webpack-plugin
:
压缩js
tree shaking
去除无用代码, 只支持ESM, 不支持commonJS的require的引入,
因为CommonJS定义的模块化规范,只有在执行代码后,才能动态确定依赖模块,所以不支持tree shaking。毕竟tree shaking的本质是在在编译生成AST以后进行无用代码去除
默认production模式开启tree shaking(由类似terser-webpack-plugin的插件做的处理)
如果想在开发环境中设置tree shaing, 需要这么配置:
1 | // --webpack.config.js |
另外有时候我们的代码是作为公共库进行开发,可能在Node环境也要运行,而CommonJs又不支持
tree shaking. 所以一般我们会有下面的处理:
1 | { |
代码分割(code splitting)
当重新载入文件的时候,因为代码分割到了不同文件,
只需要对变更代码的文件重新加载即可,所以提升了加载性能
在webpack中配置如下:
1 | optimization: { |
最后
另外还需要对webpack进行
- 多环境配置
- 支持多页面入口打包配置
- 代码打包分析
这是我写的一个webpack配置
谈谈我做的优化:
alias
和extensions
的配置减少了webpack搜索路径的查找和根据后缀查找文件HappyPack
开启多进程,是打包速度更快,减少了构建时间cacheDirectory
开启缓存,将每次的编译结果写进硬盘文件,这样如果打包的模块没有发生变换直接使用缓存就可以tree shaking
生成环境代码进行无用代码删除在压缩减少了代码的体积split chunk
代码分割以及抽离第三方模块,只需要对变更代码的文件重新加载即可,所以提升了加载性能@babel/plugin-transform-runtime
减少了代码的重复声明dynamic-import-webpack
动态加载,按需引入external
cdn外联引入一些三方库, 防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)