国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

Webpack:Loader Interface

2023-05-10 09:56 更新

loader 本質(zhì)上是導(dǎo)出為函數(shù)的 JavaScript 模塊。loader runner 會(huì)調(diào)用此函數(shù),然后將上一個(gè) loader 產(chǎn)生的結(jié)果或者資源文件傳入進(jìn)去。函數(shù)中的 this 作為上下文會(huì)被 webpack 填充,并且 loader runner 中包含一些實(shí)用的方法,比如可以使 loader 調(diào)用方式變?yōu)楫惒剑蛘攉@取 query 參數(shù)。

起始 loader 只有一個(gè)入?yún)ⅲ嘿Y源文件的內(nèi)容。compiler 預(yù)期得到最后一個(gè) loader 產(chǎn)生的處理結(jié)果。這個(gè)處理結(jié)果應(yīng)該為 String 或者 Buffer(能夠被轉(zhuǎn)換為 string)類型,代表了模塊的 JavaScript 源碼。另外,還可以傳遞一個(gè)可選的 SourceMap 結(jié)果(格式為 JSON 對(duì)象)。

如果是單個(gè)處理結(jié)果,可以在同步模式中直接返回。如果有多個(gè)處理結(jié)果,則必須調(diào)用 this.callback()。在異步模式中,必須調(diào)用 this.async() 來告知 loader runner 等待異步結(jié)果,它會(huì)返回 this.callback() 回調(diào)函數(shù)。隨后 loader 必須返回 undefined 并且調(diào)用該回調(diào)函數(shù)。

/**
 *
 * @param {string|Buffer} content 源文件的內(nèi)容
 * @param {object} [map] 可以被 https://github.com/mozilla/source-map 使用的 SourceMap 數(shù)據(jù)
 * @param {any} [meta] meta 數(shù)據(jù),可以是任何內(nèi)容
 */
function webpackLoader(content, map, meta) {
  // 你的 webpack loader 代碼
}

示例

以下部分提供了不同類型的 loader 的一些基本示例。注意,map 和 meta 參數(shù)是可選的,查看下面的this.callback。

同步 Loaders

無論是 return 還是 this.callback 都可以同步地返回轉(zhuǎn)換后的 content 值:

sync-loader.js

module.exports = function (content, map, meta) {
  return someSyncOperation(content);
};

this.callback 方法則更靈活,因?yàn)樗试S傳遞多個(gè)參數(shù),而不僅僅是 content。

sync-loader-with-multiple-results.js

module.exports = function (content, map, meta) {
  this.callback(null, someSyncOperation(content), map, meta);
  return; // 當(dāng)調(diào)用 callback() 函數(shù)時(shí),總是返回 undefined
};

異步 Loaders

對(duì)于異步 loader,使用 this.async 來獲取 callback 函數(shù):

async-loader.js

module.exports = function (content, map, meta) {
  var callback = this.async();
  someAsyncOperation(content, function (err, result) {
    if (err) return callback(err);
    callback(null, result, map, meta);
  });
};

async-loader-with-multiple-results.js

module.exports = function (content, map, meta) {
  var callback = this.async();
  someAsyncOperation(content, function (err, result, sourceMaps, meta) {
    if (err) return callback(err);
    callback(null, result, sourceMaps, meta);
  });
};

"Raw" Loader

默認(rèn)情況下,資源文件會(huì)被轉(zhuǎn)化為 UTF-8 字符串,然后傳給 loader。通過設(shè)置 raw 為 true,loader 可以接收原始的 Buffer。每一個(gè) loader 都可以用 String 或者 Buffer 的形式傳遞它的處理結(jié)果。complier 將會(huì)把它們?cè)?loader 之間相互轉(zhuǎn)換。

raw-loader.js

module.exports = function (content) {
  assert(content instanceof Buffer);
  return someSyncOperation(content);
  // 返回值也可以是一個(gè) `Buffer`
  // 即使不是 "raw",loader 也沒問題
};
module.exports.raw = true;

Pitching Loader

