alian926 / daily

学习计划以及总结
0 stars 0 forks source link

21.9.8。桥北雨余春水生,桥南日落暮山横。问君对酒胡不乐?听取菱歌烟外声。 #17

Open alian926 opened 3 years ago

alian926 commented 3 years ago

webpack

资料参考 https://mp.weixin.qq.com/s?__biz=MzI0MTUxOTE5NQ==&mid=2247484030&idx=1&sn=d630d4b3995bbfd50f99e781074acfeb

基本内容

const {
    SyncHook,  // 同步钩子
    SyncBailHook, // 同步熔断钩子
    SyncWaterfallHook, // 同步流水钩子
    SyncLoopHook, // 同步循环钩子
    AsyncParallelHook, // 异步并发钩子
    AsyncParallelBailHook, // 异步并发熔断钩子
    AsyncSeriesHook, // 异步串行钩子
    AsyncSeriesBailHook, // 异步串行熔断钩子
    AsyncSeriesWaterfallHook // 异步串行流水钩子
 } = require("tapable");
const hook = new SyncHook(["arg1", "arg2", "arg3"]);

image

绑定、执行的方法

Async*
绑定: tapAsync/tapPromise/tap   执行: callAsync/promise
Sync*
绑定: tap                       执行: call

例子

const { SyncHook } = require("tapable");
let queue = new SyncHook(['name']); //所有的构造函数都接收一个可选的参数,这个参数是一个字符串的数组。

// 订阅
queue.tap('1', function (name, name2) {// tap 的第一个参数是用来标识订阅的函数的
    console.log(name, name2, 1);
    return'1'
});
queue.tap('2', function (name) {
    console.log(name, 2);
});
queue.tap('3', function (name) {
    console.log(name, 3);
});

// 发布
queue.call('webpack', 'webpack-cli');// 发布的时候触发订阅的函数 同时传入参数

// 执行结果:
/*
webpack undefined 1 // 传入的参数需要和new实例的时候保持一致,否则获取不到多传的参数
webpack 2
webpack 3
*/

webpack中的例子

if (Array.isArray(options)) {
        compiler = new MultiCompiler(
            Array.from(options).map(options => webpack(options))
        );
    } elseif (typeof options === "object") {
        // 1 做初始的操作
        options = new WebpackOptionsDefaulter().process(options);

        compiler = new Compiler(options.context);
        compiler.options = options;
        // 2  必须插件有apply接受compiler 参数
        new NodeEnvironmentPlugin({
            infrastructureLogging: options.infrastructureLogging
        }).apply(compiler);
        // 插件接收compiler对象上的hooks,议案事件触发,插件也会执行操作
        if (options.plugins && Array.isArray(options.plugins)) {
            for (const plugin of options.plugins) {
                if (typeof plugin === "function") {
                    plugin.call(compiler, compiler);
                } else {
                    plugin.apply(compiler);
                }
            }
        }
        compiler.hooks.environment.call();
        compiler.hooks.afterEnvironment.call();
        compiler.options = new WebpackOptionsApply().process(options, compiler);
    }

流程概览

Webpack首先会把配置参数和命令行的参数及默认参数合并,并初始化需要使用的插件和配置插件等执行环境所需要的参数;初始化完成后会调用Compiler的run来真正启动webpack编译构建过程,webpack的构建流程包括compile、make、build、seal、emit阶段,执行完这些阶段就完成了构建过程。

  1. 初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
  2. 开始编译: 根据我们的webpack配置注册好对应的插件调用 compile.run 进入编译阶段,在编译的第一阶段是 compilation,他会注册好不同类型的module对应的 factory,不然后面碰到了就不知道如何处理了。
  3. 编译模块: 进入 make 阶段,会从 entry 开始进行两步操作:第一步是调用 loaders 对模块的原始代码进行编译,转换成标准的JS代码, 第二步是调用 acorn 对JS代码进行语法分析,然后收集其中的依赖关系。每个模块都会记录自己的依赖关系,从而形成一颗关系树。
  4. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
  5. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
alian926 commented 3 years ago

流程详解

分为三个阶段: 初始化阶段,编译阶段,输出文件(chunk)。

初始化阶段:

编译阶段

输出阶段