手を取ってWebpack Loaderを書いてあげます.


本論文のソースコードの例は、githubブログを押してください.
この文章はloaderのいくつかの使用方法を紹介しません.知らない方は自分でWebpack loaderを調べてください.
1、背景
まず、私達はなぜloaderが必要ですか?彼は何ができますか?webpackは、JavaScriptおよびJSONファイルしか理解できない.loaderは、他のタイプのファイルをwebpackに処理させ、アプリケーションのために有効なモジュールに変換し、依存図に追加する.
本質的には、loadernodeモジュールであり、これはwebpackにおける「すべてのものがモジュールである」という考え方にぴったりです.nodeモジュールである以上、必ず何かを導出します.webpackの定義では、loaderは、変換元モジュールloaderの時に関数を呼び出す関数を導出する.この関数の内部では、resourceコンテキストに入ることによって、Loader APIに対して使用することができる.最終的には直接参照できるモジュールに取り付けます.
2、xml-loader実現
前に知っていましたが、WebpackはNode.jsの上で実行されていますので、Loaderは実はNode.jsモジュールです.このモジュールは関数を導出する必要があります.この導出された関数の仕事は、処理前のコンテンツを取得し、元のコンテンツに対して処理を実行した後、処理後の内容に戻ります.簡単なloaderソースは以下の通りです.
module.exports = function(source) {
  // source   compiler     Loader          
  //              ,      ,         ,     Loader        
  return source;
};
LoaderがNode.jsで実行しているので、Node.jsが所有するAPIを呼び出したり、第三者のモジュールをインストールして呼び出したりできます.

const xml2js = require('xml2js');
const parser = new xml2js.Parser();

module.exports =  function(source) {
  this.cacheable && this.cacheable();
  const self = this;
  parser.parseString(source, function (err, result) {
    self.callback(err, !err && "module.exports = " + JSON.stringify(result));
  });
};
ここで私たちは簡単にthis を実現します.
注意:処理の順番が最後の場合はxml-loaderでは、その戻り値は最終的に渡されます.loaderwebpack、言い換えれば、それは一定の期間で実行されます.requireスクリプト(文字列で保存)は、より正確には、1つです. JSモジュールのnode脚本ですので、必要です.JS エクスポートします
全体のプロセスはこのloaderがソースファイルを
//     source   
転化する
// example.js
module.exports = '    source   ';
その後、リキュールの呼び出し元に渡す:
// applySomeModule.js
var source = require('example.js'); 
console.log(source); //     source   
書き終わったら私たちはどうやって現地で検証しますか?簡単なデモを書いて検証します.
2.1、検証
まず、私達はルートディレクトリxml-loaderを作成します.このディレクトリの下でnpm init-yはデフォルトのpackage.jsonファイルを生成して、ファイルの中にパッケージコマンドを配置します.
"scripts": {
    "dev": "webpack-dev-server"
  },
module.exports =の後、npm i -D webpack webpack-cliをインストールし、ルートディレクトリにプロファイルwebpackを作成する.
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.xml$/,
        use: ['xml-loader'],
      }
    ]
  },
  resolveLoader: {
    modules: [path.join(__dirname, '/src/loader')]
  },
  devServer: {
    contentBase: './dist',
    overlay: {
      warnings: true,
      errors: true
    },
    open: true
  }
}
ルートディレクトリにsrcディレクトリを作成し、index.jsを作成します.
import data from './foo.xml';

function component() {
  var element = document.createElement('div');
  element.innerHTML = data.note.body;
  element.classList.add('header');
  console.log(data);
  return element;
}

document.body.appendChild(component());
同時にもう一つのwebpack.config.jsファイルがあります.


    Mary
    John
    Reminder  dd
    Call Cindy on Tuesday dd
最後に上のfoo.xmlxml-loaderフォルダの下に置いてください.完全なデモのソースコードを見てください.最終的に私達の運行効果は下の図のようです.
これで簡単なsrc/loaderが完成しました.もちろん最終的にはnpmでリリースできます.
3、若干の議論知識の補充
3.1、Loaderのoptionsを獲得する
私達がloaderを配置する時、私達はよくこのような構成を見ます.
ules: [{
    test: /\.html$/,
    use: [ {
      loader: 'html-loader',
      options: {
        minimize: true
      }
    }],
  }]