loader 總是 從右到左被調(diào)用。有些情況下,loader 只關(guān)心 request 后面的 元數(shù)據(jù)(metadata),并且忽略前一個(gè) loader 的結(jié)果。在實(shí)際(從右到左)執(zhí)行 loader 之前,會(huì)先 從左到右 調(diào)用 loader 上的 pitch 方法。

對(duì)于以下 use 配置:

module.exports = {
  //...
  module: {
    rules: [
      {
        //...
        use: ['a-loader', 'b-loader', 'c-loader'],
      },
    ],
  },
};

將會(huì)發(fā)生這些步驟:

|- a-loader `pitch`
  |- b-loader `pitch`
    |- c-loader `pitch`
      |- requested module is picked up as a dependency
    |- c-loader normal execution
  |- b-loader normal execution
|- a-loader normal execution

那么,為什么 loader 可以利用 "pitching" 階段呢?

首先,傳遞給 pitch 方法的 data,在執(zhí)行階段也會(huì)暴露在 this.data 之下,并且可以用于在循環(huán)時(shí),捕獲并共享前面的信息。

module.exports = function (content) {
  return someSyncOperation(content, this.data.value);
};

module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  data.value = 42;
};

其次,如果某個(gè) loader 在 pitch 方法中給出一個(gè)結(jié)果,那么這個(gè)過程會(huì)回過身來,并跳過剩下的 loader。在我們上面的例子中,如果 b-loader 的 pitch 方法返回了一些東西:

module.exports = function (content) {
  return someSyncOperation(content);
};

module.exports.pitch = function (remainingRequest, precedingRequest, data) {
  if (someCondition()) {
    return (
      'module.exports = require(' +
      JSON.stringify('-!' + remainingRequest) +
      ');'
    );
  }
};

上面的步驟將被縮短為:

|- a-loader `pitch`
  |- b-loader `pitch` returns a module
|- a-loader normal execution

The Loader Context

loader context 表示在 loader 內(nèi)使用 this 可以訪問的一些方法或?qū)傩浴?/p>

loader 上下文示例

下面提供一個(gè)例子,將使用 require 進(jìn)行調(diào)用:

在 /abc/file.js 中:

require('./loader1?xyz!loader2!./resource?rrr');

this.addContextDependency

addContextDependency(directory: string)

添加目錄作為 loader 結(jié)果的依賴。

this.addDependency

addDependency(file: string)
dependency(file: string) // shortcut

添加一個(gè)文件作為產(chǎn)生 loader 結(jié)果的依賴,使它們的任何變化可以被監(jiān)聽到。例如,sass-loaderless-loader 就使用了這個(gè)技巧,當(dāng)它發(fā)現(xiàn)無論何時(shí)導(dǎo)入的 css 文件發(fā)生變化時(shí)就會(huì)重新編譯。

this.addMissingDependency

addMissingDependency(file: string)

添加一個(gè)不存在的文件作為 loader 結(jié)果的依賴項(xiàng),以使它們可監(jiān)聽。類似于 addDependency,但是會(huì)在正確附加觀察者之前處理在編譯期間文件的創(chuàng)建。

this.async

告訴 loader-runner 這個(gè) loader 將會(huì)異步地回調(diào)。返回 this.callback。

this.cacheable

設(shè)置是否可緩存標(biāo)志的函數(shù):

cacheable(flag = true: boolean)

默認(rèn)情況下,loader 的處理結(jié)果會(huì)被標(biāo)記為可緩存。調(diào)用這個(gè)方法然后傳入 false,可以關(guān)閉 loader 處理結(jié)果的緩存能力。

一個(gè)可緩存的 loader 在輸入和相關(guān)依賴沒有變化時(shí),必須返回相同的結(jié)果。這意味著 loader 除了 this.addDependency 里指定的以外,不應(yīng)該有其它任何外部依賴。

this.callback

可以同步或者異步調(diào)用的并返回多個(gè)結(jié)果的函數(shù)。預(yù)期的參數(shù)是:

