ライブラリの作成

アプリケーション以外に、webpackはJavaScriptライブラリをバンドルするためにも使用できます。以下のガイドは、バンドル戦略を合理化しようとしているライブラリ作成者を対象としています。

ライブラリの作成

ここでは、ユーザーが1から5までの数値を数値表現からテキスト表現に、またはその逆に変換できるようにする小さなライブラリwebpack-numbersを作成すると仮定します。例:2を'two'に変換。

基本的なプロジェクト構造は次のようになります

プロジェクト

+  |- webpack.config.js
+  |- package.json
+  |- /src
+    |- index.js
+    |- ref.json

npmでプロジェクトを初期化し、webpackwebpack-clilodashをインストールします

npm init -y
npm install --save-dev webpack webpack-cli lodash

lodashは、ライブラリにバンドルしたくないため、またはライブラリが簡単に肥大化する可能性があるため、dependenciesではなく、devDependenciesとしてインストールします。

src/ref.json

[
  {
    "num": 1,
    "word": "One"
  },
  {
    "num": 2,
    "word": "Two"
  },
  {
    "num": 3,
    "word": "Three"
  },
  {
    "num": 4,
    "word": "Four"
  },
  {
    "num": 5,
    "word": "Five"
  },
  {
    "num": 0,
    "word": "Zero"
  }
]

src/index.js

import _ from 'lodash';
import numRef from './ref.json';

export function numToWord(num) {
  return _.reduce(
    numRef,
    (accum, ref) => {
      return ref.num === num ? ref.word : accum;
    },
    ''
  );
}

export function wordToNum(word) {
  return _.reduce(
    numRef,
    (accum, ref) => {
      return ref.word === word && word.toLowerCase() ? ref.num : accum;
    },
    -1
  );
}

Webpackの設定

この基本的なwebpack設定から始めましょう

webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'webpack-numbers.js',
  },
};

上記の例では、webpackにsrc/index.jsdist/webpack-numbers.jsにバンドルするように指示しています。

ライブラリの公開

これまでのところ、すべてがアプリケーションのバンドルと同じであるはずです。ここが異なる部分です。エントリポイントからのエクスポートをoutput.libraryオプションを介して公開する必要があります。

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'webpack-numbers.js',
+     library: "webpackNumbers",
    },
  };

エントリポイントをwebpackNumbersとして公開したため、ユーザーはscriptタグを介して使用できます

<script src="https://example.org/webpack-numbers.js"></script>
<script>
  window.webpackNumbers.wordToNum('Five');
</script>

ただし、scriptタグを介して参照されている場合にのみ機能し、CommonJS、AMD、Node.jsなどの他の環境では使用できません。

ライブラリ作成者として、さまざまな環境で互換性を持たせたいと考えています。つまり、ユーザーは以下に示す複数の方法でバンドルされたライブラリを使用できる必要があります

  • CommonJSモジュールrequire:

    const webpackNumbers = require('webpack-numbers');
    // ...
    webpackNumbers.wordToNum('Two');
  • AMDモジュールrequire:

    require(['webpackNumbers'], function (webpackNumbers) {
      // ...
      webpackNumbers.wordToNum('Two');
    });
  • scriptタグ:

    <!DOCTYPE html>
    <html>
      ...
      <script src="https://example.org/webpack-numbers.js"></script>
      <script>
        // ...
        // Global variable
        webpackNumbers.wordToNum('Five');
        // Property in the window object
        window.webpackNumbers.wordToNum('Five');
        // ...
      </script>
    </html>

output.libraryオプションをtype'umd'に設定された状態で更新しましょう

 const path = require('path');

 module.exports = {
   entry: './src/index.js',
   output: {
     path: path.resolve(__dirname, 'dist'),
     filename: 'webpack-numbers.js',
-    library: 'webpackNumbers',
+    globalObject: 'this',
+    library: {
+      name: 'webpackNumbers',
+      type: 'umd',
+    },
   },
 };

これで、webpackはCommonJS、AMD、およびscriptタグで機能するライブラリをバンドルします。

Lodashの外部化

ここで、npx webpackを実行すると、大きなバンドルが作成されることがわかります。ファイルを調べると、lodashがコードとともにバンドルされていることがわかります。この場合、lodashピア依存関係として扱うことをお勧めします。つまり、コンシューマーはすでにlodashをインストールしている必要があります。したがって、この外部ライブラリの制御をライブラリのコンシューマーに譲りたいと考えるでしょう。

これは、externals設定を使用して行うことができます

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'webpack-numbers.js',
      library: {
        name: "webpackNumbers",
        type: "umd"
      },
    },
+   externals: {
+     lodash: {
+       commonjs: 'lodash',
+       commonjs2: 'lodash',
+       amd: 'lodash',
+       root: '_',
+     },
+   },
  };

これは、ライブラリが、コンシューマーの環境で使用可能なlodashという名前の依存関係を予期していることを意味します。

外部の制限

依存関係から複数のファイルを使用するライブラリの場合

import A from 'library/one';
import B from 'library/two';

// ...

externalslibraryを指定しても、バンドルから除外することはできません。一つずつ除外するか、正規表現を使用する必要があります。

module.exports = {
  //...
  externals: [
    'library/one',
    'library/two',
    // Everything that starts with "library/"
    /^library\/.+$/,
  ],
};

最終ステップ

プロダクションガイドに記載されている手順に従って、プロダクション向けに出力を最適化してください。また、生成されたバンドルのパスをpackage.jsonのパッケージのmainフィールドとして追加しましょう。

package.json

{
  ...
  "main": "dist/webpack-numbers.js",
  ...
}

または、このガイドに従って、標準モジュールとして追加します。

{
  ...
  "module": "src/index.js",
  ...
}

キーmainは、package.jsonの標準を指し、moduleは、a proposal であり、JavaScript エコシステムが後方互換性を損なうことなく ES2015 モジュールを使用できるようにするためのものです。

これで、npmパッケージとして公開し、unpkg.comで見つけてユーザーに配布できます。

10 貢献者

pksjcejohnstewsimon045angelmarioaccbyzykEugeneHlushkoAnayaDesignchenxsanwizardofhogwarts