07_01_定義加載器(Webpack Book)

Loader Definitions

定義加載器javascript

Webpack provides multiple ways to set up module loaders. Webpack 2 simplified the situation by introducing the use field. It can be a good idea to prefer absolute paths here as they allow you to move configuration without breaking assumptions.
Webpack提供多種設置模塊加載器的方法。在Webpack 2 中引入use來簡化這種狀況。在這裏選擇絕對路徑多是一個好主意,由於它們容許您在不破壞假設的狀況下移動配置。css

The other way is to set context field as this gives a similar effect and affects the way entry points and loaders are resolved. It doesn't have an impact on the output, though, and you still need to use an absolute path or / there.
另外一個方法是設置context字段,由於這會產生相似的效果,同時也影響入口點和加載器的解析方式。可是,它不會影響輸出,你仍然須要在那裏使用絕對路徑或者/java

Assuming you set an include or exclude rule, packages loaded from node_modules still work as the assumption is that they have been compiled in such a way that they work out of the box. If they don't, then you have to apply techniques covered in the Consuming Packages chapter.
假設您設置了一個includeexclude規則,從node_modules加載的包仍然能夠工做,由於它們是以一種開箱即用的方式編譯的。若是不能用,你就須要用到 Consuming Packages 中提到的技術了。node

T> include/exclude is handy with node_modules as webpack processes and traverses the installed packages by default when you import JavaScript files to your project. Therefore you need to configure it to avoid that behavior. Other file types don't suffer from this issue.
當您將JavaScript文件導入到項目中時,「include」/「exclude」與*node_modules一塊兒做爲webpack處理和遍歷已安裝包方式時很是方便。所以你須要配置以避免發生這個狀況。其餘文件類型沒有這個問題。webpack

Anatomy of a Loader(加載器結構)

Webpack supports a large variety of formats through loaders. Also, it supports a couple of JavaScript module formats out of the box. The idea is the same. You always set up a loader, or loaders, and connect those with your directory structure.
Webpack經過 loaders 支持各類各樣的格式。它也直接支持一些Javascript模塊格式。方法是同樣的。你始終設置一個或多個 loader,而且將他們與你的目錄結構相關聯。git

{pagebreak}github

Consider the example below where webpack processes JavaScript through Babel:
參考如下經過 Babel 處理 Javascript的示例:web

webpack.config.js正則表達式

module.exports = {
  ...
  module: {
    rules: [
      {
        // **Conditions** to match files using RegExp, function.
        test: /\.js$/,

        // **Restrictions**
        // Restrict matching to a directory. This
        // also accepts an array of paths or a function.
        // The same applies to `exclude`.
        include: path.join(__dirname, "app"),
        exclude(path) {
          // You can perform more complicated checks  as well.
          return path.match(/node_modules/);
        },

        // **Actions** to apply loaders to the matched files.
        use: "babel-loader",
      },
    ],
  },
};

T> If you are not sure how a particular RegExp matches, consider using an online tool, such as regex101, RegExr, or Regexper.
若是你不肯定一個正則表達式如何匹配字符串上,能夠考慮使用在線工具,如: regex101, RegExr, or Regexper.npm

Loader Evaluation Order(加載器計算順序)

It's good to keep in mind that webpack's loaders are always evaluated from right to left and from bottom to top (separate definitions). The right-to-left rule is easier to remember when you think about as functions. You can read definition use: ["style-loader", "css-loader"] as style(css(input)) based on this rule.
最好記住Webpack的加載器老是從右到左從下到上(分離的定義)計算。從右到左的原則比較容易記住,由於和函數同樣。根據這個原則,你能夠把use:["style-loader", "css-loader"]當成style(css(input))

To see the rule in action, consider the example below:
參考如下示例來了解這個規則的應用:

{
  test: /\.css$/,
  use: ["style-loader", "css-loader"],
},

Based on the right to left rule, the example can be split up while keeping it equivalent:
基於從右到左的規則,上面的例子能夠被拆分紅如下結構,而功能保持一致:

{
  test: /\.css$/,
  use: "style-loader",
},
{
  test: /\.css$/,
  use: "css-loader",
},

Enforcing Order(強制順序)

Even though it would be possible to develop an arbitrary configuration using the rule above, it can be convenient to be able to force specific rules to be applied before or after regular ones. The enforce field can come in handy here. It can be set to either pre or post to push processing either before or after other loaders.
儘管使用上面的規則能夠開發任意的配置,可是強制特定的規則在普通規則以前或以後執行仍是很是方便的。enforce字段能夠方便的達到這個目的。把它能夠被設置成prepost, 能夠在其餘加載器以前或者以後處理執行。

