【青训营】Webpack知识体系

293 阅读8分钟

这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

授课老师:范文杰老师

为什么要学习webpack?

  • 理解前端“工程化”概念、工具、目标
  • 一个团队总要有那么几个人熟悉Webpack,某种程度上可以成为个人的核心竞争力
  • 高阶前端必经之路(webpack,babel,es6工具)

目录:

  1. 什么是Webpack
  2. Webpack 打包核心流程
    • 示例
    • Entry => Dependencies Lookup => Transform => Bundle => Output
    • 关键配置项介绍
  3. Loader组件
  4. Plugin组件
  5. 如何学习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,它们均为静态资源,用于展示你的内容。

image.png

  • 多份资源文件打包成一个Bundle
  • 支持Babel、Eslint、 TS、 CoffeScript、 Less、Sass
  • 支持模块化处理css、图片等资源文件
  • 支持HMR+开发服务器
  • 支持持续监听、持续构建
  • 支持代码分离
  • 支持Tree-shaking
  • 支持Sourcemap

02. 使用webpack

  1. 安装
npm i -D webpack webpack-cli
  1. 编辑配置文件webpack.config.js image.png
  2. 执行编译命令npx webpack,得到如下结果:

image.png

经过打包后,原始的import会变成require

核心流程:

image.png

递归调用2,3,直到所有的资源处理完毕。

Webpack具有一致性和模块化的优点:

  1. 多个文件资源合并成一个,减少http 请求数
  2. 支持模块化开发
  3. 支持高级JS特性
  4. 支持Typescript、CoffeeScript方言
  5. 统一图片、CSS、字体等其它资源的处理模型
  6. Etc. . .

使用Webpack:基本围绕“配置”展示

  • 流程类: 作用于流程中某个or若干个环节,直接影响打包效果的配置项(上图的四个流程)
  • 工具类: 主流程之外,提供更多工程化能力的配置项

流程类

image.png

配置总览

image.png

文件结构 按使用频率:

  • entry/output:在一个项目里面至少需要一个entry和output
  • module/plugins
  • mode:用作production,产物会压缩。
  • watch/devServer/devtool

处理CSS:需要loader,否则模块module解析异常。

  1. 安装Loader
npm add -D css-loader style-loader
  1. 添加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转义工具

  1. 安装依赖
npm i -D @babel/core @babel/preset-env @babel-loader
  1. 声明产物output

image.png

  1. 执行npx webpack

思考:

  • Babel 具体有什么功能?
  • Babel与Webpack分别解决了什么问题?为什么两者能协作到一起了?

生成HTML

  1. 安装依赖
npm i -D html-webpack-plugin

自动生成一个html文件,可以在浏览器上标准地生成:

image (1).png

思考:

  • 相比于手工维护HTML内容,这种自动生成的方式有什么优缺点?
    • 当资源已经被webpack托管了之后,就没有必要重新写一份html文件。

工具线

image.png

工具相关的目的:

  • 优化编译过程
  • 优化开发效率
  • 优化日志输出

HMR

Hot Module Replacement —— 模块热替换

使用:

  1. 开启HMR,设置devServer的hot属性值为true。将修改的代码立即推送到服务器上。

image.png

  1. 执行
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

  1. 安装
npm add -D css-loader style-loader less-loader
  1. 添加module处理CSS文件

image.png

image.png

链式调用,先实现less=>css转换,再将css包装成字符串。最后将css模块包进require语句,注入到style标签。

image.png

Loader其他特性

  1. 链式调用
  2. 支持异步执行
  3. 分normal,pitch两种模式

(所以写的时候需要注意自右向左的顺序~)

如何编写Loader

默认模板:

module.exports = function(source,sourceMap?,date?
{
    //source 为loader输入
    //可能是文件内容,也可能是上一个loader处理结果。
    return source;
}

ESlint 实现:

image.png

常见loader:我们需要掌握功能以及配置方法。

image.png

思考题

  • Loader输入是什么?要求的输出是什么?

  • Loader的链式调用是什么意思?如何串联多个Loader ?

  • Loader中如何处理异步场景?

04.进阶篇:理解插件

很多知名工具,如:

  • VS Code、Web Storm、Chrome、 Firefox
  • Babel、Webpack、Rollup、 Eslint
  • Vue、 Redux、 Quill、 Axios

等等,都设计了所谓“插件”架构,为什么?

插件架构精髓:对扩展开放,对修改封闭。

Webpack本身很多功能都是基于插件实现的。

插件使用过程:

image.png

image.png

插件使用起来很简单,但是写起来比较复杂。插件的模板如下:

image.png

插件围绕 “钩子”展开:钩子从某种程度上说可以理解成一个事件。

钩子的核心信息:

  1. 时机:编译过程的特定节点,Webpack会以钩子形式通知插件此刻正在发生什么事情;

2.上下文:通过tapable提供的回调机制,以参数方式传递上下文信息; (每个钩子传递的参数都是不一样的。)

  1. 交互:在上下文参数对象中附带了很多存在side effect的交互接口,插件可以通过这些接口改变

Webpack内有239个钩子。

时机: compier.hooks.compilation 参数: compilation等 交互: dependencyFactories.set

思考:

  • Loader与插件有什么区别点?
  • 钩子是什么?如何监听钩子函数?

05. 学习方法

  1. 入门应用
  • 理解打包流程。
  • 熟练掌握常用配置项、Loader、 插件的使用方法,能够灵活搭建集成Vue、 React、 Babel、 Eslint、 Less、 Sass、 图片处理等工具的Webpack环境。
  • 掌握常见脚手架工具的用法,例如: Vue-cli、 create-react-app、 @ angular/cli。
  1. 进阶
  • 理解Loader、 Plugin 机制,能够自行开发Webpack组件。
  • 理解常见性能优化手段,并能用于解决实际问题。
  • 理解前端I程化概念与生态现状。
  1. 大师级
  • 阅读源码,理解Webpack编译、打包原理,甚至能够参与共建。

image.png

Q&A:

  1. 面试,Webpack需掌握到什么程度?
  • loader作用,怎么写,常用loader有哪些?
    • css-loader,style-loader,vue-loader,file-loader,eslint-loader,babel-loader
  • 插件作用,怎么写,插件原理
  • Bundle
  1. require和import导入webpack区别,import支持树摇

  2. webpack不支持polyfill IE,所以需要babel。

  3. vite快,不需要将东西打包在一起。摒弃了bundle。对兼容性要求较高的业务需要webpack。

  4. loader和plugin :对资源的转义,对非JS的资源转成JS。插件作用于整个webpack的生命周期,任意时间点修改webpack运行流程。没有这个职责。

  5. webpack和rollup区别。webpack更重,包含许多钩子,扩展性更强,rollup制作npm包。

  6. 为什么使用__dirname?为了更加精确和安全。

学习资料

1、webpack中文文档——概念:可以在这里起步。

2、深度剖析 Webpack 系列

3、Webpack 知识体系:这是一个很全面的思维导图。

4、深入浅出 Webpack

5、Babel · The compiler for next generation JavaScript

6、Configuration | webpack

7、GitHub - Tecvan-fe/awesome-webpack-4plus