这是我参与「第五届青训营」伴学笔记创作活动的第 11 天。
为什么需要Webpack
前端项目由许许多多的资源文件构成。
手工管理、组织这些资源面临许许多多的问题:
- 操作过程繁琐
- 当代码文件之间有依赖的时候,就得严格按依赖顺序书写
- 开发与生产环境一致,难以接入TS或JS新特性
- 比较难接入Less、Sass等工具
- JS、图片、CSS 资源管理模型不一致
为此,出现了许多管理、组织、处理资源文件的工具,即所谓的“工程化工具”。
Webpack就是一种工程化工具,其本质是一种前端资源的编译、打包工具:
- 多份资源文件打包成一个Bundle
- 支持Babel、Eslint、 TS、CoffeScript、 Less、Sass支持模块化处理css、图片等资源文件
- 支持HMR+开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持Tree-shaking
- 支持SourceMap
- ……
Webpack的设计目标:模块化、一致地处理资源
- 多个文件资源合并成一个,减少HTTP请求数
- 支持模块化开发
- 支持高级JS特性
- 支持Typescript、CoffeeScript方言
- 统一图片、CSS、字体等其它资源的处理模型
- ……
Webpack初体验
安装
npm i -D webpack webpack-cli
使用实例
配置:声明输入、处理流程、输出
module.exports = {
entry: "main.js",
output: {
filename:"[name].js"
path: path.join(__dirname, "./dist"),
},
module:{
rules: [{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"]
}]
}
}
编译
npx webpack
核心流程
- 入口处理:从
entry文件开始,启动编译流程 - 依赖解析:从
entry文件开始,根据require/import等语句找到依赖资源 - 资源解析:根据
module配置,调用资源转移器,将png、css等非标准JS资源转译为JS内容 - 递归调用2、3,直到所有资源处理完毕
- 资源合并打包:将转译后的资源内容做后处理并合并打包为可直接在浏览器运行的JS文件
配置Webpack
Webpack的使用基本都围绕【配置】展开,而这些配置大致可划分为两类:
- 流程类:作用于流程中某个/若干个环节,直接影响打包效果的配置项
- 输入配置
entrycontext
- 模块解析
resolveexternals
- 模块转译
module
- 后处理
optimizationmodetarget
- 输入配置
- 工具类:主流程之外,提供更多工程化能力的配置项
- 开发效率类:
watchdevtooldevServer
- 性能优化类:
cacheperformance
- 日志类:
statsinfrastructureLogging
- 其它:
amdbail- ……
- 开发效率类:
按使用频率(重要程度)排名:
entry/outputmodule/pluginsmodewatch/devServer/devtool
流程类配置例子
-
声明输入
entry、输出output(这两个必须有)const path = require("path"); module.exports = { entry: "./src/index", output: { filename: "[name].js" path: path.join(__dirname, "./dist"), }, }; -
配置转换流程(Loader)1:以CSS处理为例
安装:
npm add -D css-loader style-loader配置:
const path = require("path"); module.exports = { entry: "./src/index", output: { filename: "[name].js" path: path.join(__dirname, "./dist"), }, module: { rules: [{ test: /\.css$/, // 文件匹配规则 use: ["style-loader", "css-loader"] // 指定处理用到的Loader }] }, };其中
use中的指令是按逆序来执行的,即先执行css-loader,再执行style-loader:- css-loader:解析CSS文件的
@import和url(),会import/require(),经过此Loader后CSS文件转变为JS数组对象,其中的元素是CSS文件的原始内容 - style-loader:通过上述的JS数组创建一个style标签
- css-loader:解析CSS文件的
-
配置转换流程(Loader)2:以JS文件的Babel为例
Babel:将ES6语法转换为旧式JS语法
安装:
npm i -D @babel/core @babel/preset-env babel-loaderbabel的preset是一些处理的规则集,常用的preset有:
@babel/preset-env@babel/preset-react@babel/preset-typescript
配置:
const path = require("path"); module.exports = { entry: "./src/index", output: { filename: "[name].js", path: path.join(__dirname, "./dist"), }, module: { rules: [{ test: /\.js$/, use: [ loader: "babel-loader", options: { presets: [ ["@babel/preset-env"] ] } ] }] }, }; -
配置转换流程(Plugin)3:以自动生成配套HTML文件为例
安装:
npm i -D html-webpack-plugin配置:
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: "./src/index", output: { filename: "[name].js", path: path.join(__dirname, "./dist"), }, plugins: [new HtmlWebpackPlugin()] };
工具类配置例子
-
模块热替换(源码修改,预览服务器即修改而不需要重新生成)
module.exports = { // ... devserver: { hot: true } };npx webpack serve -
删除死代码
module.exports = { // ... mode: "production" optimization: { usedExports: true } };