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

資訊專欄INFORMATION COLUMN

Webpack Loader 高手進(jìn)階(一)

MAX_zuo / 2839人閱讀

摘要:在一個構(gòu)建過程中,首先根據(jù)的依賴類型例如調(diào)用對應(yīng)的構(gòu)造函數(shù)來創(chuàng)建對應(yīng)的模塊。

文章首發(fā)于個人github blog: Biu-blog,歡迎大家關(guān)注~

Webpack 系列文章:

Webpack Loader 高手進(jìn)階(一)
Webpack Loader 高手進(jìn)階(二)
Webpack Loader 高手進(jìn)階(三)

Webpack loader 詳解 loader 的配置

Webpack 對于一個 module 所使用的 loader 對開發(fā)者提供了2種使用方式:

webpack config 配置形式,形如:

// webpack.config.js
module.exports = {
  ...
  module: {
    rules: [{
      test: /.vue$/,
      loader: "vue-loader"
    }, {
      test: /.scss$/,
      use: [
        "vue-style-loader",
        "css-loader",
        {
          loader: "sass-loader",
          options: {
            data: "$color: red;"
          }
        }
      ]
    }]
  }
  ...
}

inline 內(nèi)聯(lián)形式

// module

import a from "raw-loader!../../utils.js"

2種不同的配置形式,在 webpack 內(nèi)部有著不同的解析方式。此外,不同的配置方式也決定了最終在實(shí)際加載 module 過程中不同 loader 之間相互的執(zhí)行順序等。

loader 的匹配

在講 loader 的匹配過程之前,首先從整體上了解下 loader 在整個 webpack 的 workflow 過程中出現(xiàn)的時機(jī)。

在一個 module 構(gòu)建過程中,首先根據(jù) module 的依賴類型(例如 NormalModuleFactory)調(diào)用對應(yīng)的構(gòu)造函數(shù)來創(chuàng)建對應(yīng)的模塊。在創(chuàng)建模塊的過程中(new NormalModuleFactory()),會根據(jù)開發(fā)者的 webpack.config 當(dāng)中的 rules 以及 webpack 內(nèi)置的 rules 規(guī)則實(shí)例化 RuleSet 匹配實(shí)例,這個 RuleSet 實(shí)例在 loader 的匹配過濾過程中非常的關(guān)鍵,具體的源碼解析可參見Webpack Loader Ruleset 匹配規(guī)則解析。實(shí)例化 RuleSet 后,還會注冊2個鉤子函數(shù):

class NormalModuleFactory {
  ...
  // 內(nèi)部嵌套 resolver 的鉤子,完成相關(guān)的解析后,創(chuàng)建這個 normalModule
  this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => { ... })

  // 在 hooks.factory 的鉤子內(nèi)部進(jìn)行調(diào)用,實(shí)際的作用為解析構(gòu)建一共 module 所需要的 loaders 及這個 module 的相關(guān)構(gòu)建信息(例如獲取 module 的 packge.json等)
  this.hooks.resolver.tap("NormalModuleFactory", () => (result, callback) => { ... })
  ...
}

當(dāng) NormalModuleFactory 實(shí)例化完成后,并在 compilation 內(nèi)部調(diào)用這個實(shí)例的 create 方法開始真實(shí)開始創(chuàng)建這個 normalModule。首先調(diào)用hooks.factory獲取對應(yīng)的鉤子函數(shù),接下來就調(diào)用 resolver 鉤子(hooks.resolver)進(jìn)入到了 resolve 的階段,在真正開始 resolve loader 之前,首先就是需要匹配過濾找到構(gòu)建這個 module 所需要使用的所有的 loaders。首先進(jìn)行的是對于 inline loaders 的處理:

// NormalModuleFactory.js

// 是否忽略 preLoader 以及 normalLoader
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
// 是否忽略 normalLoader
const noAutoLoaders =
  noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
// 忽略所有的 preLoader / normalLoader / postLoader
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");

// 首先解析出所需要的 loader,這種 loader 為內(nèi)聯(lián)的 loader
let elements = requestWithoutMatchResource
  .replace(/^-?!+/, "")
  .replace(/!!+/g, "!")
  .split("!");
let resource = elements.pop(); // 獲取資源的路徑
elements = elements.map(identToLoaderRequest); // 獲取每個loader及對應(yīng)的options配置(將inline loader的寫法變更為module.rule的寫法)

首先是根據(jù)模塊的路徑規(guī)則,例如模塊的路徑是以這些符號開頭的 ! / -! / !! 來判斷這個模塊是否只是使用 inline loader,或者剔除掉 preLoader, postLoader 等規(guī)則:

! 忽略 webpack.config 配置當(dāng)中符合規(guī)則的 normalLoader

-! 忽略 webpack.config 配置當(dāng)中符合規(guī)則的 preLoader/normalLoader

!! 忽略 webpack.config 配置當(dāng)中符合規(guī)則的 postLoader/preLoader/normalLoader