Linting is a good example because the build should fail before it does anything else. Using enforce: "post" is rarer and it would imply you want to perform a check against the built source. Performing analysis against the built source is one potential example.
Linting是一個很好的例子,由於若是Linting報錯,Build過程應該在執行其餘操做前就失敗。enforce:"post"更少見,這意味着你要對生成的的源碼進行檢查。對生成的源碼進行分析算是一種應用情形。

{pagebreak}

The basic syntax goes as below:
如下是基本語法:

{
  // Conditions
  test: /\.js$/,
  enforce: "pre", // "post" too

  // Actions
  use: "eslint-loader",
},

It would be possible to write the same configuration without enforce if you chained the declaration with other loaders related to the test carefully. Using enforce removes the necessity for that and allows you to split loader execution into separate stages that are easier to compose.
若是你仔細地將相關test加載器的聲明連接起來而不使用enforce來獲得相同效果的配置是可能的。使用enforce能夠移除 順序 的必要性,並讓你很容易地將加載器的執行放在不一樣階段。

Passing Parameters to a Loader(向加載器傳遞參數)

There's a query format that allows passing parameters to loaders:
有一個查詢格式容許傳遞參數給加載器。

{
  // Conditions
  test: /\.js$/,
  include: PATHS.app,

  // Actions
  use: "babel-loader?presets[]=env",
},

This style of configuration works in entries and source imports too as webpack picks it up. The format comes in handy in certain individual cases, but often you are better off using more readable alternatives.
這種樣式的配置在 entries 和 源碼導入中也適用,由於Webpack也採用了這個格式。這種格式在特定狀況很是方便,可是你最好使用更易讀的替代方案。

{pagebreak}

It's preferable to go through use:
最好經過使用use:

{
  // Conditions
  test: /\.js$/,
  include: PATHS.app,

  // Actions
  use: {
    loader: "babel-loader",
    options: {
      presets: ["env"],
    },
  },
},

If you wanted to use more than one loader, you could pass an array to use and expand from there:
若是你想使用不僅一個加載器,能夠傳遞一個數組給use並在裏面展開:

{
  test: /\.js$/,
  include: PATHS.app,

  use: [
    {
      loader: "babel-loader",
      options: {
        presets: ["env"],
      },
    },
    // Add more loaders here
  ],
},

{pagebreak}

Branching at use Using a Function(在use中使用函數進行分支)

In the book setup, you compose configuration on a higher level. Another option to achieve similar results would be to branch at use as webpack's loader definitions accept functions that allow you to branch depending on the environment. Consider the example below:
在書中的設置,在一個較高層級組合配置。實現相似結果的另外一個選項是在use處進行分支,由於webpack的加載器定義接受容許您根據環境進行分支的函數。參考下面的例子:

{
  test: /\.css$/,

  // `resource` refers to the resource path matched.
  // `resourceQuery` contains possible query passed to it
  // `issuer` tells about match context path
  use: ({ resource, resourceQuery, issuer }) => {
    // You have to return something falsy, object, or a
    // string (i.e., "style-loader") from here.
    //
    // Returning an array fails! Nest rules instead.
    if (env === "development") {
      return {
        use: {
          loader: "css-loader", // css-loader first
          rules: [
            "style-loader", // style-loader after
          ],
        },
      };
    }
  },
},

Carefully applied, this technique allows different means of composition.
謹慎使用,由於這種技術容許不一樣的組合方式。

Inline Definitions(內聯定義)

Even though configuration level loader definitions are preferable, it's possible to write loader definitions inline:
即便配置級加載器定義更好,也能夠內聯編寫加載器定義:

// Process foo.png through url-loader and other
// possible matches.
import "url-loader!./foo.png";

// Override possible higher level match completely
import "!!url-loader!./bar.png";

The problem with this approach is that it couples your source with webpack. Nonetheless, it's still an excellent form to know. Since configuration entries go through the same mechanism, the same forms work there as well:
這個方法的問題在於讓你的代碼與Webpack相耦合。儘管如此,內聯定義也是一個不錯的格式。因爲配置入口使用相同的機制,因此該格式也適用:

{
  entry: {
    app: "babel-loader!./app",
  },
},

Alternate Ways to Match Files(匹配文件的其餘方式 )

