国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Loader學習,簡析babel-loader

wpw / 1779人閱讀

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

什么是Loader?

繼上兩篇文章webpack工作原理介紹(上篇、下篇),我們了解到Loader:模塊轉換器,也就是將模塊的內容按照需求裝換成新內容,而且每個Loader的職責都是單一,只會完成一種轉換,所以我們一般對源文件的處理,也是由多個Loader以鏈式順序執(zhí)行的方式來進行多次裝換,然后得到我們要的結果。

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

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

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

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

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

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

看看異步Loader在this.asyncAPI下如何實現(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ù)一樣
    }
處理二進制數(shù)據(jù)

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

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

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

緩存加速

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

其他API

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

this.context: 當前處理轉換的文件所在的目錄

this.resource: 當前處理轉換的文件完整請求路徑,包括querystring

this.resourcePath: 當前處理轉換的文件的路徑

this.resourceQuery: 當前處理文件的querystring

this.target: webpack配置的target

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

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

this.addDependency: 為當前處理文件添加依賴文件,以便依賴文件發(fā)生變化時重新調用Loader轉換該文件,this.addDependency(file: string)

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

this.clearDependencies: 清除當前正在處理的文件的所有依賴

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

babel-loader源碼簡析

源碼第一行如下:

    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需要同時安裝@babel/core(通常會再安裝babel-preset-envbabel-plugin-transform-runtimebabel-runtime)的原因。我們接下去看,src/index.js整個文件是不是按照我們前面所講編寫Loader的方法來組織代碼的。

//引入package.json
const pkg = require("../package.json");
/* 
根據(jù)babel-loader是否配置cacheDirectory屬性來告訴
babel-loader是否緩存loader的執(zhí)行結果,如果true,
便會使用cache方法去實現(xiàn),`cache.js`文件有著read、write、filename(文件命名方法)
以及如何處理緩存的handleCache方法(有則讀,無則寫再讀),有興趣可以去看看。
*/
const cache = require("./cache");
/*
    transfrom.js用來轉換內容,內部調用了babel.transform方法進行轉換,這里簡單介紹一下babel的原理:
    babylon將es6/es7代碼解析成ast,babel-traverse對ast進行轉譯,得到新的ast,新的ast通過
    babel-generator轉換成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可以得知,這是個異步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) {
    ....
}

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

上面代碼可以看出loader(source, inputSourceMap, overrides)函數(shù)入參有三個,分別是source=>待轉換的codeinputSourceMap=>上一個loader處理后的sourceMap,有的話overrides=>自定義加載器,整塊源碼可以分成幾部分,

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

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

將函數(shù)傳入參數(shù)和LoaderOptions歸并,得到programmaticOptions。

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

生成cacheIdentifier

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

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

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

最后將處理后的結果返回

小結

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

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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109116.html

相關文章

  • Webpack模塊化原理簡析

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

    tracy 評論0 收藏0
  • Webpack Loader簡析(一):基本概念

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

    sherlock221 評論0 收藏0
  • webpack多頁應用架構系列(八):教練我要寫ES6!webpack怎么整合Babel?

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

    gnehc 評論0 收藏0
  • webpack配置 babel

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

    Songlcy 評論0 收藏0
  • webpack學習(一)

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

    codecraft 評論0 收藏0

發(fā)表評論

0條評論

wpw

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<