this.callback(
  err: Error | null,
  content: string | Buffer,
  sourceMap?: SourceMap,
  meta?: any
);
  1. 第一個(gè)參數(shù)必須是 Error 或者 null
  2. 第二個(gè)參數(shù)是一個(gè) string 或者 Buffer。
  3. 可選的:第三個(gè)參數(shù)必須是一個(gè)可以被 this module 解析的 source map。
  4. 可選的:第四個(gè)參數(shù),會(huì)被 webpack 忽略,可以是任何東西(例如一些元數(shù)據(jù))。

this.clearDependencies

clearDependencies();

移除 loader 結(jié)果的所有依賴,甚至自己和其它 loader 的初始依賴??紤]使用 pitch。

this.context

模塊所在的目錄 可以用作解析其他模塊成員的上下文。

在我們的 例子 中:因?yàn)?nbsp;resource.js 在這個(gè)目錄中,這個(gè)屬性的值為 /abc

this.data

在 pitch 階段和 normal 階段之間共享的 data 對(duì)象。

this.emitError

emitError(error: Error)

emit 一個(gè)錯(cuò)誤,也可以在輸出中顯示。

ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Error (from ./src/loader.js):
Here is an Error!
 @ ./src/index.js 1:0-25

this.emitFile

emitFile(name: string, content: Buffer|string, sourceMap: {...})

產(chǎn)生一個(gè)文件。這是 webpack 特有的。

this.emitWarning

emitWarning(warning: Error)

發(fā)出一個(gè)警告,在輸出中顯示如下:

WARNING in ./src/lib.js (./src/loader.js!./src/lib.js)
Module Warning (from ./src/loader.js):
Here is a Warning!
 @ ./src/index.js 1:0-25

this.fs

用于訪問 compilation 的 inputFileSystem 屬性。

this.getOptions(schema)

提取給定的 loader 選項(xiàng),接受一個(gè)可選的 JSON schema 作為參數(shù)

this.getResolve

getResolve(options: ResolveOptions): resolve

resolve(context: string, request: string, callback: function(err, result: string))
resolve(context: string, request: string): Promise<string>

創(chuàng)建一個(gè)類似于 this.resolve 的解析函數(shù)。

webpack resolve 選項(xiàng) 下的任意配置項(xiàng)都是可能的。他們會(huì)被合并進(jìn) resolve 配置項(xiàng)中。請(qǐng)注意,"..." 可以在數(shù)組中使用,用于拓展 resolve 配置項(xiàng)的值。例如:{ extensions: [".sass", "..."] }。

options.dependencyType 是一個(gè)額外的配置。它允許我們指定依賴類型,用于從 resolve 配置項(xiàng)中解析 byDependency。

解析操作的所有依賴項(xiàng)都會(huì)自動(dòng)作為依賴項(xiàng)添加到當(dāng)前模塊中。

this.hot

loaders 的 HMR(熱模塊替換)相關(guān)信息。

module.exports = function (source) {
  console.log(this.hot); // true if HMR is enabled via --hot flag or webpack configuration
  return source;
};

this.importModule

5.32.0+

this.importModule(request, options, [callback]): Promise

一種可以選擇的輕量級(jí)解決方案,用于子編譯器在構(gòu)建時(shí)編譯和執(zhí)行請(qǐng)求。

  • request: 加載模塊的請(qǐng)求字符串
  • options:layer:指定該模塊放置/編譯的層publicPath:用于構(gòu)建模塊的公共路徑
  • callback:一個(gè)可選的 Node.js 風(fēng)格的回調(diào),返回模塊的 exports 或 ESM 的命名空間對(duì)象。如果沒有提供回調(diào),importModule將返回一個(gè) Promise。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /stylesheet\.js$/i,
        use: ['./a-pitching-loader.js'],
        type: 'asset/source', // 我們將 type 設(shè)置為 'asset/source',其會(huì)返回一個(gè)字符串。
      },
    ],
  },
};

a-pitching-loader.js

exports.pitch = async function (remaining) {
  const result = await this.importModule(
    this.resourcePath + '.webpack[javascript/auto]' + '!=!' + remaining
  );
  return result.default || result;
};

src/stylesheet.js