私たちはこの設定情報をどうやってloaderから取得しますか?答えはwebpack loaderです.これはwebpackが提供するツールです.それでは、使い方を見てみましょう.
const loaderUtils = require('loader-utils');
module.exports = function(source) {
  //          Loader     options
  const options = loaderUtils.getOptions(this);
  return source;
};
そうです.こんなに簡単です.
3.2、ローカルLoaderをロードする
1、path.resoveは簡単にruleオブジェクトにpath.resoveを設定することによってこのローカルファイルを指すことができます.
{
  test: /\.js$/
  use: [
    {
      loader: path.resolve('path/to/loader.js'),
      options: {/* ... */}
    }
  ]
}
2、ResoloveLoaderこれは上で使った方法です.loader-utilsは、ResolveLoaderを構成するために、Webpackをどのように探していますか?デフォルトではノドにしか行きません.modulesディレクトリの下で探してみると、LoaderにローカルプロジェクトにおいてWebpackをロードさせるためには、Loaderを修正する必要がある.ローカルresolveLoader.modulesがプロジェクトディレクトリのLoaderにある場合、次のような構成が必要である.
module.exports = {
  resolveLoader:{
    //          Loader,       
    modules: ['node_modules','./loaders/'],
  }
}
以上の構成を加えると、./loaders/loader-nameは先にWebpackプロジェクトの下でnode_modulesを探しに行きます.もし見つけられなかったら、Loaderカタログの下で探します.3、npm link ./loaders/ は、特別に現地のnpm linkモジュールを開発し、調整するために使用され、モジュールを発行しない場合、現地の開発中のモジュールのソースコードをプロジェクトのnpmディレクトリにリンクし、プロジェクトが直接に現地のnode_modules モジュールを使用できるようにすることができます.ソフトリンクで実現したので、ローカルのNpmモジュールコードを編集し、プロジェクトでも編集後のコードを使用できます.npmを完了するステップは以下の通りである.
  • は、開発中のローカルnpmモジュール(すなわち開発中のLoader)のnpm link が正しく配置されていることを確保する.
  • は、ローカルpackage.json モジュールのルートディレクトリの下でnpm を実行し、ローカルモジュールをグローバルに登録する.
  • は、プロジェクトのルートディレクトリの下でnpm linkを実行し、第2のステップをグローバルに登録したローカルNpmモジュールをプロジェクトのnpm link loader-nameにリンクさせ、node_moduelsは、第1のステップのloader-name ファイルに配置されたモジュール名を指す.
  • package.json をリンクしてプロジェクトに着いたら、本物のNpmモジュールを使うようにローカルの Loaderを使うことができます.(npm linkはあまり馴染みがなくて、複製されたもの)
    3.3、キャッシュ加速
    場合によっては、大量の計算が必要となる場合もありますが、再構築のたびに繰り返し変換操作を行うと、構築は非常に遅くなります.このため、Webpackは、デフォルトでは、Loaderの処理結果をすべてキャッシュしています.つまり、処理が必要なファイルやその依存ファイルに変化がない場合は、対応するLoaderを呼び出して変換操作を行うことはありません.
    このLoaderの処理結果をWebpackにキャッシュしてもらいたいなら、これでいいです.
    module.exports = function(source) {
      //     Loader      
      this.cacheable(false);
      return source;
    };
    3.4、バイナリデータの処理
    デフォルトの場合、WebpackがLoaderに伝えた内容はすべてUTF-8フォーマットの符号化文字列です.しかし、いくつかの場面では、Loaderはテキストファイルを処理するのではなく、バイナリファイルを処理しています.例えばfile-loaderは、WebpackがLoaderにバイナリフォーマットのデータを入力する必要があります.そのためには、Loaderをこのように書く必要があります.
    module.exports = function(source) {
        //   exports.raw === true  ,Webpack    Loader   source   Buffer    
        source instanceof Buffer === true;
        // Loader           Buffer    
        //   exports.raw !== true  ,Loader       Buffer      
        return source;
    };
    //    exports.raw      Webpack   Loader           
    module.exports.raw = true;
    
    以上のコードの中で最も重要なコードは最後の行 Loaderで、行のLoaderがないと文字列を得ることができます.
    3.5、同期と非同期
    Loaderには同期と非同期があります.上で紹介したLoaderは同期のLoaderです.彼らの変換プロセスは同期しています.変換が完了したら結果を返します.しかし、いくつかの場面では、変換のステップは非同期的にのみ行われ、例えば、ネットワーク要求によって結果が得られ、同期的にネットワーク要求が構築全体をブロックし、構築が非常に遅い.
    変換ステップが非同期の場合、このようにしても良いです.
    module.exports = function(source) {
        //    Webpack         ,Loader    callback      
        var callback = this.async();
        someAsyncOperation(source, function(err, result, sourceMaps, ast) {
            //    callback           
            callback(err, result, sourceMaps, ast);
        });
    };
    参照
    webpack loaderを作成します.