把字节青训营的视频又翻出来学习力,并且补个简单的笔记
什么是Webpack
Webpack本质上是一种前端资源编译、打包工具,核心目标是模块化
+一致性
。
可以将多份资源文件打包成一个Bundle,减少http请求数
支持模块化开发(Babel / Eslint / TS / CoffeScript / Less / Sass)统一了资源文件的管理模型,不需要为JS独立设立一套管理的规范
支持高级JS特性
支持TypeScript、CoffeeScript方言
统一图片、CSS、字体 等其他资源的处理模型
Webpack核心工作流程
- 入口处理
从entry
文件开始,启动编译流程
- 依赖解析
从entry
文件开始,根据require
or import
等语句找到依赖资源
- 资源解析
根据module
配置,调用资源转移器,将png、css等非标准JS资源转译为JS内容
(递归调用2、3,直到所有资源处理完毕)
- 资源合并打包
将转译后的资源内容合并打包为可直接在浏览器运行的JS
Webpack的基本使用流程
- 安装
yarn add webpack webpack-cli
- 编辑配置文件
// webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index',
mode:'development',
devtool:false,
output:{
// 产物文件名
filename:'[name].js',
path:path.join(__dirname,'./dist')
},
}
// src/index.js
const sum = (x, y) => x + y;
- 执行编译命令
npx webpack
如何使用Webpack
关于Webpack的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
- 流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项
- 工具类:主流程之外,提供更多工程化能力的配置项(Tree shaking、Devtool)
流程类配置总览
- 输入
entry
:定义项目入口context
:Webpack运行时该从哪个文件夹开始找资源
- 模块解析
resolve
externals
- 模块转译
module
- 后处理
optimization
mode
target
处理CSS
- 安装loader
loader是Webpack中用于处理不同资源的组件
yarn add css-loader style-loader
- 添加
module
处理css文件
// webpack.config.js
const path = require('path');
module.exports = {
entry:'./src/index',
output:{
filename:'[name].js',
path:path.join(__dirname,'./dist'),
},
module:{
// css处理器
rules:[{
// 匹配文件后缀
test:/\.css/,
// 使用这个loader
use:[
"style-loader",
"css-loader"
]
}]
}
}
- 运行
npx webpack
,进行转译
可以看到编译产物中,我们之前在css内写的内容转为字符串push到了__CSS_LOADER_EXPORT__
中
除此之外,我们会发现编译产物的内容远远多于原始文件,充斥了大段的运行时代码
处理JS(接入Babel)
- 安装依赖
yarn add @babel/core @babel/preset-env babel-loader
- 声明产物出口
output
// webpack.config.js
module.exports = {
module:{
rules:[{
test:/\.js$/,
use:[{
// 用babel-loader处理JS文件
loader:'babel-loader',
// options最终会传入loader运行
options:{
// 规则集
presets:[
['@babel/preset-env']
]
}
}]
}]
}
}
- 执行
npx webpack
生成HTML
需要安装一个html-webpack-plugin
的插件,该插件可以帮助我们自动生成HTML文件,不需要手动管理导入HTML的资源
- 安装依赖
yarn add html-webpack-plugin
- 声明产物出口
output
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins:[new HTMLWebpackPlugin()],
}
- 执行
npx webpack
开启HMR(Hot Module Replacement 热更新)
保存代码时,页面会自动更新
- 开启HMR
// webpack.config.js
module.exports = {
devServer: {
hot: true,
open: true
},
// 持续监听文件变化
watch: true
}
- 启动Webpack
npx webpack serve
开启Tree-Shaking
DeadCode: 代码没有被用到 / 代码的执行结果不会被用到 / 代码只读不写 / …
Tree-Shaking: 模块导出了,但未被其他模块使用
// webpack.config.js
module.exports = {
mode: 'production',
optimization: {
usedExports: true
}
}
理解Loader
由于Webpack只认识JS,为了处理非标准JS资源,Loader作为一个资源翻译模块诞生,用于将资源翻译为标准JS
Loader有三个特性:1. 链式调用 2. 支持异步执行 3. 分normal、pitch两种模式
使用Loader主要有两个步骤:1. 安装相关的loader 2. 将loader添加到module
处理
特性:链式调用
比如在处理less文件时,通常需要安装三个loader: style-loader
/ css-loader
/ less-loader
less-loader
用于实现less到css的转换;
css-loader
用于将CSS包装成类似module.exports = "${css}"
的内容,包装后的内容符合JavaScript语法;
style-loader
用于将CSS模块包进require语句,并在运行时调用injectStyle等函数,将内容注入到页面的style标签
三者是链式调用的关系,第一个loader的输出结果会成为第二个loader的输入
loader在pitch阶段根据loader数组定义的顺序,从前往后执行(style->css->less)。任意一个loader的pitch阶段如果有返回值,就会停止后续执行(适合做一些catch loader)
到了执行阶段,则先从源码中读取内容,按照loader数组定义顺序,从后往前执行(less->css->style)
如何编写自定义loader
一个基本的loader结构如下:
module.exports = function(source, sourceMap?, data?){
// source为loader的输入
// 可能是文件内容,也可能是上一个loader的处理结果
return source;
}
将其命名为loader.js
,并在webpack.config.js
中指定由loader.js
处理js后缀的文件
// webpack.config.js
module.exports = {
module:{
rules:[{
test:/\.js$/,
use:[path.join(__dirname, './loader')]
}]
}
}
常见loader
理解插件
插件架构的精髓:对扩展开放,对修改封闭
使用插件主要有3个步骤:1. 安装插件依赖 2. 在webpack.config.js
中引入插件 3. 在plugins
数组中添加插件实例
插件基本形态
插件用起来容易,编写时却较为复杂。
首先,插件围绕钩子
展开。一个钩子具有以下核心信息:
- 时机(
compier.hooks.complication
):在编译过程的特定节点,Webpack会以钩子形式通知插件此刻正在发生什么事情 - 上下文(
complication
):通过tapable提供的回调机制,以参数方式传递上下文信息 - 交互(
dependencyFactories.set
):在上下文参数对象中附带了很多存在side effect的交互接口,插件可以通过这些接口改变
class SomePlugin{
apply(compiler){
compiler.hooks.thisCompilation.tap('SomePlugin',(complication)=>{
// ...
})
}
}
学习Webpack的方法
入门应用
- 理解打包流程
- 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成 Vue / React / Babel / Eslint / Less / Sass / 图片处理等工具的Webpack环境
- 掌握常见脚手架工具的用法,例如:Vue-cli / cra / @angular/cli
进阶
- 理解Loader / Plugin机制,能够自行开发Webpack组件
- 理解常见性能优化手段,并能用于解决实际问题
- 理解前端工程化概念与生态现状
大师级
阅读源码,理解Webpack编译、打包原理,甚至能够参与共建
问答
面试要学到什么程度
主要围绕三种主题
Loader有什么用 / 怎么写Loader / 常用Loader有哪些
css-loader / style-loader / vue-loader / eslint-loader插件有什么用 / 怎么写插件 / 插件原理
Bundle / chunk / module 分别是什么含义
上一页: 利用Github Pages部署React项目到自己的域名下一页: 用customize-cra+react-app-rewired配置less+css module的踩坑经历