Web Frontend を Next.js + TypeScript で書いて Docker でビルドする
「手っ取り早く Web インターフェースを手に入れる方法 2020」シリーズ(?)のBFF サンプルプロジェクト と同じように Web Frontend サンプルプロジェクトを作ってみました。
今回もプロジェクト構成やビルド方法の検証が主目的です。
そのためアプリケーション自体は Docker イメージを実行するとNext.jsの Web サーバーが起動しこんなページが表示されるだけのシンプルな機能しかありません。
❯ docker run -it --rm -p 3000:3000 b2ee27d0d01d
> @ start /app
> next start
> Ready on http://localhost:3000
コードは"mazgi-showcase/202001.nextjs-typescript-jest“にあります。
使っている技術スタックは概ね以下です。
- TypeScript
- Next.js v9
- TypeScript 対応が強化された
9
以降を使っています 9.1
からはpages
をsrc
の中に入れられるようになりました- babel-plugin-module-resolver
- TypeScript 対応が強化された
- Jest
- Docker & Docker Compose
- cargo-make
Out of Scope
今回のサンプルでは以下を扱いません。
- Web API / BFF
- Business or domain logic
- Deploy
How to run
BFF と同じように次の 3 ステップで起動できるはずです。
cargo-make
をリリースページからダウンロードしてbin/cargo-make
に配置- (optional)
bin/cargo-make make --makefile tasks/setup-project.toml
を実行して空の設定ファイルを生成- Linux 上で実行する場合にこの手順が必要です
docker-compose up
docker-compose up
すると次の 2 つの Docker コンテナが起動します。
- Visual Studio Code用の Docker コンテナ
- 起動してすぐ終了しますが意図した動作です
- Web Frontend の Docker コンテナ
❯ docker-compose up
Creating network "202001nextjs-typescript-jest_default" with the default driver
Creating 202001nextjs-typescript-jest_vscode_1 ... done
Creating 202001nextjs-typescript-jest_frontend_1 ... done
Attaching to 202001nextjs-typescript-jest_vscode_1, 202001nextjs-typescript-jest_frontend_1
vscode_1 | npm WARN workspace No repository field.
vscode_1 | npm WARN workspace No license field.
vscode_1 |
vscode_1 | audited 475 packages in 1.653s
vscode_1 | found 0 vulnerabilities
vscode_1 |
202001nextjs-typescript-jest_vscode_1 exited with code 0
frontend_1 | npm WARN workspace No description
frontend_1 | npm WARN workspace No repository field.
frontend_1 | npm WARN workspace No license field.
frontend_1 | npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.2 (node_modules/fsevents):
frontend_1 | npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
frontend_1 | npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules/webpack/node_modules/fsevents):
frontend_1 | npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
frontend_1 | npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules/jest-haste-map/node_modules/fsevents):
frontend_1 | npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
frontend_1 |
frontend_1 | audited 891402 packages in 5.599s
frontend_1 | found 0 vulnerabilities
frontend_1 |
frontend_1 |
frontend_1 | > @ dev /workspace
frontend_1 | > next
frontend_1 |
frontend_1 | [ wait ] starting the development server ...
frontend_1 | [ info ] waiting on http://localhost:3000 ...
frontend_1 | [ info ] bundled successfully, waiting for typecheck results...
frontend_1 | [ ready ] compiled successfully - ready on http://localhost:3000
接続すると記事冒頭のスクリーンショットのようなページが返ります。
❯ curl -LI 127.0.0.1:3000
HTTP/1.1 200 OK
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
ETag: "6b2-ISeH+ybP2WwZ4qoLiEZ3PPggx20"
Content-Type: text/html; charset=utf-8
Content-Length: 1714
Vary: Accept-Encoding
Date: Wed, 22 Jan 2020 13:10:11 GMT
Connection: keep-alive
また Web Frontend といいつつサーバーが立っているので存在しない path に接続するとちゃんと 404 が返ります。
❯ curl -LI 127.0.0.1:3000/not-found
HTTP/1.1 404 Not Found
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
ETag: "88b-4CxhQ5CjqmJABvp/LLA2dxUDW5A"
Content-Type: text/html; charset=utf-8
Content-Length: 2187
Vary: Accept-Encoding
Date: Wed, 22 Jan 2020 13:10:17 GMT
Connection: keep-alive
How to resolve module paths
Web Frontend 開発ではだいたい次のようなステップを手動/自動問わず繰り返して開発を進めることになると思います。
npm run dev
npm run test
npm run build
そしてこれらのステップを繰り返す中で使われるツールも tsc
, webpack
, babel
やそれらのプラグイン等多岐にわたります。
そんな中で module の解決に頭を抱えることが多々 Module not found: Can't resolve 'components/xxx' in '/workspace/src/pages'
本サンプルでは試行錯誤の結果、どうにか path 定義の重複を減らすことができた気がします。
ポイントは以下 2 つのようです。
tsconfig.json
のbaseUrl
を指定する(paths
は指定不要).babelrc
内でbabel-plugin-module-resolver
のroot
とextensions
を設定する
だいぶ時間を溶かしたのですが解決してみればたった 2 点ですね、そんなもんです。
Build and just before Deploy
BFF とあまり変わらないのですが、Next.js のDeployment > Self hostingに「.next
, node_modules
, package.json
をサーバーに置くべし」と書かれているのでDockerfile
の中でそのようにしています。
That’s all
どうにか Web API に加えて Web Frontend の 2020 年らしいたたき台を作れたので今後の開発に活かそうと思います。