Webpack5 のローダーの詳細な紹介

ローダーは、Webpack がさまざまな種類のファイルを Webpack が認識できるモジュールに変換するのに役立ちます。
ここに画像の説明を挿入します

優先順位の分類

pre: フロントローダー
normal: 通常のローダー、enforceで指定しない場合は通常
inline: インラインローダー
post: ポストローダー

ローダーの実行順序

pre > normal > inline > post
同じ優先度を持つローダーの実行順序は、右から左、下から上です。

ローダーの使い方

1. 設定方法:webpack.config.jsファイルにローダーを指定します。(pre、normal、post ローダー)
2. インライン モード: 各インポート ステートメントでローダーを明示的に指定します。(インラインローダー)

インラインローダー

使用法: css-loader と style-loader を使用して、styles.css ファイルを処理します。import Styles from 'style-loader!css-loader?modules!./styles.css';

リソース内のローダーは !,? で区切ります。これはパラメータをフロントに渡すためであり、インラインローダーは異なるプレフィックスを追加することで他のタイプのローダーをスキップできます。

通常どおりに設定されたローダーをスキップするには、前に ! を追加します。

import Styles from '!style-loader!css-loader?modules!./styles.css';

-! preおよびnormalとして設定されたスキップローダー。

import Styles from '-!style-loader!css-loader?modules!./styles.css';

!! pre、normal、post として設定されたスキップローダー。

import Styles from '!!style-loader!css-loader?modules!./styles.css';

ローダーの分類

ローダーによって受け入れられるパラメータ:
content ソース ファイル
マップのコンテンツ SourceMap データ
メタ データ (任意のコンテンツ)

1. ローダーを同期する

処理対象のソースコードをパラメータとして受け取り、変換されたjsコードを出力します。

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

this.callback メソッドは、コンテンツだけでなく複数のパラメーターを渡すことができるため、より柔軟です。

module.exports = function (content, map, meta) {
    
    
  // 传递map,让source-map不中断
  // 传递meta,让下一个loader接收到其他参数
  this.callback(null, content, map, meta);
  return; // 当调用 callback() 函数时,总是返回 undefined
};

2. 非同期ローダー

module.exports = function (content, map, meta) {
    
    
  const callback = this.async();
  // 进行异步操作
  setTimeout(() => {
    
    
    callback(null, result, map, meta);
  }, 1000);
};

同期計算は時間がかかりすぎるため、Node.js などのシングルスレッド環境で実行するのは得策ではなく、ローダーはできるだけ非同期にしてください。ただし、計算量が少なければローダーの同期も可能です。

3.ローローダー

デフォルトでは、リソース ファイルは UTF-8 文字列に変換されてからローダーに渡されます。raw を true に設定すると、ローダーは、通常、画像、フォント、その他のリソースの処理に使用されるオリジナルのバッファーを受け取ることができます。

module.exports = function (content) {
    
    
  // content是一个Buffer数据
  return content;
};
module.exports.raw = true; // 开启 Raw Loader

4.ピッチングローダー