import { green, red } from './colors.js';
export default `body { background: ${red}; color: ${green}; }`;

src/colors.js

export const red = '#f00';
export const green = '#0f0';

src/index.js

import stylesheet from './stylesheet.js';
// stylesheet 在構(gòu)建時(shí)會(huì)成為一個(gè)字符串:`body { background: #f00; color: #0f0; }`。

在上面的例子中你可能會(huì)注意到一些東西:

  1. 我們有一個(gè) pitching loader,
  2. 我們?cè)?pitching loader 中使用 !=! 語法來為請(qǐng)求設(shè)置 matchResource,例如,我們將使用 ?this.resourcePath? +? '.webpack[javascript/auto]' ?而不是原始資源匹配 module.rules,
  3. ?.webpack[javascript/auto] ?是? .webpack[type] ?模式的偽拓展,當(dāng)沒有指定其他模塊類型時(shí),我們使用它指定一個(gè)默認(rèn) 模塊類型,它通常和 !=! 語法一起使用。

注意,上面的示例是一個(gè)簡(jiǎn)化的示例,你可以查看 webpack 倉(cāng)庫(kù)的完整示例

this.loaderIndex

當(dāng)前 loader 在 loader 數(shù)組中的索引。

在示例中:loader1 中得到:0,loader2 中得到:1

this.loadModule

loadModule(request: string, callback: function(err, source, sourceMap, module))

解析給定的 request 到模塊,應(yīng)用所有配置的 loader,并且在回調(diào)函數(shù)中傳入生成的 source、sourceMap 和模塊實(shí)例(通常是 NormalModule 的一個(gè)實(shí)例)。如果你需要獲取其他模塊的源代碼來生成結(jié)果的話,你可以使用這個(gè)函數(shù)。

this.loadModule 在 loader 上下文中默認(rèn)使用 CommonJS 來解析規(guī)則。用一個(gè)合適的 dependencyType 使用 this.getResolve。例如,在使用不同的語義之前使用 'esm'、'commonjs' 或者一個(gè)自定義的。

this.loaders

所有 loader 組成的數(shù)組。它在 pitch 階段的時(shí)候是可以寫入的。

loaders = [{request: string, path: string, query: string, module: function}]

在此示例中:

[
  {
    request: '/abc/loader1.js?xyz',
    path: '/abc/loader1.js',
    query: '?xyz',
    module: [Function],
  },
  {
    request: '/abc/node_modules/loader2/index.js',
    path: '/abc/node_modules/loader2/index.js',
    query: '',
    module: [Function],
  },
];

this.mode

當(dāng) webpack 運(yùn)行時(shí)讀取 mode 的值

可能的值為:'production', 'development', 'none'

this.query

  1. 如果這個(gè) loader 配置了 options 對(duì)象的話,this 就指向這個(gè)對(duì)象。
  2. 如果 loader 中沒有 options,而是以 query 字符串作為參數(shù)調(diào)用時(shí),this.query 就是一個(gè)以 ? 開頭的字符串。

this.request

被解析出來的 request 字符串。

在我們的示例中:'/abc/loader1.js?xyz!/abc/node_modules/loader2/index.js!/abc/resource.js?rrr'

this.resolve

resolve(context: string, request: string, callback: function(err, result: string))

像 require 表達(dá)式一樣解析一個(gè) request。

  • context 必須是一個(gè)目錄的絕對(duì)路徑。此目錄用作解析的起始位置。
  • request 是要被解析的 request。通常情況下,像 ./relative 的相對(duì)請(qǐng)求或者像 module/path 的模塊請(qǐng)求會(huì)被使用,但是像 /some/path 也有可能被當(dāng)做 request。
  • callback 是一個(gè)給出解析路徑的 Node.js 風(fēng)格的回調(diào)函數(shù)。

解析操作的所有依賴項(xiàng)都會(huì)自動(dòng)作為依賴項(xiàng)添加到當(dāng)前模塊中。

this.resource

request 中的資源部分,包括 query 參數(shù)。

示例中:'/abc/resource.js?rrr'

