重学webpack系列(八) -- webpack的运行机制与工作原理

前面几个章节我们分别去探索了webpackloader机制、plugin机制、devServersourceMapHMR,但是你是否知道这些配置项是怎么去跟webpack本身执行机制挂钩的呢?这一章我们就来探索一下webpack的运行机制与工作原理吧。

webpack核心工作过程

我们打开webpack官网,我们可以看到这样的一张图。

上图陈述了任意资源文件模块,经过webpack处理会生成相对应的资源文件,在这里你可能会问,webpack输出不是只有.js文件吗,为什么会有.css.jpg呢,各位同学不要着急,请听我慢慢向你道来。

画图解释

构建成了依赖树之后,webpack会递归遍历当前的依赖树,使用我们在配置中写的loader进行对应的模块加载,加载完毕之后会进行output的配置选项进行文件输出,一般我们默认的是dist/main.js为输出文件。我们也称之为bundle.js

至此我们就完成了整个项目的打包过程。

webpack是怎么去处理那些不能被js处理的文件的呢

对于依赖模块中,那些无法被js解释描述的模块,比如图片,字体等等,那么会有对应的loader,比如file-loader,会把这些资源直接输出到打包目录,然后会把当前资源的访问路径作为模块的导出成员暴露出来,以供外部成员调用。

plugin是怎么工作的呢

pluginwebpack打包的任意阶段中,可以通过hooks往阶段中去注入某些功能,去完成某些构建任务。

webpack核心工作的原理

上面也提到webpack打包的核心流程,我们在package.json里面配置了"build": webpack && webpack-cli,之后只需要在terminal中键入npm run build就可以让webpack自动打包构建了,然后webpack会经历如下步骤。

  • webpack-cli启动。
  • 载入配置项参数,初始化Compiler对象,加载所有配置项plugin
  • 使用Compiler对象的run方法开始编译项目。
  • 通过entry找到入口文件,解析模块依赖,形成依赖树。
  • 递归遍历依赖树,让loader去加载对应的模块以及依赖模块。
  • 合并loader处理结果,组装成chunks,转换成文件,输出到build目录。

如果你看文字比较烦闷,那么我也可以画成概念图:

深入webpack的源码

那么webpack5是怎么进行构建的呢,我们还是得来深入一下源码,我们在webpack-cli文件夹下的bin目录找到入口文件。

// webpack/node_modules/webpack-cli/bin/cli.js
#!/usr/bin/env node
 "use strict";

const importLocal = require("import-local");
const runCLI = require("../lib/bootstrap");

...
process.title = "webpack";
// 执行runCLI函数
// process.argv = [
//'/usr/local/bin/node',
//'/Users/mac/Desktop/webpack/webpack/node_modules/.bin/webpack-cli'
//] 
runCLI(process.argv);

// webpack/node_modules/webpack-cli/lib/bootstrap.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// 导入WebpackCLI
const WebpackCLI = require("./webpack-cli");

const runCLI = async (args) => {//创建一个webpack-cli实例const cli = new WebpackCLI();try {await cli.run(args);}catch (error) {cli.logger.error(error);process.exit(2);}
};
module.exports = runCLI; 

上述代码表明webpack在工作的时候创建了一个WebpackCli的实例,之后去调用类的run方法执行流程,我们这里先大致看一下WebpackCli的实现。

run方法的执行

run方法里面去加载了构建配置项、版本配置项、监听配置项、帮助配置项等,代码足足有500多行,我们只关注于核心代码。

...
 run(args, parseOptions){ // args为process.argv // parseOptions为装填的解析配置项 ... const loadCommandByName = async (commandName, allowToInstall = false) => { ... if (isBuildCommandUsed || isWatchCommandUsed) { console.log(options, 'options')  // options : {} // 这里执行runWebpack await this.runWebpack(options, isWatchCommandUsed); console.log(options, '
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值