webpack源码深入--- compiler.compile

compiler.compile

compiler.compile

Compiler.prototype.compile方法总览

class Compiler {
    // ...
    compile(callback) {
        // 调用compiler.newCompilationParams()获取创建compilation实例对象的参数
        const params = this.newCompilationParams();
        // 传入参数,触发this.hooks.beforeCompile的钩子
        this.hooks.beforeCompile.callAsync(params, err => {
            // 触发compiler.hooks.compile钩子
            this.hooks.compile.call(params);
            // 创建compilation对象
            const compilation = this.newCompilation(params);
            // 触发make的钩子
            this.hooks.make.callAsync(compilation, err => {
                // 触发finishMake钩子
                this.hooks.finishMake.callAsync(compilation, err => {
                    process.nextTick(() => {
                        // 触发finish钩子
                        compilation.finish(err => {
                            compilation.seal(err => {
                                this.hooks.afterCompile.callAsync(compilation, err => {
                                  return callback(null, compilation);
                                });
                            });
                        });
                    });
                });
            });
        });
    }
}
compiler.newCompilationParams()方法
class Compiler {
    // ...
    newCompilationParams() {  
        const params = {  
            // 常规模块工厂
            normalModuleFactory: this.createNormalModuleFactory(),  
            // 上下文模块中的工厂类
            contextModuleFactory: this.createContextModuleFactory()  
        };  
        return params;  
    }
}
  1. 普通模块: ESM或者commonjs或者cmd/amd的模块规范产物
  2. 上下文模块: 当编译的时候无法具体确定某一个模块,可以直接在webpack上引用一整个目录,把目录中的所有模块都打包,然后等到运行的时候去具体某一个的模块, 这种模块叫上下文模块
createNormalModuleFactory方法
class Compiler { 
    // ...
    createNormalModuleFactory() {
        const normalModuleFactory = new NormalModuleFactory({});   
        this.hooks.normalModuleFactory.call(normalModuleFactory);
        return normalModuleFactory;
    }
}
  • 定义 factory/resolve 等 NMF 与模块创建相关生命周期钩子
  • 格式化webpack.config.js中定义的loader
  • 定义loader和模块的加载解析工作
  • 定义模块构建相关工作
    createcontextmodulefactory方法和上面的方法类似
compiler.hooks.beforeCompile.call方法
  1. DllReferencePlugin:DLL引用插件,就是动态链接库的引用库,在beforeCompile阶段尝试manifest.json,就是DLL清单列表
  2. ProgressPlugin: webpack的构建进度
  3. lazycompilationPlugin: 用于在webpack beforeCompile中针对一些懒加载的入口进行处理。
compiler.hooks.compile

触发compiler.hooks.compile钩子,有几个插件订阅在这个阶段

  1. DLLReferencePlugin: 在compiler.hooks.compile阶段根据配置生成externals对象。
  2. ExternalsPlugin: 处理 external 选项,在该阶段为配置的各个 external 配置 ExternalModuleFactoryPlugin,该插件订阅 NMF 的 factory 阶段为配置的外部模块创建模块,以便这些外部模块可以正常的加入的 webpack runtime 的工作流中
compiler.newCompilation(params)

创建compilation对象,该方法接受前面的params对象

class Compiler { 
    // ...
    newCompilation(params) {
        const compilation = this.createCompilation(params);
        compilation.name = this.name;
        compilation.records = this.records;
        this.hooks.thisCompilation.call(compilation, params);
        this.hooks.compilation.call(compilation, params);
        return compilation;
    }	
    // 创建compilation
    createCompilation(params) {
        this._cleanupLastCompilation();
        return (this._lastCompilation = new Compilation(this, params));
    }
}

compilation是webpack中最重要的对象,相当于是处理具体编译相关事宜的对象。包括模块构建,生成moduleGraph,chunkGraph,以及模块,chunk的相关优化的工作

compiler.hooks.make

有了compilation之后,触发compiler.hooks.make钩子,进入了模块构建阶段。webpackoptionsapply.prototype.process方法注册了EntryOptionsApply,EntryPlugin为每个entry注册了EntryPlugin,而EntryPlugin又订阅了compiler.hooks.make钩子

EntryOptionPlugin

EntryOption订阅了compiler.hooks.entryOption钩子,当钩子触发调用EntryOptionPlugin.applyEntryPlugin根据不同的类型的入口应用不同的类型的入口插件

