webpack 4+TypeScript 3+globで開発環境をつくる

はじめに

今日は webpack で TypeScript をコンパイルするための設定をご紹介します。さらに今回はglobを使って、特定ディレクトリ以下のファイルをすべてエントリポイントにする方法をご紹介します。複数ページがあるサイトで、それぞれのページに1つずつエントリポイント(JSファイル)を持たせたい場合に利用可能です。

すべてを一気にインストール、設定することも可能ですが、今回はそれぞれ3つに分けて導入を行います。

npm
6.9.0
TypeScript
3.5.3
webpack
4.36.1
目次
  1. webpack を導入
  2. TypeScript を導入、webpack で使用する設定
  3. glob でエントリポイント自動読込

1.webpack の導入

これから紹介する webpack の導入は、公式サイトのマニュアルを参考に行いました。

今回はwebpack-sample というディレクトリの下に各種ファイルを置くことを想定してご説明します。

1-1. package.json の初期化

$ cd /path/to/webpack-sample
$ npm init -y

処理が完了すると package.json が作られます。それをエディタで開き、description: "",の下部にある"main": "index.js",を削除し、そこに"private": true,を追記。

package.json
{
  "name": "webpack-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js", ← これを削除
  "private": true,    ← これを追加
  ~~~ 省略 ~~~
}

1-2. webpack、webpack-cliのインストール

$ npm i webpack webpack-cli --save-dev

処理が完了すると package-lock.json が作られます。

1-3. エントリポイントとなるJSファイルを作成

今回は、下記のようなファイル構成でJSファイルを作成します。

/webpack-sample
  |- /node_modules
  |- /src
    |- /sub
      |- test-1.js
    |- test-2.js
    |- test-3.js
  |- package-lock.json
  |- package.json
各 test-●.js
// sub/test-1.js
alert("Test 1");

// test-2.js
alert("Test 2");

// test-3.js
alert("Test 3");

1-4. webpack.config.js の作成

/webpack-sample ディレクトリの中に webpack.config.js を作り、下記コードを追加。

webpack.config.js
const path = require("path"); // 出力先ディレクトリ指定で「path.resolve()」使用するため

module.exports = {
  mode: "production", // "development" にすると未圧縮のファイルが生成
  entry: {
    "sub/test-1": "./src/sub/test-1.js",
    "test-2": "./src/test-2.js",
    "test-3": "./src/test-3.js"
  },
  output: {
    path: path.resolve(__dirname, "dist") // 出力先のディレクトリ
  }
};

1-5. webpack実行

下記コマンドで webpack を実行。

$ npx webpack
Hash: 123456789a9876543210
Version: webpack 4.39.2
Time: 407ms
Built at: 2019-08-27 11:00:01 PM
        Asset       Size  Chunks             Chunk Names
sub/test-1.js  945 bytes       0  [emitted]  sub/test-1
    test-2.js  946 bytes       1  [emitted]  test-2
    test-3.js  947 bytes       2  [emitted]  test-3
Entrypoint sub/test-1 = sub/test-1.js
Entrypoint test-2 = test-2.js
Entrypoint test-3 = test-3.js
[0] ./src/sub/test-1.js 16 bytes {0} [built]
[1] ./src/test-2.js 16 bytes {1} [built]
[2] ./src/test-3.js 16 bytes {2} [built]

下記のように、./dist の中にコンパイルされたJSファイルが作られます

/webpack-sample
  |- /dist
    |- /sub
      |- /test-1.js
    |- test-2.js
    |- test-3.js
  |- /node_modules
  |- /src
  |- package-lock.json
  |- package.json

2. TypeScript を導入、webpack で使用する設定

2-1. TypeScript をインストール

npm コマンドで TypeScript と、それを webpack でコンパイルするための ts-loader をインストール。

$ npm i typescript ts-loader --save-dev

2-2. tsconfig.json を作成

下記内容で、tsconfig.json を作成。

tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5",
    "module": "es2015"
  }
}

2-3. JSファイルの拡張子を .ts に変更

src ディレクトリにある各JSファイルの拡張子を .ts に変更

|- /src
  |- /sub
    |- test-1.ts
  |- test-2.ts
  |- test-3.ts

2-4. webpack.config.js を変更

webpack.config.js のエントリポイントの拡張子を ts に変更。また、下記のように moduleresolve の内容を追記。

webpack.config.js
const path = require("path");

module.exports = {
  mode: "production",
  // 【変更】各ファイルの拡張子を .ts に変更
  entry: {
    "sub/test-1": "./src/sub/test-1.ts",
    "test-2": "./src/test-2.ts",
    "test-3": "./src/test-3.ts"
  },
  // 【追加】拡張子が .ts は ts-loader 通す
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader"
      }
    ]
  },
  // 【追加】拡張子省略時に、.ts ファイルを対象にする
  resolve: {
    extensions: [
      ".ts"
    ]
  },
  output: {
    path: path.resolve(__dirname, "dist")
  }
};

2-5. webpack を実行

dist の中にある各JSファイルを一度削除し、下記コマンドで webpack を実行。 処理が完了すると 1-5 と同様に、./dist のなかにコンパイルされたJSファイルができます。

$ npx webpack
Hash: 50e42bbe2ee3fe99e150
Version: webpack 4.39.2
Time: 3655ms
Built at: 2019-08-27 11:55:57 PM
        Asset       Size  Chunks             Chunk Names
sub/test-1.js  945 bytes       0  [emitted]  sub/test-1
    test-2.js  946 bytes       1  [emitted]  test-2
    test-3.js  947 bytes       2  [emitted]  test-3
Entrypoint sub/test-1 = sub/test-1.js
Entrypoint test-2 = test-2.js
Entrypoint test-3 = test-3.js
[0] ./src/sub/test-1.ts 18 bytes {0} [built]
[1] ./src/test-2.ts 18 bytes {1} [built]
[2] ./src/test-3.ts 18 bytes {2} [built]

glob でエントリーポイント自動読込

このままだと、エントリポイントを変更するたびに webpack.config.js を更新する必要があります。そこで、glob プラグインを作って、特定ディレクトリにあるファイルを走査し、entry プロパティに渡すオブジェクトを生成します。

下記のように、webpack.config.js にファイルパスが格納されたオブジェクト「entries」を生成するコードを追記。そして entry プロパティに、その entries を指定します。

webpack.config.js
const glob = require("glob"); // ← 追加
const path = require("path");

// 【追加】srcフォルダ下にある .ts のファイルを抽出、オブジェクトに追加
const entries = {};
const srcFiles = `./src/**/*.ts`;
glob.sync(srcFiles).map(function (file) {
  const key = file.replace("src/", "").replace(/\.ts$/, "");
  entries[key] = file;
});

module.exports = {
  mode: "production",
  entry: entries, // ← 上記で作った entries オブジェクトに変更
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader"
      }
    ]
  },
  resolve: {
    extensions: [
      ".ts"
    ]
  },
  output: {
    path: path.resolve(__dirname, "dist")
  }
};

あとは、2-5 と同様に、dist ディレクトリにあるJSファイルを削除し、npx webpackコマンドを実行して、dist の中にファイルがコンパイルされていれば完了です。