SharePoint Framework ツールチェーンでの Webpack の拡張

webpack は、JavaScript ファイルとその依存関係を処理して 1 つまたは複数の JavaScript ファイルを生成する JavaScript モジュール バンドラーです。さまざまなシナリオについて異なるコードの部分を読み込むことができます。

開発ツール チェーンは CommonJS を使用してバンドルします。これにより、モジュール、およびそれらを使用する場所を定義することができます。また、ツール チェーンを使用してユニバーサル モジュール ローダーである SystemJS を使用し、モジュールをロードします。これにより、各 Web パーツが独自の名前空間で実行されることを確実にすることによって、Web パーツのスコープをすることができます。

SharePoint Framework のツールチェーンに追加できる一般的なタスクの 1 つは、カスタム ローダーとプラグインを使って Webpack 構成を拡張することです。

Webpack ローダーの使用

開発時に JavaScript 以外のリソースをインポートして利用する機会は数多くあります。この場合、通常はイメージやテンプレートを使用します。 Webpack ローダーは、JavaScript アプリケーションで利用できるものにリソースを変換するか、JavaScript アプリケーションで認識できる単純な参照を提供します。

たとえば、Markdown テンプレートがコンパイルされてテキスト文字列に変換され、イメージ リソースがインライン Base64 イメージに変換されることもあれば、URL として参照されて、dist ディレクトリにコピーされ展開されることもあります。

いくつかの便利なローダーが用意されており、その中のいくつかは標準の SharePoint Framework Webpack 構成で既に使用されています。たとえば、次のローダーがあります。

  • html-loader
  • json-loader
  • loader-load-themed-styles

カスタム ローダーを使用してフレームワークの Webpack 構成を拡張する作業は、簡単なプロセスです。この説明は、「Webpack Loaders (Webpack のローダー)」にあります。

例:markdown-loader パッケージの使い方

一例として、markdown-loader パッケージを使ってみましょう。このローダーでは、.md ファイルを参照し、それを HTML 文字列として出力します。

完成したサンプルは、samples/js-extend-webpack からダウンロードできます。

手順 1 - パッケージをインストールする

プロジェクトで、markdown-loader ローダーを参照します。

npm i --save markdown-loader

手順 2 - webpack を構成する

これでパッケージをインストールできました。次に、SharePoint Framework Webpack の構成に markdown-loader を組み込みます。

markdown-loader のドキュメントには、Webpack 構成を拡張してローダーを組み込む方法が記載されています。

{
  module: {
    rules: [
      {
        test: /\.md$/,
        use: [
          {
            loader: 'html-loader'
          },
          {
            loader: 'markdown-loader',
            options: {
              /* options for markdown-loader here */
            }
          }
        ]
      }
    ]
  }
}

この構成で行われる処理の内容を概観してみましょう。

  • Webpack 構成内の rules 配列は、ファイル パス テスト、およびそのテストと一致するリソースが見つかったときに使用されるローダーのセットを定義します。この場合、test プロパティは、.md で終わるファイル パスをチェックします。
  • use 配列には、リソースに順番に適用されるローダーのリストが記述されます。 最後から最初への順番で適用されます。 ここでは、最初に適用されるローダーが markdown-loader、最後に適用されるローダーが html-loader になります。
  • 複数のローダーが指定されている場合、各ローダーの結果は、次のものにパイプでつながれます。

ここでは、この情報を使用してプロジェクト内で Webpack 構成を構成します。

SharePoint フレームワーク Webpack 構成にこのカスタム ローダーを追加するには、Webpack を構成するようにビルド タスクに指示を与える必要があります。 ビルド タスクは gulpfile.js で定義します。これはプロジェクトのルートにあります。

gulpfile.js を編集し、次のコードを build.initialize(gulp); の直前に追加します。

build.configureWebpack.mergeConfig({
  additionalConfiguration: (generatedConfiguration) => {
    generatedConfiguration.module.rules.push(
      {
        test: /\.md$/,
        use: [
          {
            loader: 'html-loader'
          },
          {
            loader: 'markdown-loader'
          }
        ]
      }
    );

    return generatedConfiguration;
  }
});

このコード スニペットで発生する処理の内容を概観してみましょう。

  • (build.configureWebpack としてインスタンス化された) ConfigureWebpackTask は、Webpack を構成します。SPFx プロジェクトのビルドでは特別な構成が大量に発生するため、このタスクには重要なロジックがいくつかあります。
  • ConfigureWebpackTask は、オプションの additionalConfiguration プロパティを取ります。 このプロパティを関数に設定します。この関数は生成される構成を取り、変更を加え、更新された構成を返します。 この関数は、Webpack 構成をツールチェーンに返す必要があります。そうしないと、Webpack は正しく構成されません。
  • additionalConfiguration に設定する関数の本体内で、構成内の既存のルール セットに新しいルールを単にプッシュします。 この新しいルールは、手順 2 の最初に出てくる構成スニペットの例に似ています。

注意

この方法を使ってツールチェーンの既定の Webpack 構成を完全に置き換えることもできますが、パフォーマンスと最適化のメリットを最大限に活用するために、ドキュメントに明記されていない限り、そのようにすることはお勧めしません。

手順 3 - コードを更新する

これでローダーの構成が終わりました。次に、コードを更新し、いくつかのファイルを追加してシナリオをテストします。

  1. ./src/my-markdown.md というファイルを作成し、その中にいくつかのマークダウン テキストを入力します。

    #Hello Markdown
    
    *Markdown* is a simple markup format to write content.
    
    You can also format text as **bold** or *italics* or ***bold italics***
    

プロジェクトをビルドすると、Webpack markdown-loader によってこのマークダウン テキストが HTML 文字列に変換されます。

  1. ソース .ts ファイルのいずれかでこの HTML 文字列を使用するには、次の require() 行を、ファイル先頭の imports の後に追加します。たとえば、次のとおりです。

    const markdownString: string = require<string>('./../../../../src/my-markdown.md');
    

    Webpack は既定では lib フォルダーからファイルを探しますが、既定では .md ファイルが lib フォルダーにコピーされません。したがって、かなり長い相対パスを作成する必要があります。この設定を制御するには、ツールチェーンが md ファイルを lib フォルダーにコピーするように構成ファイルを定義します。

  2. ファイル ./config/copy-static-assets.json を作成し、いくつかの追加ファイルを src から lib にコピーするようにビルド システムに指示を与えます。このビルド タスクは、既定のツールチェーン Webpack 構成に認識される拡張子 (pngjson など) を持つファイルをコピーします。したがって、md ファイルもコピーするようにビルドタスクに指示を与える必要があります。

    {
      "includeExtensions": [
        "md"
      ]
    }
    
  3. これで、require ステートメントで、相対パスを使う代わりに、ファイル パスを使用できるようになります。たとえば、次のとおりです。

    const markdownString: string = require<string>('./../../readme.md');
    
  4. その後、この文字列をコードで参照することができます。たとえば、次のとおりです。

    public render(): void {
      this.domElement.innerHTML = markdownString;
    }
    

手順 4 - コードをビルドしてテストする

コードをビルドしてテストするために、コンソールから、プロジェクト ディレクトリのルートで、次のコマンドを実行します。

gulp serve

関連項目