這幾個匹配規(guī)則主要適用于在 webpack.config 已經(jīng)配置了對應(yīng)模塊使用的 loader,但是針對一些特殊的 module,你可能需要多帶帶的定制化的 loader 去處理,而不是走常規(guī)的配置,因此可以使用這些規(guī)則來進(jìn)行處理。

接下來將所有的 inline loader 轉(zhuǎn)化為數(shù)組的形式,例如:

import "style-loader!css-loader!stylus-loader?a=b!../../common.styl"

最終 inline loader 統(tǒng)一格式輸出為:

[{
  loader: "style-loader",
  options: undefined
}, {
  loader: "css-lodaer",
  options: undefined
}, {
  loader: "stylus-loader",
  options: "?a=b"
}]

對于 inline loader 的處理便是直接對其進(jìn)行 resolve,獲取對應(yīng) loader 的相關(guān)信息:

asyncLib.parallel([
  callback => 
    this.resolveRequestArray(
      contextInfo,
      context,
      elements,
      loaderResolver,
      callback
    ),
  callback => {
    // 對這個 module 進(jìn)行 resolve
    ...
    callack(null, {
      resouceResolveData, // 模塊的基礎(chǔ)信息,包含 descriptionFilePath / descriptionFileData 等(即 package.json 等信息)
      resource // 模塊的絕對路徑
    })
  }
], (err, results) => {
  const loaders = results[0] // 所有內(nèi)聯(lián)的 loaders
  const resourceResolveData = results[1].resourceResolveData; // 獲取模塊的基本信息
  resource = results[1].resource; // 模塊的絕對路徑
  ...
  
  // 接下來就要開始根據(jù)引入模塊的路徑開始匹配對應(yīng)的 loaders
  let resourcePath =
    matchResource !== undefined ? matchResource : resource;
  let resourceQuery = "";
  const queryIndex = resourcePath.indexOf("?");
  if (queryIndex >= 0) {
    resourceQuery = resourcePath.substr(queryIndex);
    resourcePath = resourcePath.substr(0, queryIndex);
  }
  // 獲取符合條件配置的 loader,具體的 ruleset 是如何匹配的請參見 ruleset 解析(https://github.com/CommanderXL/Biu-blog/issues/30)
  const result = this.ruleSet.exec({
    resource: resourcePath, // module 的絕對路徑
    realResource:
      matchResource !== undefined
        ? resource.replace(/?.*/, "")
        : resourcePath,
    resourceQuery, // module 路徑上所帶的 query 參數(shù)
    issuer: contextInfo.issuer, // 所解析的 module 的發(fā)布者
    compiler: contextInfo.compiler 
  });

  // result 為最終根據(jù) module 的路徑及相關(guān)匹配規(guī)則過濾后得到的 loaders,為 webpack.config 進(jìn)行配置的
  // 輸出的數(shù)據(jù)格式為:

  /* [{
    type: "use",
    value: {
      loader: "vue-style-loader",
      options: {}
    },
    enforce: undefined // 可選值還有 pre/post  分別為 pre-loader 和 post-loader
  }, {
    type: "use",
    value: {
      loader: "css-loader",
      options: {}
    },
    enforce: undefined
  }, {
    type: "use",
    value: {
      loader: "stylus-loader",
      options: {
        data: "$color red"
      }
    },
    enforce: undefined 
  }] */

  const settings = {};
  const useLoadersPost = []; // post loader
  const useLoaders = []; // normal loader
  const useLoadersPre = []; // pre loader
  for (const r of result) {
    if (r.type === "use") {
      // postLoader
      if (r.enforce === "post" && !noPrePostAutoLoaders) {
        useLoadersPost.push(r.value);
      } else if (
        r.enforce === "pre" &&
        !noPreAutoLoaders &&
        !noPrePostAutoLoaders
      ) {
        // preLoader
        useLoadersPre.push(r.value);
      } else if (
        !r.enforce &&
        !noAutoLoaders &&
        !noPrePostAutoLoaders
      ) {
        // normal loader
        useLoaders.push(r.value);
      }
    } else if (
      typeof r.value === "object" &&
      r.value !== null &&
      typeof settings[r.type] === "object" &&
      settings[r.type] !== null
    ) {
      settings[r.type] = cachedMerge(settings[r.type], r.value);
    } else {
      settings[r.type] = r.value;
    }

    // 當(dāng)獲取到 webpack.config 當(dāng)中配置的 loader 后,再根據(jù) loader 的類型進(jìn)行分組(enforce 配置類型)
    // postLoader 存儲到 useLoaders 內(nèi)部
    // preLoader 存儲到 usePreLoaders 內(nèi)部
    // normalLoader 存儲到 useLoaders 內(nèi)部
    // 這些分組最終會決定加載一個 module 時不同 loader 之間的調(diào)用順序

    // 當(dāng)分組過程進(jìn)行完之后,即開始 loader 模塊的 resolve 過程
    asyncLib.parallel([
      [
        // resolve postLoader
        this.resolveRequestArray.bind(
          this,
          contextInfo,
          this.context,
          useLoadersPost,
          loaderResolver
        ),
        // resove normal loaders
        this.resolveRequestArray.bind(
          this,
          contextInfo,
          this.context,
          useLoaders,
          loaderResolver
        ),
        // resolve preLoader
        this.resolveRequestArray.bind(
          this,
          contextInfo,
          this.context,
          useLoadersPre,
          loaderResolver
        )
      ],
      (err, results) => {
        ...
        // results[0]  ->  postLoader
        // results[1]  ->  normalLoader
        // results[2]  ->  preLoader
        // 這里將構(gòu)建 module 需要的所有類型的 loaders 按照一定順序組合起來,對應(yīng)于:
        // [postLoader, inlineLoader, normalLoader, preLoader]
        // 最終 loader 所執(zhí)行的順序?qū)?yīng)為: preLoader -> normalLoader -> inlineLoader -> postLoader
        // 不同類型 loader 上的 pitch 方法執(zhí)行的順序?yàn)椋?postLoader.pitch -> inlineLoader.pitch -> normalLoader.pitch -> preLoader.pitch (具體loader內(nèi)部執(zhí)行的機(jī)制后文會多帶帶講解)
        loaders = results[0].concat(loaders, results[1], results[2]);

        process.nextTick(() => {
          ...
          // 執(zhí)行回調(diào),創(chuàng)建 module
        })
      }
    ])
  }
})