class EntryOptionPlugin {
    apply(compiler) {
        // 订阅 compiler.hooks.entryOpion 钩子
        compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
            EntryOptionPlugin.applyEntryOption(compiler, context, entry);
            return true;
        });
    }
    static applyEntryOption(compiler, context, entry) {
        if (typeof entry === "function") {
            // 处理动态入口场景
            const DynamicEntryPlugin = require("./DynamicEntryPlugin");
            new DynamicEntryPlugin(context, entry).apply(compiler);
        } else {
            // 初始化 EntryPlugin 插件初始化普通入口
            const EntryPlugin = require("./EntryPlugin");
            for (const name of Object.keys(entry)) {
                const desc = entry[name];
                const options = EntryOptionPlugin.entryDescriptionToOptions(
                    compiler,
                    name,
                    desc
                );
                for (const entry of desc.import) {
                    new EntryPlugin(context, entry, options).apply(compiler);
                }
            }
        }
    }
}
EntryPlugin
class EntryPlugin {
    constructor(context, entry, options) {
        this.context = context;
        this.entry = entry;
        this.options = options || "";
    }
    apply(compiler) {
        compiler.hooks.compilation.tap(
            "EntryPlugin",
            (compilation, { normalModuleFactory }) => {
                compilation.dependencyFactories.set(
                    EntryDependency,
                    normalModuleFactory
                );
            }
        );
        const { entry, options, context } = this;
        const dep = EntryPlugin.createDependency(entry, options);
        compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {
            compilation.addEntry(context, dep, options, err => {
                callback(err);
            });
        });
    }
}
  1. 订阅compiler.hooks.compilation钩子,向EntryDependency设置工厂类为normalModuleFactory
  2. 创建入口依赖并订阅compiler.hooks.make钩子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/760177.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

时序分析之Clock rise/fall edge边沿对选取解析

目录 一、前言 二、Clock edge的选取逻辑 2.1 设计工程 2.2 同频同相 2.3 同频不同相1 2.4 同频不同相2 2.5 倍频关系(Fclk1>Fclk2) 2.6 倍频关系(Fclk1)<> 2.7 倍频关系存在相移(Fclk1)<> 2.8 非倍频关系无相移(Fclk1)<> 2.9 非倍频关系有相移…

在数字化转型中,中小企业如何打造数字化产品和服务?

引言&#xff1a;随着社会的发展和消费者行为的变化&#xff0c;市场对数字化产品和服务的需求日益增长。中小企业需要紧跟这一趋势&#xff0c;通过开发数字化产品和服务来满足消费者的新需求。云计算、大数据、人工智能等先进技术的出现&#xff0c;为中小企业提供了更多的机…

第5章_Modbus通讯协议

文章目录 5.1 学习Modbus的快速方法5.1.1 寄存器速记5.1.2 协议速记 5.2 初识Modbus5.2.1 背景5.2.2 什么是Modbus&#xff1f;1. Modbus简介2. Modbus特点3. Modbus常用术语4. Modbus事务处理 5.3 Modbus软件与使用5.3.1 Modbus软件简介5.3.2 Modbus Poll&#xff08;主站设备…

Pikachu靶场--Sql Inject

参考借鉴 pikachu靶场练习&#xff08;详细&#xff0c;完整&#xff0c;适合新手阅读&#xff09;-CSDN博客 数字型注入(post) 这种类型的SQL注入利用在用户输入处插入数值&#xff0c;而不是字符串。攻击者试图通过输入数字来修改SQL查询的逻辑&#xff0c;以执行恶意操作。…

C# OpenCvSharp 入门

摘要 C# OpenCvSharp 是一个基于OpenCV&#xff08;开源计算机视觉库&#xff09;的C#封装库&#xff0c;它提供了一组功能强大的工具和函数&#xff0c;用于图像处理、计算机视觉和计算机图形学等领域。通过使用OpenCvSharp库&#xff0c;您可以在C#应用程序中轻松地实现各种图…

5.6 0-1背包问题

#include<iostream> #include<string> #include<stdlib.h> #include<bits/stdc.h> using namespace std;int c;//背包容纳的重量 int n;//物品数量 int cw;//当前重量 int cv;//当前价值 int bestv;//当前最优价值 int x[100]; int bestx[100]; struct…

VMware每次打开网络设置都出现需要运行NetworkManager问题

