成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

webpack 源碼分析(四)——complier模塊

tianlai / 3164人閱讀

摘要:源碼分析四模塊上一篇我們看到,通過(guò)對(duì)命令行傳入的參數(shù)和配置文件里的配置項(xiàng)做了轉(zhuǎn)換包裝,然后傳遞給的模塊去編譯。這一篇我們來(lái)看看做了些什么事。在上面的分析中,我們看到最核心的其實(shí)就是實(shí)例,接下來(lái)我們就看下它的類的內(nèi)部邏輯。

webpack 源碼分析(四)——complier模塊

上一篇我們看到,webpack-cli 通過(guò) `yargs 對(duì)命令行傳入的參數(shù)和配置文件里的配置項(xiàng)做了轉(zhuǎn)換包裝,然后傳遞給 webpackcompiler 模塊去編譯。

這一篇我們來(lái)看看 compiler 做了些什么事。

入口

首先,我們來(lái)看看 webpack 是在什么地方引入 Compiler 這個(gè)模塊的,在 webpack/lib/webpack.js 中我們發(fā)現(xiàn),這個(gè)文件第一行就引入了它,并在下面的主要邏輯中使用了它:

const Compiler = require("./Compiler");

……

/*
* options:這就是由 webpack-cli 轉(zhuǎn)換包裝后的配置項(xiàng)
* callback:第二篇分析時(shí),發(fā)現(xiàn) `webpack-cli` 只是傳入了 options對(duì)象來(lái)獲取 `compiler` 對(duì)象,并沒(méi)有傳入回調(diào) 
*/

const webpack = (options, callback) => {

    // 驗(yàn)證配置項(xiàng)的格式
    // webpackOptionsSchema 是一個(gè)json格式的描述文件,它描述了webpack可接受的所有配置項(xiàng)及其格式
    // options 是用戶定義的webpack.config.*.js中導(dǎo)出的所有配置項(xiàng)
    // validateSchema 使用 ajv 包,根據(jù) webpackOptionsSchema 中定義的數(shù)據(jù)類型和描述來(lái)校驗(yàn) options 中的各項(xiàng)配置項(xiàng),最后返回一個(gè)錯(cuò)誤對(duì)象,其中包含所有錯(cuò)誤的配置項(xiàng)及說(shuō)明
    const webpackOptionsValidationErrors = validateSchema(
        webpackOptionsSchema,
        options
    );
    // 如果存在配置項(xiàng)錯(cuò)誤,則拋出所有錯(cuò)誤
    if (webpackOptionsValidationErrors.length) {
        throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
    }
    //判斷配置項(xiàng)是否數(shù)組,如果是數(shù)組則使用MultiCompiler進(jìn)行編譯,否則使用Compiler模塊進(jìn)行編譯,一般情況下,我們的 options 都是對(duì)象不是數(shù)組
    let compiler;
    if (Array.isArray(options)) {
        compiler = new MultiCompiler(options.map(options => webpack(options)));
    } else if (typeof options === "object") {
        //使用默認(rèn)配置項(xiàng)處理輸入配置項(xiàng)
        // WebpackOptionsDefaulter 繼承自 OptionsDefaulter 類
        // 在這個(gè)類里有兩個(gè)對(duì)象:
        //    * this.defaults : 用來(lái)存放配置項(xiàng)的值
        //  * this.config : 用來(lái)存放配置項(xiàng)的值的類型
        // process 方法的處理邏輯:
        //     * 如果defaults對(duì)象中存在,但在config對(duì)象中不存在,并且在options中也不存在,就從 defaults對(duì)象中復(fù)制一份到options中
        //  * 如果在config對(duì)象中存在并且值為 “call”,則說(shuō)明它的值是一個(gè)方法調(diào)用,就直接調(diào)用,并將options作為參數(shù)傳入
        //  * 如果在config對(duì)象中存在且值為 “make”,并且在 options中沒(méi)有,則說(shuō)明它是一個(gè)方法,就直接調(diào)用它,并將options作為參數(shù)傳入,拿到返回值,賦值給options中對(duì)應(yīng)的項(xiàng)
        //  * 如果在config對(duì)象中存在切值為 “append”,則取出options中對(duì)應(yīng)的值,如果它不是數(shù)組,就把它重置為數(shù)組,并且把defaults對(duì)象中的值復(fù)制到數(shù)組中,最后將這個(gè)數(shù)組作為值賦值給options相應(yīng)的項(xiàng)
        options = new WebpackOptionsDefaulter().process(options);
        // new 一個(gè)compiler實(shí)例,參數(shù)為當(dāng)前執(zhí)行node命令的目錄路徑
    // Compiler類繼承自我們上一篇講過(guò)的Tapable類,在構(gòu)造函數(shù)中,初始化了各種類型的鉤子實(shí)例
    // compiler 類的內(nèi)部邏輯,后面詳解++++++++++++++++++++++
        compiler = new Compiler(options.context);
    // WebpackOptionsDefaulter類處理后返回的options 復(fù)制給 compiler
        compiler.options = options;
    // 使用NodeEnviromentPlugin 類給compiler添加文件輸入輸出的能力
    // NodeEnviromentPlugin的內(nèi)部邏輯,后面詳解++++++++++++++++++++++++++
        new NodeEnvironmentPlugin().apply(compiler);
    // 如果配置項(xiàng)中有插件配置并且插件配置為數(shù)組
    // 遍歷插件數(shù)組,如果插件是一個(gè)函數(shù),則使用complier來(lái)調(diào)用它,,并且將compier作為參數(shù)出入
    // 否則,使用 WebpackPluginInstance 的 apply 方法來(lái)返回一個(gè) void 值(相當(dāng)于undefined)
        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);
                }
            }
        }
    // 觸發(fā) environment 同步鉤子,這里的 call() 是我們講過(guò)的Tapable鉤子事件的觸發(fā)方法
    // environment 準(zhǔn)備好之后,執(zhí)行插件
        compiler.hooks.environment.call();
    // 觸發(fā) afterEnvironment 同步鉤子
    // environment 安裝完成之后,執(zhí)行插件
        compiler.hooks.afterEnvironment.call();
    // 使用 WebpackOptionsApply 類處理選項(xiàng),返回處理過(guò)的選項(xiàng)對(duì)象
    // WebpackOptionsApply 的處理邏輯,后面詳解++++++++++++++
        compiler.options = new WebpackOptionsApply().process(options, compiler);
    } else {
    //如果配置既不是數(shù)組類型也不是對(duì)象類型,拋出錯(cuò)誤
        throw new Error("Invalid argument: options");
    }
  // 如果傳入了回到函數(shù)
    if (callback) {
    // 如果回調(diào)不是函數(shù),拋出參數(shù)類型錯(cuò)誤
        if (typeof callback !== "function") {
            throw new Error("Invalid argument: callback");
        }
    // 如果是監(jiān)聽(tīng)模式,或者(配置是數(shù)組且數(shù)組中的項(xiàng)中有監(jiān)聽(tīng)選項(xiàng)為true),則初始化監(jiān)聽(tīng)配置,最后返回compiler實(shí)例的監(jiān)聽(tīng)方法
    // 實(shí)例的監(jiān)聽(tīng)方法會(huì)返回一個(gè) Watching類的實(shí)例,它本質(zhì)上是一個(gè)觀察者
        if (
            options.watch === true ||
            (Array.isArray(options) && options.some(o => o.watch))
        ) {
            const watchOptions = Array.isArray(options)
                ? options.map(o => o.watchOptions || {})
                : options.watchOptions || {};
            return compiler.watch(watchOptions, callback);
        }
    // 使用compiler的run方法運(yùn)行回調(diào)
        compiler.run(callback);
    }
  //返回compiler實(shí)例
    return compiler;
};

通過(guò)以上源碼分析,我們得知,在 webpack() 中,實(shí)際上總共做了三件事:

對(duì)參數(shù)進(jìn)行校驗(yàn)和規(guī)范化處理;

new 一個(gè)編譯器實(shí)例并且初始化各種tapable鉤子,并且在環(huán)境準(zhǔn)備好和安裝完成后執(zhí)行響應(yīng)的鉤子

初始化監(jiān)聽(tīng)。

在上面的分析中,我們看到最核心的其實(shí)就是compiler實(shí)例,接下來(lái)我們就看下它的類的內(nèi)部邏輯。

compiler 分析 主體結(jié)構(gòu)

首先,我們來(lái)看主要結(jié)構(gòu):

/*…… *// 各種引入

// Compiler 類繼承自Tapable
class Compiler extends Tapable {
    constructor(context) {……}//構(gòu)造函數(shù)執(zhí)行各種初始化操作
    watch(watchOptions, handler) {……}//監(jiān)聽(tīng)初始化
    run(callback) {……}// 運(yùn)行編譯
    runAsChild(callback) {...} // 作為子編譯進(jìn)程運(yùn)行
    purgeInputFileSystem() {...} // 凈化輸入
    emitAssets(compilation, callback) {...} // 發(fā)布資源
    emitRecords(callback) {...} // 發(fā)布記錄
    readRecords(callback) {...} // 讀取記錄
    createChildCompiler(
        compilation,
        compilerName,
        compilerIndex,
        outputOptions,
        plugins
    ) {...} // 創(chuàng)建子編譯器
    isChild() {return !!this.parentCompilation;} // 是否子匯編
    createCompilation() {return new Compilation(this);} // 創(chuàng)建匯編實(shí)例
    newCompilation(params) {return compilation;} // 根據(jù)參數(shù)創(chuàng)建新的匯編實(shí)例
    createNormalModuleFactory() {return normalModuleFactory;} // 創(chuàng)建普通模塊的工廠
    createContextModuleFactory() {return contextModuleFactory;} // 創(chuàng)建上下文模塊的工廠
    newCompilationParams() {return params;} // 獲取一個(gè)新的匯編參數(shù)對(duì)象
    compile(callback) {} // 編譯
}

module.exports = Compiler;

class SizeOnlySource extends Source {} // 定義了一個(gè)類,作用是+++++++++++

下一講,我們將逐個(gè)攻破

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/110319.html

相關(guān)文章

  • 【提高系列】webpack相關(guān)知識(shí)

    摘要:基本配置項(xiàng)基本配置項(xiàng)。的插件架構(gòu)主要基于實(shí)現(xiàn)的,這個(gè)就是專注于事件的廣播和操作。開(kāi)啟多進(jìn)程,加快打包速度。 這次我們主要研究的是webpack框架的相關(guān)知識(shí),webpack是一個(gè)打包構(gòu)建的前端框架,用于解決前端開(kāi)發(fā)的模塊化問(wèn)題。 應(yīng)用場(chǎng)景和縱向比較 說(shuō)到webpack,肯定你還會(huì)想到gulp和grunt這些框架,那么webpack是做什么的呢?他和其他的框架有什么區(qū)別呢?我們一起來(lái)分析...

    DirtyMind 評(píng)論0 收藏0
  • 用十分之一的構(gòu)建時(shí)間做一場(chǎng)頁(yè)面靜態(tài)資源依賴分析

    摘要:不直接使用的原因很簡(jiǎn)單首先構(gòu)建一次實(shí)在太慢了,特別是有幾十個(gè)頁(yè)面存在的情況下,另一個(gè)原因是我只是想拿到資源依賴,我根本不想對(duì)整個(gè)前端進(jìn)行一次構(gòu)建,也不想生成任何。這就達(dá)到了本文題目中目的,用十分之一的構(gòu)建時(shí)間做一場(chǎng)頁(yè)面靜態(tài)資源依賴分析。原文鏈接 作者:梯田 前言: 所謂【靜態(tài)資源依賴分析】,指的是可以通過(guò)分析頁(yè)面資源后,可以以 json 數(shù)據(jù)或者圖表的方式拿到頁(yè)面資源間的依賴關(guān)系。 比如 c...

    B0B0 評(píng)論0 收藏0
  • 你想要的——webpack構(gòu)建過(guò)程分析

    摘要:類定義了方法,用于注冊(cè)插件,將插件及其回調(diào)函數(shù)以的形式保存在內(nèi)部對(duì)象中又定義了,等方法來(lái)觸發(fā)插件的回調(diào)函數(shù)。所以當(dāng)類繼承類后,也同樣具有注冊(cè)插件和觸發(fā)回調(diào)函數(shù)的功能。 說(shuō)起webpack,相信對(duì)于前端工程師們而言早已經(jīng)不是什么新鮮的事物。但是由于webpack有著較為復(fù)雜和靈活的配置項(xiàng),所以給人的第一感覺(jué)是難以完全掌握。 這次就跟大家分享一下有關(guān)webpack構(gòu)建過(guò)程的相關(guān)知識(shí),希望對(duì)...

    Lycheeee 評(píng)論0 收藏0
  • webpack4.x升級(jí)摘要

    摘要:以為例,編寫來(lái)幫助我們完成重復(fù)的工作編譯壓縮我只要執(zhí)行一下就可以檢測(cè)到文件的變化,然后為你執(zhí)行一系列的自動(dòng)化操作,同樣的操作也發(fā)生在這些的預(yù)處理器上。的使用是針對(duì)第三方類庫(kù)使用各種模塊化寫法以及語(yǔ)法。 showImg(https://segmentfault.com/img/bVbtZYK); 一:前端工程化的發(fā)展 很久以前,互聯(lián)網(wǎng)行業(yè)有個(gè)職位叫做 軟件開(kāi)發(fā)工程師 在那個(gè)時(shí)代,大家可能...

    levinit 評(píng)論0 收藏0
  • Webpack Loader簡(jiǎn)析(一):基本概念

    摘要:需要得到最后一個(gè)產(chǎn)生的處理結(jié)果。這個(gè)處理結(jié)果應(yīng)該是或者被轉(zhuǎn)換為一個(gè),代表了模塊的源碼。另外還可以傳遞一個(gè)可選的結(jié)果格式為對(duì)象。在異步模式中,必須調(diào)用,來(lái)指示等待異步結(jié)果,它會(huì)返回回調(diào)函數(shù),隨后必須返回并且調(diào)用該回調(diào)函數(shù)。 準(zhǔn)備工作 安裝 Node.js, 建議安裝LTS長(zhǎng)期支持版本 mkdir webpack and cd webpack and npm init -y npm ...

    sherlock221 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<