簡單總結(jié)下匹配的流程就是:

首先處理 inlineLoaders,對其進(jìn)行解析,獲取對應(yīng)的 loader 模塊的信息,接下來利用 ruleset 實(shí)例上的匹配過濾方法對 webpack.config 中配置的相關(guān) loaders 進(jìn)行匹配過濾,獲取構(gòu)建這個 module 所需要的配置的的 loaders,并進(jìn)行解析,這個過程完成后,便進(jìn)行所有 loaders 的拼裝工作,并傳入創(chuàng)建 module 的回調(diào)中。

文章首發(fā)于個人github blog: Biu-blog,歡迎大家關(guān)注~

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/109088.html

相關(guān)文章

  • Webpack Loader 高手進(jìn)階(三)

    摘要:相關(guān)的內(nèi)容為這樣對于一個處理的第二階段也就結(jié)束了,通過去攔截不同類型的,并返回新的,跳過后面的的執(zhí)行,同時在內(nèi)部會剔除掉,這樣在進(jìn)入到下一個處理階段的時候,不在使用的范圍之內(nèi),因此下一階段便不會經(jīng)由來處理。 文章首發(fā)于個人github blog: Biu-blog,歡迎大家關(guān)注~ Webpack 系列文章: Webpack Loader 高手進(jìn)階(一)Webpack Loader 高手...

    ivydom 評論0 收藏0
  • Webpack Loader 高手進(jìn)階(二)

    摘要:如果函數(shù)沒有返回值的話,那么進(jìn)入到下一個的函數(shù)的執(zhí)行階段。這也是異步化的一種方式如果執(zhí)行后有返回值,執(zhí)行開始下一個執(zhí)行以上就是對于在構(gòu)建過程中執(zhí)行流程的源碼分析。 文章首發(fā)于個人github blog: Biu-blog,歡迎大家關(guān)注~ Webpack 系列文章: Webpack Loader 高手進(jìn)階(一)Webpack Loader 高手進(jìn)階(二)Webpack Loader 高手...

    jackzou 評論0 收藏0
  • webpack進(jìn)階loader

    webpack的loaders是一大特色,也是很重要的一部分。這遍博客我將分類講解一些常用的laodershowImg(https://segmentfault.com/img/remote/1460000005742040); 一、loaders之 預(yù)處理 css-loader 處理css中路徑引用等問題 style-loader 動態(tài)把樣式寫入css sass-loader scss編譯器 ...

    qylost 評論0 收藏0
  • [js高手之路]深入淺出webpack教程系列1-安裝與基本打包用法和命令參數(shù)

    摘要:,我想大家應(yīng)該都知道或者聽過,是前端一個工具可以讓各個模塊進(jìn)行加載預(yù)處理再進(jìn)行打包。 webpack,我想大家應(yīng)該都知道或者聽過,Webpack是前端一個工具,可以讓各個模塊進(jìn)行加載,預(yù)處理,再進(jìn)行打包。現(xiàn)代的前端開發(fā)很多環(huán)境都依賴webpack構(gòu)建,比如vue官方就推薦使用webpack.廢話不多說,我們趕緊開始吧. 第一步、安裝webpack 新建文件夾webpack->再在web...

    pubdreamcc 評論0 收藏0
  • webpack4 高手之路 第四天

    摘要:配置文件中設(shè)置引入文件之前講過在引用文件的時候可以引入和,諸如這樣現(xiàn)在提供一種更常用和更便捷的方法。同樣先在項(xiàng)目文件夾下安裝和模塊配置文件如下選項(xiàng)用來處理對應(yīng)的模塊用正則匹配所有的文件使用模塊這樣就已經(jīng)可以正常打包文件了。 配置文件中設(shè)置引入css文件 之前講過在引用css文件的時候可以引入style-loader和css=loader,諸如這樣: require(style-load...

    animabear 評論0 收藏0

發(fā)表評論

0條評論

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