每次打开都出现这个情况&#xff0c;是因为之前把NetworkManager服务服务关闭&#xff0c;重新输入命令&#xff1a; sudo systemctl start NetworkManager.service或者 sudo service network-manager restart 即可解决&#xff0c;但是每次开机重启都要打开就很麻烦&#xf…

无人机赋能工程测绘

勘察设计 业务挑战 采集效率低导致工程周期延长&#xff0c;难以满足及时交付的需求 外业工作量大&#xff0c;人员、时间、设备投入成本高 测绘成果单一&#xff0c;仅限于数字线划图&#xff0c;无法提供可视化模型 无人机优势 快速构建二三维模型&#xff0c;提供丰富…

Go 语言环境搭建

本篇文章为Go语言环境搭建及下载编译器后配置Git终端方法。 目录 安装GO语言SDK Window环境安装 下载 安装测试 安装编辑器 下载编译器 设置git终端方法 总结 安装GO语言SDK Window环境安装 网站 Go下载 - Go语言中文网 - Golang中文社区 还有 All releases - The…

PyTorch使用GPU进行Tensor及模型计算

文章目录 1. 计算设备&#xff1a;GPU/CPU2. Tensor的GPU计算3. 模型的GPU计算 对复杂的神经网络和大规模的数据来说&#xff0c;使用CPU来计算可能不够高效。这里&#xff0c;我们将介绍如何使用单块NVIDIA GPU来计算。 首先&#xff0c;需要确保已经安装好了PyTorch GPU版本…

系统运维面试总结(shell编程)

SYNDDOS攻击&#xff0c;需要判断这个访问是正常访问还是信包攻击&#xff0c;当前这个信包发起的访问数量是多少&#xff0c;例如看到30个信包同时再访问时设置监控报警。

使用LabVIEW报告生成工具包时报错97

问题详情&#xff1a; 在运行使用Excel/Word调用节点的程序时&#xff0c;收到错误97&#xff1a;LabVIEW&#xff1a;&#xff08;十六进制0x61&#xff09;输入中传递了一个空引用句柄或先前已删除的引用句柄。 当运行报告生成工具包中的一个示例程序时&#xff0c;收到错误…

什么是 人工智能(AI)与机器学习(ML)?

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;和机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09;是现代科技的核心概念&#xff0c;它们在不同领域中应用广泛。了解它们之间的关系及其工作原理对理解现代技术至关重要。本文将详细介…

Django 页面展示模型创建表的数据

1&#xff0c;添加视图函数 Test/app8/urls.py from django.shortcuts import render from .models import Userdef create_user(request):if request.method POST:username request.POST.get(username)email request.POST.get(email)# ... 获取其他字段的值# 创建用户实例…

什么是TOGAF架构框架的ADM方法?

ADM是架构开发方法&#xff08; Architecture Development Method&#xff09;&#xff0c;为开发企业架构所要执行的各个步骤以及它们质检的关系进行详细的定义&#xff0c;它是TOGAF规范中最为核心的内容。 ADM的具体步骤&#xff1a; 预备阶段&#xff08;Preliminary Phas…

C# Benchmark

创建控制台项目&#xff08;或修改现有项目的Main方法代码&#xff09;&#xff0c;Nget导入Benchmark0.13.12&#xff0c;创建测试类&#xff1a; public class StringBenchMark{int[] numbers;public StringBenchMark() {numbers Enumerable.Range(1, 20000).ToArray();}[Be…

【每日一练】python运算符

1. 算术运算符 编写一个Python程序&#xff0c;要求用户输入两个数&#xff0c;并执行以下运算&#xff1a;加法、减法、乘法、求余、除法、以及第一个数的第二个数次方。将结果打印出来。 a input("请输入第一个数&#xff1a;") b input("请输入第二个数&…

ffmpeg使用bmp编码器把bgr24编码为bmp图像

version #define LIBAVCODEC_VERSION_MAJOR 60 #define LIBAVCODEC_VERSION_MINOR 15 #define LIBAVCODEC_VERSION_MICRO 100 note 不使用AVOutputFormat code void CFfmpegOps::EncodeBGR24ToBMP(const char* infile, const char* width_str, const char* height_str…

Axure使用小技巧

Axure的小技巧 在这个数字化时代&#xff0c;用户体验设计已成为产品成功的关键。 Axure RP&#xff0c;作为一款强大的原型设计和规格文档工具&#xff0c;为设计师和产品经理提供了一个平台&#xff0c;让他们能够将创意转化为交互式的原型。 然而&#xff0c;Axure的强大…