this.resourcePath

資源文件的路徑。

在【示例](#example-for-the-loader-context)中:'/abc/resource.js'

this.resourceQuery

資源的 query 參數(shù)。

示例中:'?rrr'

this.rootContext

從 webpack 4 開始,原先的 this.options.context 被改為 this.rootContext。

this.sourceMap

是否應(yīng)該生成一個(gè) source map。因?yàn)樯?source map 可能會(huì)非常耗時(shí),你應(yīng)該確認(rèn) source map 確實(shí)需要。

this.target

compilation 的目標(biāo)。從配置選項(xiàng)中傳遞。

示例:'web', 'node'

this.utils

5.27.0+

可以訪問 contextify 與 absolutify 功能。

  • contextify: 返回一個(gè)新的請(qǐng)求字符串,盡可能避免使用絕對(duì)路徑。
  • absolutify: 盡可能使用相對(duì)路徑返回一個(gè)新的請(qǐng)求字符串。

my-sync-loader.js

module.exports = function (content) {
  this.utils.contextify(
    this.context,
    this.utils.absolutify(this.context, './index.js')
  );
  this.utils.absolutify(this.context, this.resourcePath);
  // …
  return content;
};

this.version

loader API 的版本號(hào) 目前是 2。這對(duì)于向后兼容性有一些用處。通過這個(gè)版本號(hào),你可以自定義邏輯或者降級(jí)處理。

this.webpack

如果是由 webpack 編譯的,這個(gè)布爾值會(huì)被設(shè)置為 true。

Webpack 特有屬性

loader 接口提供所有模塊的相關(guān)信息。然而,在極少數(shù)情況下,你可能需要訪問 compiler api 本身。

因此,你應(yīng)該把它們作為最后的手段。使用它們將降低 loader 的可移植性。

this._compilation

用于訪問 webpack 的當(dāng)前 Compilation 對(duì)象。

this._compiler

用于訪問 webpack 的當(dāng)前 Compiler 對(duì)象。

過時(shí)的上下文屬性

由于我們計(jì)劃將這些屬性從上下文中移除,因此不鼓勵(lì)使用這些屬性。它們?nèi)匀涣性谶@里,以備參考。

this.debug

一個(gè)布爾值,當(dāng)處于 debug 模式時(shí)為 true。

this.inputValue

從上一個(gè) loader 那里傳遞過來的值。如果你會(huì)以模塊的方式處理輸入?yún)?shù),建議預(yù)先讀入這個(gè)變量(為了性能因素)。

this.minimize

決定處理結(jié)果是否應(yīng)該被壓縮。

this.value

向下一個(gè) loader 傳值。如果你知道了作為模塊執(zhí)行后的結(jié)果,請(qǐng)?jiān)谶@里賦值(以元素?cái)?shù)組的形式)。

this._module

一種 hack 寫法。用于訪問當(dāng)前加載的 Module 對(duì)象。

錯(cuò)誤報(bào)告

您可以通過以下方式從 loader 內(nèi)部報(bào)告錯(cuò)誤:

  • 使用 this.emitError. 將在不中斷模塊編譯的情況下報(bào)告錯(cuò)誤。
  • 使用 throw(或其他未捕獲的意外異常)。loader 運(yùn)行時(shí)引發(fā)錯(cuò)誤將導(dǎo)致當(dāng)前模塊編譯失敗。
  • 使用 callback(異步模式)。向回調(diào)傳遞錯(cuò)誤也會(huì)導(dǎo)致模塊編譯失敗。

示例:

./src/index.js

require('./loader!./lib');

從 loader 當(dāng)中拋出錯(cuò)誤:

./src/loader.js

module.exports = function (source) {
  throw new Error('This is a Fatal Error!');
};

或者在異步模式下,傳入一個(gè)錯(cuò)誤給 callback:

./src/loader.js

module.exports = function (source) {
  const callback = this.async();
  //...
  callback(new Error('This is a Fatal Error!'), source);
};

這個(gè)模塊將獲取像下面的 bundle:

