Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@kinchiki

TypeScript+Webpack+Node(Express)でファイル変更後にnodeを自動再起動する

More than 1 year has passed since last update.

はじめに

この記事はLinkbal Advent Calendar 2018の3日目の記事です。昨日は弊社CTOの開発組織の育て方 – エンジニア3人から30人へという、組織と事業が拡大していくことによる技術や採用の変遷のお話です。ぜひご一読いただければ幸いです。

リンクバルに新卒入社して2年目の水野(キンチキ)です。今年の10月からエンジニアではなくビジネス側(?)になったのですが、プライベートでも仕事でもコードはちょくちょく書いているので、もちろんアドベントカレンダーも書きます!

今回はTypeScript+Webpack+Node(Express)でNodeの再起動を自動で行う方法がわからず、あまり良いとは思わないながらも解決できた方法について書きます。

ちなみにリンクバルはTyepScriptを採用していない(!)です。学習コストは仕方ないとしても、型があるおかげでバグは間違いなく減ると思います。あと採用面での効果は絶対に+のはず(水野予測)。

いずれ使ってくれるといいなあ。

パッケージのインストール

最初の工程から説明します。

必要なパッケージを以下のコマンドでインストールします。
yarn addのオプションの-D--devと同じです。
lintは省いています。

$ mkdir sample && cd $_
$ yarn init -y # 初期化
$ yarn add -D @types/express typescript ts-loader webpack webpack-cli nodemon webpack-node-externals # パッケージインストール(devDependencies)
$ yarn add express # パッケージインストール(dependencies)

# npmを使う場合
$ npm init -y
$ npm i -D ...
$ npm i -S express

expresだけdependenciesにしていますが、devDependenciesでもいいかもしれません。
私はdependenciesにしないといけないパッケージがよくわかっていないです。。。

インストールしたパッケージの用途です。

  • @types/express: express用の型定義
  • typescript: TypeScript
  • ts-loader: webpackがTypeScriptをコンパイルできるようになるやつ
  • webpack, webpack-cli: webpack周り
  • nodemon: node再起動
  • webpack-node-externals: WARNING抑制(必須ではない)

tsconfigの作成

tscでtypescriptの設定ファイル(tsconfig)を作成します。

$ npx tsc --init

tsconfigを以下のようにします。
これは開発用なので、本番環境用を作成する際は別途ファイル作成するなどして内容を適宜変更してください。

./tsconfig.js
{
  "compilerOptions": {
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "lib": [
      "es2018",
      "dom"
    ],
    "moduleResolution": "node",
    "removeComments": true,
    "strict": true,
    "noUnusedLocals": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "strictFunctionTypes": false
  }
}

webpack.configの作成

touch webpack.configやエディアでファイルを作成し、以下のようにしてください。

エントリーポイントは./src/server.tsとし、最終的にビルドされるファイルはdist/server.jsとしています。
watchをtrueにしておくことでファイルの変更を検知します。

こちらも開発用なので、本番環境用を作成する際は別途ファイル作成するなどして内容を適宜変更してください。

./webpack.config.js
const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  watch: true,
  mode: 'development',
  entry: './src/server.ts',
  target: 'node',
  externals: [nodeExternals()],
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        loader: 'ts-loader',
        test: /\.ts$/,
        exclude: [
          /node_modules/
        ],
        options: {
          configFile: 'tsconfig.json'
        }
      }
    ]
  },
  resolve: {
    extensions: ['.ts', '.js']
  },
  output: {
    filename: 'server.js',
    path: path.resolve(__dirname, 'dist')
  }
};

nodemon.jsonの作成

touch nodemon.jsonなどで作成し、以下のようにしてください。

watch対象をwebpackのoutputに指定しているディレクトリ(この場合dist)にするのがポイントです。こうすることで、コンパイル後に自動でnodeを再起動してくれます。

./nodemon.json
{
  "restartable": "rs",
  "watch": [
    "dist"
  ],
  "env": {
    "NODE_ENV": "development"
  }
}

expressの実装

srcディレクトリを作り、そこにserver.tsを作成します。/へのgetリクエストに文字列を返す処理だけ書いておきましょう。

$ mkdir src
$ touch src/server.ts
src/server.ts
import * as express from 'express';

const app: express.Application = express();
const router: express.Router = express.Router();
const port = process.env.PORT || 3000;

router.get('/', (req: express.Request, res: express.Response) => {
  res.send('Hello, Express with TypeScript!');
});
app.use('/', router);

app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}/`);
});

最後にpackage.jsonにscriptsを追加しましょう。
webpackとnodemonを&で繋いで同時起動しています。tsファイルが変更されたらwebpackがコンパイルし、nodemonがnodeを再起動します。

./package.json
{
  "name": "express-test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "nodemon dist/server.js & webpack --config webpack.config.js"
  },
  "devDependencies": {
  "以下略"
}

ここまできたら yarn run dev で動かすことができます。

auto-restart-node.gif

ファイルを編集したらnodeが再起動し、リロードしたら反映されていますね!

おわりに

この方法だとエラー箇所がわかりづらかったり、webpackがクラッシュしたらプロセスが残ったりしますが、あまりいい方法が見つからなかったのでいったんこれで開発しています。この方法は手軽なのがウリです。webpack-dev-serverでうまいことホットリロードできると思いましたが、やり方がわかりませんでした。この方法でも支障は特にありません。

プロセスが残っていたら以下のコマンドで一括killしましょう。

kill -9 `ps -ef | grep nodemon |  awk '{print $2;}'`

リンクバルでTypeScriptが採用される日を待っています(強い意思はない)。

参考

このページも結構参考にしたのですが、今は見れなくなっています。
https://dev.to/briandgls/using-typescript-with-express--e0k

ts-nodeを使ったりすればホットリロードできそうですね。

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kinchiki
プログラミングは少し好きです。2018年10月より職種がエンジニアではなくなり、完全にビジネスサイドです。 プログラミングはほぼしません!SQLは書きます!
linkbal
街コンポータルサイト「machicon JAPAN」やマッチングサービス「CoupLink」などを開発・運営しています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?