这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战
授课老师:范文杰老师
为什么要学习webpack?
- 理解前端“工程化”概念、工具、目标
- 一个团队总要有那么几个人熟悉Webpack,某种程度上可以成为个人的核心竞争力
- 高阶前端必经之路(webpack,babel,es6工具)
目录:
- 什么是Webpack
- Webpack 打包核心流程
- 示例
- Entry => Dependencies Lookup => Transform => Bundle => Output
- 关键配置项介绍
- Loader组件
- Plugin组件
- 如何学习Webpack
- 入门级:学会灵活应用
- 进阶:学会扩展Webpack
- 大师:源码级理解Webpack打包编译原理
01. 什么是Webpack
先抛出一个问题:前端项目由什么构成? ————资源
这些都是资源:HTML,CSS,JS,SASS,LESS,VUE,JPG,PNG,WEBP...
我们可以手动管理这些资源,但...
- 依赖手工,比如有50个JS文件,就要操作50个
<script>,过程繁琐 - 当代码文件之间有依赖的时候,就得严格按依赖顺序书写
- 开发与生产环境一致,难以接入TS或JS新特性
- 比较难接入Less、Sass等工具
- JS、图片、CSS资源管理模型不一致
所以出现了很多工程化工具(Webpack,rollup.js,vite,require.js等等),正是这些工具的出现,才有了“前端工程”的概念。
Webpack是什么?
本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
- 多份资源文件打包成一个Bundle
- 支持Babel、Eslint、 TS、 CoffeScript、 Less、Sass
- 支持模块化处理css、图片等资源文件
- 支持HMR+开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持Tree-shaking
- 支持Sourcemap
02. 使用webpack
- 安装
npm i -D webpack webpack-cli
- 编辑配置文件
webpack.config.js - 执行编译命令
npx webpack,得到如下结果:
经过打包后,原始的import会变成require
核心流程:
递归调用2,3,直到所有的资源处理完毕。
Webpack具有一致性和模块化的优点:
- 多个文件资源合并成一个,减少http 请求数
- 支持模块化开发
- 支持高级JS特性
- 支持Typescript、CoffeeScript方言
- 统一图片、CSS、字体等其它资源的处理模型
- Etc. . .
使用Webpack:基本围绕“配置”展示
- 流程类: 作用于流程中某个or若干个环节,直接影响打包效果的配置项(上图的四个流程)
- 工具类: 主流程之外,提供更多工程化能力的配置项
流程类
配置总览
文件结构 按使用频率:
entry/output:在一个项目里面至少需要一个entry和outputmodule/pluginsmode:用作production,产物会压缩。watch/devServer/devtool
处理CSS:需要loader,否则模块module解析异常。
- 安装Loader
npm add -D css-loader style-loader
- 添加module处理css文件,使用test过滤文件,use使用loader序列
在入口文件index.js中引入需要的CSS文件:
const styles = require('./ index.css );
// or
import styles from ' ./ index.css '
在webpack.config.js中使用对应的loader:
const path = require("path");
module.exports = {
ectry:"./src/index",
output:{
filename:"[name].js",
path:path.join(__dirname,"./dist"),
},
module:{
rules:[{
test:/\.css/i,
use:['style-loader','css-loader']
}]
}
}
接入Babel
Babel:JS转义工具
- 安装依赖
npm i -D @babel/core @babel/preset-env @babel-loader
- 声明产物
output
- 执行
npx webpack
思考:
- Babel 具体有什么功能?
- Babel与Webpack分别解决了什么问题?为什么两者能协作到一起了?
生成HTML
- 安装依赖
npm i -D html-webpack-plugin
自动生成一个html文件,可以在浏览器上标准地生成:
思考:
- 相比于手工维护HTML内容,这种自动生成的方式有什么优缺点?
- 当资源已经被webpack托管了之后,就没有必要重新写一份html文件。
工具线
工具相关的目的:
- 优化编译过程
- 优化开发效率
- 优化日志输出
HMR
Hot Module Replacement —— 模块热替换
使用:
- 开启HMR,设置devServer的hot属性值为true。将修改的代码立即推送到服务器上。
- 执行
npx webpack serve
设置 watch:true。使得webpack持续监听代码的变化进行构建。
Tree-Shaking
树摇,用于删除没有使用到的代码。
什么是Dead Code?
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
如何开启?
mode:'production'optimization.usedExports:true
PS:对工具类库如Lodash有奇效。这个库里面有很多的工具,但是我们只用到一两个,一旦开启了TreeShaking,则可以去掉很多没有使用到的效果。
其他工具:
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
哪里配置可以划分为流程类? 工具类配置具体有什么作用?包括'devTool'等等。
核心概念:所有的用法都是基于配置项规则进行的。
03. 进阶篇:理解Loader
问题:Webpack只认识JS。 解决方案:Loader——资源翻译模块。
为了处理非标准JS资源,设计出资源翻译模块 ———— Loader。用于将资源翻译为标准JS。
使用loader
- 安装
npm add -D css-loader style-loader less-loader
- 添加module处理CSS文件
链式调用,先实现less=>css转换,再将css包装成字符串。最后将css模块包进require语句,注入到style标签。
Loader其他特性
- 链式调用
- 支持异步执行
- 分normal,pitch两种模式
(所以写的时候需要注意自右向左的顺序~)
如何编写Loader
默认模板:
module.exports = function(source,sourceMap?,date?
{
//source 为loader输入
//可能是文件内容,也可能是上一个loader处理结果。
return source;
}
ESlint 实现:
常见loader:我们需要掌握功能以及配置方法。
思考题
-
Loader输入是什么?要求的输出是什么?
-
Loader的链式调用是什么意思?如何串联多个Loader ?
-
Loader中如何处理异步场景?
04.进阶篇:理解插件
很多知名工具,如:
- VS Code、Web Storm、Chrome、 Firefox
- Babel、Webpack、Rollup、 Eslint
- Vue、 Redux、 Quill、 Axios
等等,都设计了所谓“插件”架构,为什么?
插件架构精髓:对扩展开放,对修改封闭。
Webpack本身很多功能都是基于插件实现的。
插件使用过程:
插件使用起来很简单,但是写起来比较复杂。插件的模板如下:
插件围绕 “钩子”展开:钩子从某种程度上说可以理解成一个事件。
钩子的核心信息:
- 时机:编译过程的特定节点,Webpack会以钩子形式通知插件此刻正在发生什么事情;
2.上下文:通过tapable提供的回调机制,以参数方式传递上下文信息; (每个钩子传递的参数都是不一样的。)
- 交互:在上下文参数对象中附带了很多存在side effect的交互接口,插件可以通过这些接口改变
Webpack内有239个钩子。
时机: compier.hooks.compilation
参数: compilation等
交互: dependencyFactories.set
思考:
- Loader与插件有什么区别点?
- 钩子是什么?如何监听钩子函数?
05. 学习方法
- 入门应用
- 理解打包流程。
- 熟练掌握常用配置项、Loader、 插件的使用方法,能够灵活搭建集成Vue、 React、 Babel、 Eslint、 Less、 Sass、 图片处理等工具的Webpack环境。
- 掌握常见脚手架工具的用法,例如: Vue-cli、 create-react-app、 @ angular/cli。
- 进阶
- 理解Loader、 Plugin 机制,能够自行开发Webpack组件。
- 理解常见性能优化手段,并能用于解决实际问题。
- 理解前端I程化概念与生态现状。
- 大师级
- 阅读源码,理解Webpack编译、打包原理,甚至能够参与共建。
Q&A:
- 面试,Webpack需掌握到什么程度?
- loader作用,怎么写,常用loader有哪些?
- css-loader,style-loader,vue-loader,file-loader,eslint-loader,babel-loader
- 插件作用,怎么写,插件原理
- Bundle
-
require和import导入webpack区别,import支持树摇
-
webpack不支持polyfill IE,所以需要babel。
-
vite快,不需要将东西打包在一起。摒弃了bundle。对兼容性要求较高的业务需要webpack。
-
loader和plugin :对资源的转义,对非JS的资源转成JS。插件作用于整个webpack的生命周期,任意时间点修改webpack运行流程。没有这个职责。
-
webpack和rollup区别。webpack更重,包含许多钩子,扩展性更强,rollup制作npm包。
-
为什么使用__dirname?为了更加精确和安全。
学习资料
1、webpack中文文档——概念:可以在这里起步。
3、Webpack 知识体系:这是一个很全面的思维导图。