ヒキダスブログ

テック系や最近見たもの感じたことを書いて残す引き出しスペースです

React x TypeScript 学習 (2) - DevServer (webpack-dev-server)

概要

Reac x TypeScriptの1回目では開発環境を作ってみました。

hikidasu.hatenablog.com

npm startを実行してTypeScriptファイルをJSへビルド出力しましたが、できるならブラウザで出力結果の画面を見ながらファイル更新を検知してビルドするといった流れにした方が効率的ですよね。
今回は、webpackのオプションでローカルサーバ立ち上げ・ライブリロード(ファイル変更を検知して自動リロードし)をしてくれるDevServer、 webpack-dev-server を導入していきます。

第1回の環境をベースに進めます。

実装

npm

webpack-dev-serverをnpmでインストールします。

npm install --save-dev webpack-dev-server

次に、npm scriptsにwebpack-dev-serverコマンドを追加します。第1回ではnpm startに対しwebpackコマンドにしていましたが、今回webpack-dev-serverコマンドに対応づけをして、npm run buildを叩いたらwebpackコマンドを実行するようにしました(この辺りの対応づけや命名はプロジェクトに合わせて任意で設定してください)。

{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/react": "^16.8.22",
    "@types/react-dom": "^16.8.4",
    "awesome-typescript-loader": "^5.2.1",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "source-map-loader": "^0.2.4",
    "ts-loader": "^6.0.4",
    "typescript": "^3.5.2",
    "webpack": "^4.35.0",
    "webpack-cli": "^3.3.4",
    "webpack-dev-server": "^3.7.2"
  }
}

ターミナルでnpm startを実行すると、以下のようなログが出てくるのでブラウザを立ち上げて http://localhost:8080/ にアクセスすると、index.htmlが表示されるようになります。

「wds」: Project is running at http://localhost:8080/
「wds」: webpack output is served from /

DevServerオプション

ローカルサーバを立ち上げることはできたものの、npm run buildを実行してdist配下に出力しない限り、「Hello from TypeScript and React!」の文字列が表示されません。つまり、ローカルサーバを立ち上げた状態でビルド結果を読み込むようにしつつ、ファイル変更を監視し更新分を反映する必要があります。それにはDevServerにオプションとして設定を加える必要があります。

設定方法としては2通りあります。

  1. webpack.config.jsにdevServerオブジェクトを追加しその中にオプションを追加
  2. npm scriptsで実行する、webpack-dev-serverコマンドの後ろにオプションを追加

先ほどローカルサーバを立ち上げましたが、逐一ブラウザを立ち上げてURLにアクセスする必要がありました。例えば、コマンド実行したら自動的にブラウザを立ち上げるようにする場合、 1.ではwebpack.config.jsのdevServerオブジェクトにopen: trueを追加します。

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  },
  devServer: {
    open: true
  },
  ...
}

2.の場合、package.jsonnpm startに対し、webpack-dev-serverコマンドの後ろに--openを追加します。

{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --open",
    "build": "webpack"
  },
  ...
}  

ビルド結果の読み込み

実はローカルサーバを立ち上げた際、ビルド結果は以下のURLで確認することができます。

http://localhost:8080/bundle.js

実ファイルとして出力されてはいませんが、なぜこのURLになっているかというとデフォルト設定でpublicPathが /になっているためです。
index.htmlでは ./dist/bundle.jsのファイルを参照するようにしているので、DevServerでもこのパスに合わせる必要が出てきます。

そこで、以下のようにpublicPathキーを追加し/dist/にしておけば、ローカルサーバ立ち上げ後「Hello from TypeScript and React!」が表示されるようになります。

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  },
  devServer: {
    open: true,
    publicPath: '/dist/'
  },
  ...
}

Hot Module Replacement

モジュールの更新に合わせてその更新のみ画面に反映させたい場合、webpackのHot Module Replacement(HMR)を使用します。

webpack.js.org

HMRを使うには、webpack.config.jsのdevServerにhotキーを追加します。

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  },
  devServer: {
    open: true,
    publicPath: '/dist/',
    hot: true
  },
  ...
}  

似たようなもので変更を受けてリロードを行うliveReloadもありますが、こちらを使う場合HMRはdisableにしておくのが良いそうです。

webpack.js.org

ファイル変更検知

DevServerで提供されるモジュール以外のhtmlファイル等の変更を検知するには、watchContentBaseキーを追加する必要があります。こちらをtrueにしておくと、変更を受けて画面のリロードを行ってくれます。

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  },
  devServer: {
    open: true,
    publicPath: '/dist/',
    hot: true,
    watchContentBase: true
  },
  ...
}  

上述の設定まで行ったら、ビルド結果を読み込みファイル変更を検知して反映までをローカルサーバで行なえるでしょう。

その他オプションの詳細はこちらを参照すると良いと思います。

webpack.js.org

振り返り

前回に続いて、開発環境よりの話でしたがローカルサーバまで組み込んだので、ReactとTypeScriptについて次回から書いていこうと思います。とはいえ、webpack周りの設定はつまんだ程度のものなので、こちらも知見あれば追加で上げていこうと思います。