module.exports = function (content) {
    
    
  return content;
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {
    
    
  console.log("do somethings");
};

Webpack は、まずローダー チェーン内の各ローダーでピッチ メソッド (存在する場合) を左から右に実行し、次にローダー チェーン内の各ローダーで通常のローダー メソッドを右から左に実行します。
ここに画像の説明を挿入します
このプロセス中に、いずれかのピッチが値を返した場合、ローダー チェーンはブロックされます。webpack は、後続のピッチとローダーをすべてスキップし、前のローダーに直接進みます。
ここに画像の説明を挿入します

ローダーAPI

ここに画像の説明を挿入します
詳細はこちらを参照してください。

カスタムローダー

クリーンログローダー

機能: js コード内の console.log をクリーンアップするために使用されます。

// loaders/clean-log-loader.js
module.exports = function cleanLogLoader(content) {
    
    
  // 将console.log替换为空
  return content.replace(/console\.log\(.*\);?/g, "");
};

バナーローダー

機能: JSコードにテキストコメントを追加します。

ローダー/バナーローダー/index.js:

const schema = require("./schema.json");

module.exports = function (content) {
    
    
  // 获取loader的options,同时对options内容进行校验
  // schema是options的校验规则(符合 JSON schema 规则)
  const options = this.getOptions(schema);

  const prefix = `
    /*
    * Author: ${
      
      options.author}// 这也可以直接一个字符串写死,就不用json和options配置了
    */
  `;

  return `${
      
      prefix} \n ${
      
      content}`;
};

ローダー/バナーローダー/schema.json:

{
    
    
  "type": "object",
  "properties": {
    
    
    "author": {
    
    
      "type": "string"
    }
  },
  "additionalProperties": false
}

webpack.config.js で使用: ルールを追加:

{
    
    
  test: /\.js$/,
  loader: "./loaders/banner-loader",
  options: {
    
    
	author: "zagiee"
  }
},

バベルローダー

機能: js コードをコンパイルし、ES6+ 構文を ES5- 構文にコンパイルします。

依存関係をダウンロードします。npm i @babel/core @babel/preset-env -D

ローダー/babel-loader/index.js:

const schema = require("./schema.json");
const babel = require("@babel/core");

module.exports = function (content) {
    
    
  const options = this.getOptions(schema);
  // 使用异步loader
  const callback = this.async();
  // 使用babel对js代码进行编译
  babel.transform(content, options, function (err, result) {
    
    
    callback(err, result.code);
  });
};

ローダー/バナーローダー/schema.json:

{
    
    
  "type": "object",
  "properties": {
    
    
    "presets": {
    
    
      "type": "array"
    }
  },
  "additionalProperties": true
}

webpack.config.js で使用: ルールを追加:

{
    
    
  test: /\.js$/,
  loader: "./loaders/babel-loader",
  options: {
    
    
	presets: ["@babel/preset-env"]
  }
},

バベル公式サイト

ファイルローダー

機能:ファイルをそのまま出力します。

パッケージをダウンロード:npm i loader-utils -D

ローダー/ファイルローダー.js:

const loaderUtils = require("loader-utils");

function fileLoader(content) {
    
    
  // 根据文件内容生产一个新的文件名称
  const filename = loaderUtils.interpolateName(this, "[hash].[ext]", {
    
    
    content,
  });
  // 输出文件
  this.emitFile(filename, content);
  // 暴露出去,给js引用。
  // 记得加上''
  return `export default '${
      
      filename}'`;
}
fileLoader.raw = true;// 图片是 Buffer 数据
module.exports = fileLoader;

ローダー構成:

{
    
    
  test: /\.(png|jpe?g|gif)$/,
  loader: "./loaders/file-loader.js",
  type: "javascript/auto", // 只使用自定义的loader,解决图片重复打包问题
},

スタイルローダー

機能: スタイルタグを動的に作成し、js にスタイルコードを挿入し、スタイルを有効にします。

ローダー/スタイルローダー.js

const styleLoader = () => {
    
    };

styleLoader.pitch = function (remainingRequest) {
    
    
  /*
    remainingRequest: C:\Users\86176\Desktop\source\node_modules\css-loader\dist\cjs.js!C:\Users\86176\Desktop\source\src\css\index.css
      这里是inline loader用法,代表后面还有一个css-loader等待处理

    最终我们需要将remainingRequest中的路径转化成相对路径,webpack才能处理
      希望得到:../../node_modules/css-loader/dist/cjs.js!./index.css

    所以:需要将绝对路径转化成相对路径
    要求:
      1. 必须是相对路径
      2. 相对路径必须以 ./ 或 ../ 开头
      3. 相对路径的路径分隔符必须是 / ,不能是 \
  */
  const relativeRequest = remainingRequest
    .split("!")
    .map((part) => {
    
    
      // 将路径转化为相对路径
      const relativePath = this.utils.contextify(this.context, part);
      return relativePath;
    })
    .join("!");

  /*
    !!${relativeRequest} 
      relativeRequest:../../node_modules/css-loader/dist/cjs.js!./index.css
      relativeRequest是inline loader用法,代表要处理的index.css资源, 使用css-loader处理
      !!代表禁用所有配置的loader,只使用inline loader。(也就是外面我们style-loader和css-loader),它们被禁用了,只是用我们指定的inline loader,也就是css-loader

    import style from "!!${relativeRequest}"引入css-loader处理后的css文件
      为什么需要css-loader处理css文件,不是我们直接读取css文件使用呢?
      因为可能存在@import导入css语法,这些语法就要通过css-loader解析才能变成一个css文件,否则我们引入的css资源会缺少
    const styleEl = document.createElement('style')
      动态创建style标签
    styleEl.innerHTML = style
      将style标签内容设置为处理后的css代码
    document.head.appendChild(styleEl)
      添加到head中生效
  */
  const script = `
    import style from "!!${
      
      relativeRequest}"
    const styleEl = document.createElement('style')
    styleEl.innerHTML = style
    document.head.appendChild(styleEl)
  `;

  // style-loader是第一个loader, 由于return导致熔断,所以其他loader不执行了(不管是normal还是pitch)
  return script;
};

module.exports = styleLoader;

参考資料

おすすめ

転載: blog.csdn.net/zag666/article/details/131954094