test combined with include or exclude to constrain the match is the most common approach to match files. These accept the data types as listed below:
「test」與「include」或「exclude」組合來約束匹配是最多見的匹配文件的方法。如下是可接受的數據類型:

  • test - Match against a RegExp, string, function, an object, or an array of conditions like these. (經過正則表達式,字符串,函數,對象,條件數組等等匹配。)
  • include - The same.(同上)
  • exclude - The same, except the output is the inverse of include.(同上,除了輸出與"include"相反).
  • resource: /inline/ - Match against a resource path including the query. Examples: /path/foo.inline.js, /path/bar.png?inline.(匹配包含查詢的資源路徑。)
  • issuer: /bar.js/ - Match against a resource requested from the match. Example: /path/foo.png would match if it was requested from /path/bar.js.(來自匹配項的資源請求來匹配)
  • resourcePath: /inline/ - Match against a resource path without its query. Example: /path/foo.inline.png.(匹配不包含查詢的資源路徑)
  • resourceQuery: /inline/ - Match against a resource based on its query. Example: /path/foo.png?inline.(匹配基於查詢的資源)

Boolean based fields can be used to constrain these matchers further:
布爾值能夠用來更好的約束匹配器:

  • not - Do not match against a condition (see test for accepted values).(不要經過條件匹配)
  • and - Match against an array of conditions. All must match.(經過條件數據匹配。條件數組所有知足)
  • or - Match against an array while any must match.(經過條件數據匹配。條件數組任意項必須知足)

Loading Based on resourceQuery(基於resourceQuery加載)

oneOf field makes it possible to route webpack to a specific loader based on a resource related match:
oneOf 字段能夠將Webpack跳轉到相應資源的匹配項的加載器上:

{
  test: /\.png$/,
  oneOf: [
    {
      resourceQuery: /inline/,
      use: "url-loader",
    },
    {
      resourceQuery: /external/,
      use: "file-loader",
    },
  ],
},

If you wanted to embed the context information to the filename, the rule could use resourcePath over resourceQuery.
若是你想把上下文信息嵌入到文件名中,規則應該使用resourcePath而不是resourceQuery

{pagebreak}

Loading Based on issuer(基於issuer加載)

issuer can be used to control behavior based on where a resource was imported. In the example below adapted from css-loader issue 287, style-loader is applied when webpack captures a CSS file from a JavaScript import:
issuer能夠根據導入位置來控制行爲。下面的示例是基於css-loader issue 287,當Wepack捕獲到JavaScript導入一個CSS文件時,style-loader就會運行。

{
  test: /\.css$/,

  rules: [
    {
      issuer: /\.js$/,
      use: "style-loader",
    },
    {
      use: "css-loader",
    },
  ],
},

Another approach would be to mix issuer and not:
另外一個方法就是混合使用issuernot

{
  test: /\.css$/,

  rules: [
    // CSS imported from other modules is added to the DOM
    {
      issuer: { not: /\.css$/ },
      use: "style-loader",
    },
    // Apply css-loader against CSS imports to return CSS
    {
      use: "css-loader",
    },
  ],
}

Understanding Loader Behavior(理解加載器行爲)

Loader behavior can be understood in greater detail by inspecting them. loader-runner allows you to run them in isolation without webpack. Webpack uses this package internally and Extending with Loaders chapter covers it in detail.
經過檢查他們,能夠更深刻的瞭解加載器行爲。loader-runner容許你在沒有Webpack的狀況下獨立運行他們。Webpack在內部使用這個包,而且在Extending with Loaders一節有更詳細的介紹。

inspect-loader allows you to inspect what's being passed between loaders. Instead of having to insert console.logs within node_modules, you can attach this loader to your configuration and inspect the flow there.
inspect-loader讓你檢查加載器之間傳遞的內容。不須要在node_modules中添加consloe.log,你能將這個加載器添加到你的配置中並能夠檢查流程。

Conclusion(總結)

Webpack provides multiple ways to setup loaders but sticking with use is enough in webpack 4. Be careful with loader ordering, as it's a common source of problems.
Webpack提供多種方式設置加載器,可是在Webpack4中堅持使用use就足夠了。要當心處理加載器的順序,由於大部分緣由都是它致使的。

To recap:(收穫)

  • Loaders allow you determine what should happen when webpack's module resolution mechanism encounters a file.
    Loaders 讓你決定當Webpack處理機制碰到一個文件時該如何處理。
  • A loader definition consists of conditions based on which to match and actions that should be performed when a match happens.
    加載器定義由要匹配的conditions和在匹配發生時應該執行的action組成。
  • Webpack 2 introduced the use field. It combines the ideas of old loader and loaders fields into a single construct.
    Webpack 2 引入了use字段,它將以前的loaderloaders的功能合併成一個功能。
  • Webpack 4 provides multiple ways to match and alter loader behavior. You can, for example, match based on a resource query after a loader has been matched and route the loader to specific actions.

Webpack 4提供了多種匹配和更改加載器行爲的方法。例如,在匹配了加載器以後,能夠基於resourcequery進行匹配,並將加載器路由到特定操做。

In the next chapter, you'll learn to load images using webpack.

相關文章
相關標籤/搜索