/***/ "./src/loader.js!./src/lib.js":
/*!************************************!*\
  !*** ./src/loader.js!./src/lib.js ***!
  \************************************/
/*! no static exports found */
/***/ (function(module, exports) {

throw new Error("Module build failed (from ./src/loader.js):\nError: This is a Fatal Error!\n    at Object.module.exports (/workspace/src/loader.js:3:9)");

/***/ })

然后構(gòu)建輸出結(jié)果將顯示錯(cuò)誤,與 this.emitError 相似:

ERROR in ./src/lib.js (./src/loader.js!./src/lib.js)
Module build failed (from ./src/loader.js):
Error: This is a Fatal Error!
    at Object.module.exports (/workspace/src/loader.js:2:9)
 @ ./src/index.js 1:0-25

如下所示,不僅有錯(cuò)誤消息,還提供了有關(guān)所涉及的 loader 和模塊的詳細(xì)信息:

  • 模塊路徑:ERROR in ./src/lib.js
  • request 字符串:(./src/loader.js!./src/lib.js)
  • loader 路徑:(from ./src/loader.js)
  • 調(diào)用路徑:@ ./src/index.js 1:0-25

Inline matchResource

在 webpack v4 中引入了一種新的內(nèi)聯(lián)請(qǐng)求語法。前綴為 <match-resource>!=! 將為此請(qǐng)求設(shè)置 matchResource。

當(dāng) matchResource 被設(shè)置時(shí),它將會(huì)被用作匹配 module.rules 而不是源文件。如果需要對(duì)資源應(yīng)用進(jìn)一步的 loader,或者需要更改模塊類型,這可能會(huì)很有用。 它也顯示在統(tǒng)計(jì)數(shù)據(jù)中,用于匹配 Rule.issuer 和 test in splitChunks。

示例:

file.js

/* STYLE: body { background: red; } */
console.log('yep');

loader 可以將文件轉(zhuǎn)換為以下文件,并使用 matchResource 應(yīng)用用戶指定的 CSS 處理規(guī)則:

file.js (transformed by loader)

import './file.js.css!=!extract-style-loader/getStyles!./file.js';
console.log('yep');

這將會(huì)向 extract-style-loader/getStyles!./file.js 中添加一個(gè)依賴,并將結(jié)果視為 file.js.css。因?yàn)?nbsp;module.rules 有一條匹配 /\.css$/ 的規(guī)則,并且將會(huì)應(yīng)用到依賴中。

這個(gè) loader 就像是這樣:

extract-style-loader/index.js

const getStylesLoader = require.resolve('./getStyles');

module.exports = function (source) {
  if (STYLES_REGEXP.test(source)) {
    source = source.replace(STYLES_REGEXP, '');
    return `import ${JSON.stringify(
      this.utils.contextify(
        this.context || this.rootContext,
        `${this.resource}.css!=!${getStylesLoader}!${this.remainingRequest}`
      )
    )};${source}`;
  }
  return source;
};

extract-style-loader/getStyles.js

module.exports = function (source) {
  const match = source.match(STYLES_REGEXP);
  return match[0];
};

Logging

自 webpack 4.37 發(fā)布以來,Logging API 就可用了。當(dāng) stats configuration 或者 infrastructure logging 中啟用 logging 時(shí),loader 可以記錄消息,這些消息將以相應(yīng)的日志格式(stats,infrastructure)打印出來。

  • Loaders 最好使用 this.getLogger() 進(jìn)行日志記錄,這是指向 compilation.getLogger() 具有 loader 路徑和已處理的文件。這種日志記錄被存儲(chǔ)到 Stats 中并相應(yīng)地格式化。它可以被 webpack 用戶過濾和導(dǎo)出。
  • Loaders 可以使用 this.getLogger('name') 獲取具有子名稱的獨(dú)立記錄器。仍會(huì)添加 loader 路徑和已處理的文件。
  • Loaders 可以使用特殊的回退邏輯來檢測(cè)日志支持 this.getLogger() ? this.getLogger() : console。在使用不支持 getLogger 方法的舊 webpack 版本時(shí)提供回退方法。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)