Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack5 源码详解 - 先导 #15

Open
Hazlank opened this issue Apr 10, 2022 · 0 comments
Open

webpack5 源码详解 - 先导 #15

Hazlank opened this issue Apr 10, 2022 · 0 comments
Labels

Comments

@Hazlank
Copy link
Owner

Hazlank commented Apr 10, 2022

阅读源码先导

webpack源码很庞大,并且配置很丰富,阅读起来十分困难。有很多重要的功能模块,概念,独立于webpack外的包等。在阅读源码之前最好先把它们单独整理出来进行简单的介绍,更利于后面的阅读。

Compiler

webpack在运行的时候,会传入配置信息,返回实例化的Compiler对象。它在运行环境里是唯一的,所有主流程都由它来控制,比如开始编译,从入口开始处理模块,对于不同模块根据配置进行封装在一个组里,最后生成文件等等。当然,它只是操作流程,流程内的事情都是托付给其他模块处理。

Compilation

它能够调用许多处理模块的方法,并保存相应的构建的信息,比如modules,assets,moduleGraph, chunkGraph等。每次资源的重构建都会产生新的Compilation。

Module

在webpack里,万物都是模块,js文件,图片,视频等。普通的模块都会生成NormalModule对象,它可以调用方法解析模块,可以调用parser解析成AST(抽象语法树)等。NormalModule对象包含着Loader处理过后的代码,被哪个模块解析引入,模块解析的路径,引入其他模块的依赖等信息。而且在构建模块的时候,会生成moduleGraph来记录模块之间引用信息,可以保存导出信息,用于分析导出是否有被使用。

Chunk

在构建完之后,所有的module都会被打包在一个Chunk里,但也可以自行配置,对代码进行分块。

Loader

webpack能够处理js,并且webpack5还添加了许多能处理其他资源的能力。但是还有很多文件webpack本身不能处理,需要引入其他Loader转换成js,才能够被webpack操作。如果你想写一个Loader处理相关资源,可以阅读文档

Plugin

插件能够帮助webpack扩展功能,包括内置的很多功能也是通过插件的方式引入的,比如热模块替换,external,splitChunk等。它们统统扩展于Tapable,这样的好处在于能够很好的扩展webpack的功能并且和webpack解耦。如果你想写一个Plugin扩展功能,可以阅读这里

Parser

Parser用于解析资源,最常用到的parser就是JavascriptParser。它用acorn将js解析成AST(抽象语法树),并且对所有的声明或表达式进行遍历,找出相关模块的导入导出信息,添加至依赖里。也能收集导出导入情况,为后续的tree-shaking做准备。也能解析注释,实现webpack magic comment功能。

除了JavascriptParser,还有webassemblyParser,会调用@webassemblyjs/ast进行解析。还有cssParser , jsonParser等

独立库

除了webpack核心的代码,它还将很多功能独立成一个库,这些库不仅用于webpack,也能用于vanillaJs。

Tapable

这是webpack贯穿全文的库,基本重要的功能模块都有它的身影,功能模块与plugin的通信都需要靠它。在webpack里它叫做hooks,其实就是一个高级的EventEmitter,我也写了一篇详细的文章去介绍它。

如果你想写好一个插件,最好了解webpack主要模块的hooks都有哪些:

enhanse-resolve

enhanse-resolve是一个高度可配置的resolve库,它在webpack用来解析文件和loader的路径信息,也可以支持许多配置,比如我们最常用的配置就是resolve.alias,通过别名更方便导入资源,还有resolve.extensions增加文件扩展名等,webpack resolve options都是用于配置这个库。

loader-runner

loader-runner用于执行webpack loader。

webpack-sources

webpack-sources可以生成源码的sourceMap,hash等

运行环境

webpack v5.70.0

webpack.config.js

const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
	mode: "development",
	devtool: "source-map",
	entry: "./index.js",
	output: {
		path: path.join(__dirname, "./dist"),
		filename: "[fullhash].[name].bundle.js"
	},
	optimization: {
		usedExports: true
	},
	plugins: [new CleanWebpackPlugin()]
};

index.js

import { c_var } from "./module_c"

import { b } from "./module_b"

import { d } from "./module_d"

import("./module_a").then(({ a }) => {
	console.log(a)
})

var log_var = c_var;
console.log(log_var + b + d)

module_a.js

import("./module_d").then(({ d }) => {
	console.log(d)
})

export const a = "moudle_a";
export const a_unesed = "a_unused";

module_c.js

const c_var = "module_c";
const b_var = "unused";
export { c_var, b_var };

module_b.js

export const b = "I from module_b"

module_d.js

export const d = "I from module_d"

入口为./index.js

全篇执行目录context为c:\Users\Administrator\Desktop\webpack

流程

webpack的流程可以分为四个大块来讲

run

初始化,做好开始编译的准备工作。处理options,rules,注册插件,实例化compiler所需要的其他对象等。

make

通过入口文件开始构建模块,构建模块会分为几个步骤,解析路径,通过loader转换模块,进行paser收集依赖,递归处理所有外部依赖等。

seal

seal是属于Compilation的hooks,不像run,make,emit都属于Compiler,单独拿出来因为这个阶段也做了很多事,并且也是在make之后执行的。seal阶段不再接收模块,会根据ChunkGroup进行封装成一个或多个chunk,之后会做一些代码优化工作,生成文件Hash name等。

emit

输出文件阶段,webpack会根据不同的template来生成代码,一些代码会被替换,比如import,export会被替换成__webpack_require__,__webpack_exports__等。

webpack的很多代码的运行基于是否有配置,因为只是为了了解打包过程与方便调试,所以后续代码示例大部分会去掉一些无用代码,错误处理,为了实现cache的代码等。并且运行模式为"development",在"production"下很多配置会默认为true,会对代码压缩,不利于理解。

@Hazlank Hazlank changed the title webpack5 源码解析 - 先导 webpack5 源码详解 - 先导 Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant