亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Loader學(xué)習(xí),簡(jiǎn)析babel-loader

wpw / 1844人閱讀

摘要:用來轉(zhuǎn)換內(nèi)容,內(nèi)部調(diào)用了方法進(jìn)行轉(zhuǎn)換,這里簡(jiǎn)單介紹一下的原理將代碼解析成,對(duì)進(jìn)行轉(zhuǎn)譯,得到新的,新的通過轉(zhuǎn)換成,核心方法在中的方法,有興趣可以去了解一下。將函數(shù)傳入?yún)?shù)和歸并,得到。通常我們是用不上的,估計(jì)在某些中可能會(huì)使用到。

什么是Loader?

繼上兩篇文章webpack工作原理介紹(上篇、下篇),我們了解到Loader:模塊轉(zhuǎn)換器,也就是將模塊的內(nèi)容按照需求裝換成新內(nèi)容,而且每個(gè)Loader的職責(zé)都是單一,只會(huì)完成一種轉(zhuǎn)換,所以我們一般對(duì)源文件的處理,也是由多個(gè)Loader以鏈?zhǔn)巾樞驁?zhí)行的方式來進(jìn)行多次裝換,然后得到我們要的結(jié)果。

那么這樣Loader只需要關(guān)心輸入和輸出,Loader其實(shí)是一個(gè)Node.js模塊,該模塊導(dǎo)出的是一個(gè)函數(shù)(意味著,所有node.js的api我們都可以使用),如下:

    module.exports = function (source) {
        // 對(duì)source做一系列的轉(zhuǎn)換
        return source;
    }

下面我們介紹一下webpack提供了哪些供Loader調(diào)用的api,對(duì)Loader有個(gè)比較深刻的理解,然后來分析babel-loader的源碼,看看我們常用的loader是怎么編寫出來的。

獲得Loader的options
    const loaderUtils = require("loader-utils");
    module.exports = function(source) {
        // 獲取用戶為當(dāng)前Loader傳入的options
        console.log(loaderUtils.getOptions(this));
        return source;
    }
返回其他結(jié)果

如上,我們返回的是轉(zhuǎn)換后的內(nèi)容,但是有些情況下,我們不僅僅需要返回轉(zhuǎn)換后的內(nèi)容,還需要返回一些其他的內(nèi)容,如sourceMap或是AST語(yǔ)法樹,那么這時(shí)候我們可以使用webpack提供的APIthis.callback,當(dāng)使用this.callback了,那么我們就必須需要在Loader函數(shù)返回undefined,以此來讓webpack知道返回的結(jié)果在this.callback中,API詳細(xì)參數(shù)如下:

    this.callback(
        // 無法裝換原內(nèi)容時(shí)的Error
        err: Error || null,
        // 裝換后的的內(nèi)容,如上述的source
        content: string | Buffer,
        // 用于通過裝換后的內(nèi)容得出原內(nèi)容的Source Map,方便調(diào)試
        // 我們了解到,SourceMap我們只是會(huì)在開發(fā)環(huán)境去使用,于是就會(huì)變成可控制的,
        // webpack也提供了this.sourceMap去告訴是否需要使用sourceMap,
        // 當(dāng)然也可以使用loader的option來做判斷,如css-loader
        sourceMap?: SourceMap,
        // 如果本次轉(zhuǎn)換同時(shí)生成ast語(yǔ)法樹,也可以將這個(gè)ast返回,方便后續(xù)loader需要復(fù)用該ast,這樣可以提高性能
        abstractSyntaxTree? AST
    );
同步與異步

看看異步Loader在this.asyncAPI下如何實(shí)現(xiàn),

    module.exports = async function (source) {
        const callback = this.async();
        const { err, content, sourceMap, AST } = await Func();
        callback(err, content, sourceMap, AST); // 如上訴`this.callback`參數(shù)一樣
    }
處理二進(jìn)制數(shù)據(jù)

file-loader這樣的Loader,處理的是二進(jìn)制數(shù)據(jù),那么就需要告訴webpack給loader傳入二進(jìn)制格式的數(shù)據(jù),代碼可以如下:

    module.exports = function(source) {
        if (source instanceof Buffer) {
            // 一系列操作
            return source; //當(dāng)然我本身也可以返回二進(jìn)制數(shù)據(jù)提供給下一個(gè)loader
        }
    }
    moudle.exports.raw = true; //不設(shè)置,就會(huì)拿到字符串

通過moudle.exports.raw = true;告知webpack,自己本身需要二進(jìn)制數(shù)據(jù)。

緩存加速

優(yōu)化的最佳點(diǎn),可以使用this.cacheable(Boolen),緩存loader轉(zhuǎn)換后的內(nèi)容,當(dāng)處理文件或依賴文件沒有發(fā)生變化時(shí),使用緩存的轉(zhuǎn)換內(nèi)容,以此提速!

其他API

說到學(xué)習(xí),當(dāng)然越系統(tǒng)越好了,api多介紹 ,除了上面常用的api之外,還存在以下常用的api。

this.context: 當(dāng)前處理轉(zhuǎn)換的文件所在的目錄

this.resource: 當(dāng)前處理轉(zhuǎn)換的文件完整請(qǐng)求路徑,包括querystring

this.resourcePath: 當(dāng)前處理轉(zhuǎn)換的文件的路徑

this.resourceQuery: 當(dāng)前處理文件的querystring

this.target: webpack配置的target

this.loadMoudle: 處理文件時(shí),需要依賴其他文件的處理結(jié)果時(shí),可以使用this.loadMoudle(request: string, callback: function(err, source, sourceMap, module))去獲取到依賴文件的處理結(jié)果。

this.resolve: 獲取指定文件的完整路徑,this.resolve(context: string, request: string, callback: function(err, result: string))

this.addDependency: 為當(dāng)前處理文件添加依賴文件,以便依賴文件發(fā)生變化時(shí)重新調(diào)用Loader轉(zhuǎn)換該文件,this.addDependency(file: string)

this.addContextDependency: 為當(dāng)前處理文件添加依賴文件目錄,以便依賴文件目錄里文件發(fā)生變化時(shí)重新調(diào)用Loader轉(zhuǎn)換該文件,this.addContextDependency(dir: string)

this.clearDependencies: 清除當(dāng)前正在處理的文件的所有依賴

this.emitFile: 輸出一個(gè)文件,使用的方法為this.emitFile(name: string, content: Buffer | string, sourceMap: {...})

babel-loader源碼簡(jiǎn)析

源碼第一行如下:

    let babel;
    try {
        babel = require("@babel/core");
    } catch (err) {
        if (err.code === "MODULE_NOT_FOUND") {
            err.message +=
            "
 babel-loader@8 requires Babel 7.x (the package "@babel/core"). " +
            "If you"d like to use Babel 6.x ("babel-core"), you should install "babel-loader@7".";
        }
        throw err;
    }

babel-loader依賴了@babel/core,這就是安裝babel-loader需要同時(shí)安裝@babel/core(通常會(huì)再安裝babel-preset-envbabel-plugin-transform-runtime、babel-runtime)的原因。我們接下去看,src/index.js整個(gè)文件是不是按照我們前面所講編寫Loader的方法來組織代碼的。

//引入package.json
const pkg = require("../package.json");
/* 
根據(jù)babel-loader是否配置cacheDirectory屬性來告訴
babel-loader是否緩存loader的執(zhí)行結(jié)果,如果true,
便會(huì)使用cache方法去實(shí)現(xiàn),`cache.js`文件有著read、write、filename(文件命名方法)
以及如何處理緩存的handleCache方法(有則讀,無則寫再讀),有興趣可以去看看。
*/
const cache = require("./cache");
/*
    transfrom.js用來轉(zhuǎn)換內(nèi)容,內(nèi)部調(diào)用了babel.transform方法進(jìn)行轉(zhuǎn)換,這里簡(jiǎn)單介紹一下babel的原理:
    babylon將es6/es7代碼解析成ast,babel-traverse對(duì)ast進(jìn)行轉(zhuǎn)譯,得到新的ast,新的ast通過
    babel-generator轉(zhuǎn)換成es5,核心方法在@babel/core/lib/transformation/index.js中的`runSync`
    方法,有興趣可以去了解一下。
*/
const transform = require("./transform");
const injectCaller = require("./injectCaller");
const path = require("path");
// 獲取Loader參數(shù)options
const loaderUtils = require("loader-utils");

module.exports = makeLoader();
module.exports.custom = makeLoader;

function makeLoader(callback) {
  const overrides = callback ? callback(babel) : undefined;

  return function(source, inputSourceMap) {
    // 上面介紹過的api可以得知,這是個(gè)異步Loader,做的是異步裝換的工作
    const callback = this.async();

    loader
      .call(this, source, inputSourceMap, overrides)
      .then(args => callback(null, ...args), err => callback(err));
  };
}

async function loader(source, inputSourceMap, overrides) {
    ....
}

可以看到確實(shí)和我們Loader編寫方式是一樣的,通過module.exports = makeLoader();導(dǎo)出一個(gè)函數(shù),makeLoader()是一個(gè)高階函數(shù),又返回了一個(gè)函數(shù),通過const callback = this.async();可以知道,這是一個(gè)異步的loader,不難看出最重要的實(shí)現(xiàn)都在這一步函數(shù)loader里面了,那么到底在loader函數(shù)里面究竟做了些什么呢?我們來看看,在閱讀源碼前,最好先看看babel-loader的README,先做個(gè)基本了解.

上面代碼可以看出loader(source, inputSourceMap, overrides)函數(shù)入?yún)⒂腥齻€(gè),分別是source=>待轉(zhuǎn)換的code,inputSourceMap=>上一個(gè)loader處理后的sourceMap,有的話,overrides=>自定義加載器,整塊源碼可以分成幾部分,

let loaderOptions = loaderUtils.getOptions(this) || {};,獲取options,并且獲取當(dāng)前處理轉(zhuǎn)換的文件的路徑this.resourcePath

判斷是否自定義加載器轉(zhuǎn)換,這里會(huì)進(jìn)行一系列對(duì)options.customize進(jìn)行判斷,options.customize一個(gè)相對(duì)路徑,loader函數(shù)參數(shù)overrides為空時(shí)起效,執(zhí)行let override = require(loaderOptions.customize);,有了override之后,后續(xù)邏輯(如轉(zhuǎn)換、獲取option)override都會(huì)進(jìn)行介入處理。

將函數(shù)傳入?yún)?shù)和LoaderOptions歸并,得到programmaticOptions。

調(diào)用babel.loadPartialConfig可以拿到babel配置并賦值給config變量,其實(shí)就是為了允許系統(tǒng)輕松操作和驗(yàn)證用戶的配置,此功能解決了插件和預(yù)設(shè)

生成cacheIdentifier

判斷options.cacheDirectory是否需要緩存Loader轉(zhuǎn)換內(nèi)容,如為true,調(diào)用cache.js的module.export Cache方法(上面已做介紹)

config.babelrc不為空,則有.babelrc文件,依賴.babelrc文件變化,使用this.addDependency(config.babelrc);

metadataSubscribers 訂閱元數(shù)據(jù),主要作用是訂閱一些編譯過程中的一些元數(shù)據(jù),訂閱以后這些元數(shù)據(jù)將會(huì)被添加 到webpack的上下文中。通常我們是用不上的,估計(jì)在某些babel-plugin中可能會(huì)使用到。

最后將處理后的結(jié)果返回

小結(jié)

每一個(gè)Loader其實(shí)返回值就是一個(gè)Function,而且就是把帶轉(zhuǎn)換內(nèi)容傳入,得到轉(zhuǎn)換后的內(nèi)容,做的事情就是這樣,這篇文章先對(duì)Loader的基本概念進(jìn)行介紹,并且了解webpack為L(zhǎng)oader的編寫提供一些常用的API,最后通過簡(jiǎn)析babel-loader的源碼,我覺得應(yīng)該差不多知道如何去寫一個(gè)簡(jiǎn)單的Loader了,原文地址-個(gè)人博客。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109116.html

相關(guān)文章

  • Webpack模塊化原理簡(jiǎn)析

    摘要:模塊化原理簡(jiǎn)析的核心原理一切皆模塊在中,,靜態(tài)資源文件等都可以視作模塊便于管理,利于重復(fù)利用按需加載進(jìn)行代碼分割,實(shí)現(xiàn)按需加載。模塊化原理以為例,分析構(gòu)建的模塊化方式。 webpack模塊化原理簡(jiǎn)析 1.webpack的核心原理 一切皆模塊:在webpack中,css,html.js,靜態(tài)資源文件等都可以視作模塊;便于管理,利于重復(fù)利用; 按需加載:進(jìn)行代碼分割,實(shí)現(xiàn)按需加載。 2...

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

    摘要:需要得到最后一個(gè)產(chǎn)生的處理結(jié)果。這個(gè)處理結(jié)果應(yīng)該是或者被轉(zhuǎn)換為一個(gè),代表了模塊的源碼。另外還可以傳遞一個(gè)可選的結(jié)果格式為對(duì)象。在異步模式中,必須調(diào)用,來指示等待異步結(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
  • webpack多頁(yè)應(yīng)用架構(gòu)系列(八):教練我要寫ES6!webpack怎么整合Babel?

    摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。只是最近學(xué)習(xí)生態(tài),用起來轉(zhuǎn)換之余,也不免碰到諸多用上的教程案例,因此便稍作學(xué)習(xí)。在當(dāng)前的瀏覽器市場(chǎng)下,想在生產(chǎn)環(huán)境用上,是必不可少的。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006992218如果您對(duì)本系列文章感興...

    gnehc 評(píng)論0 收藏0
  • webpack配置 babel

    摘要:三集成所需要的依賴和在或加載模塊時(shí),對(duì)代碼進(jìn)行預(yù)處理,語(yǔ)法轉(zhuǎn)化為語(yǔ)法。到目前位置,用于開發(fā)應(yīng)用的環(huán)境已經(jīng)配置好了。 本系列主要學(xué)習(xí)webpack的配置。webpack自己間接的用過不少次,但是自己配置卻沒多少次,所以特地寫寫文章,學(xué)習(xí)webpack的配置,有不恰當(dāng)?shù)牡胤?,歡迎指正。這次配置 babel 。 若你對(duì)webpack的概念還不了解,先查看相應(yīng)文檔webpack中文文檔 一、初...

    Songlcy 評(píng)論0 收藏0
  • webpack學(xué)習(xí)(一)

    摘要:四用于對(duì)模塊的源代碼進(jìn)行轉(zhuǎn)換。對(duì)于圖片等都不能識(shí)別,所有需要引入對(duì)應(yīng)的對(duì)對(duì)應(yīng)格式的文件進(jìn)行轉(zhuǎn)換以便來識(shí)別。支持鏈?zhǔn)秸{(diào)用,調(diào)用順序由下到上,由右到左五插件目的在于解決無法實(shí)現(xiàn)的其他事。 一.entry entry是webpack打包的入口配置,entry對(duì)應(yīng)的值可以是字符串,數(shù)組,對(duì)象;單入口可以使用字符串、數(shù)組、對(duì)象,多入口配置則必須使用對(duì)象的方式 二.output output是we...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<