NestJS・Handlebars・TailwindCSSでMVCアプリをつくる

2023/12/22に公開

NestJSでMVCパターンを適用してみたのでその手順を備忘録を兼ねて記事にしておきます。

NestJSはサーバーサイドフレームワークであり、MVCパターンを採用することは少ないと思いますが、今回はスピード重視かつ画面がLPのみということで採用してみました。

今回チームで制作したのはこちらのサービスです。

対象バージョン

"@nestjs/cli": "10.0.0"
"@nestjs/common": "10.0.0"
"@nestjs/core": "10.0.0"
"hbs": "4.2.0"
"tailwindcss": "3.4.0"
"npm-run-all": "4.1.5"

1. NestJSの導入(プロジェクトの作成)

npm i -g @nestjs/cli
nest new project-name

npm run start:dev 実行後 http://localhost:3000 にアクセスし "Hello World!" が表示されればOKです。

2. テンプレートエンジンの導入

今回はテンプレートエンジンとしてhbsを利用します。

npm install --save hbs

src/main.ts を以下のようにします。

src/main.ts
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  // アセットファイルの格納先
  app.useStaticAssets(join(__dirname, '..', 'public'));
  // HTMLテンプレートの格納先
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  // hbsテンプレートエンジンを指定
  app.setViewEngine('hbs');

  await app.listen(3000);
}
bootstrap();

views/index.hbs を作成します。一旦表示確認できれば良いので、以下のようにします。

views/index.hbs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>App</title>
  </head>
  <body>
    {{ message }}
  </body>
</html>

続けて src/app.controller.ts を以下のようにします。 @Render('index') の部分は作成したhbsファイル名に合わせます。

src/app.controller.ts
import { Get, Controller, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  // viewsに作成したhbsファイルの名前を指定
  @Render('index')
  root() {
    return { message: 'こんにちは!' };
  }
}

http://localhost:3000/ にアクセスし "こんにちは!" が表示されたらOKです。

2-1. JavaScriptを実行する

通常のHTMLと同様 <script> タグを使ってスクリプトを書くことができます。

別ファイルにしている場合は public/ フォルダに配置して読み込みます。

views/index.hbs
<head>
  <meta charset="utf-8" />
  <script src="javascript/main.js"></script>
  <title>App</title>
</head>

2-2. 画像を表示する

表示したい画像を public/ に配置し、imgタグで配置した画像のパスを指定します。

views/index.hbs
<img src="./images/hello.png">

3. tailwindの導入

以下のコマンドでtailwindをインストールします。完了するとtailwind.config.js が作成されます。

npm install tailwindcss@latest
npx tailwindcss init

続けてtailwindの設定をします。

src/input.css
@tailwind base;
@tailwind components;
@tailwind utilities;
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./views/**/*.hbs'],
  theme: {
    extend: {},
  },
  plugins: [],
}
.gitignore
/public/output.css

package.json に 以下を追記します。

package.json
"scripts": {
  "css": "tailwindcss -i ./src/input.css -o ./public/output.css",
}

CSSの読み込みをします。また背景色を青に設定してみます。

index.hbs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link href="./output.css" rel="stylesheet">
    <title>App</title>
  </head>
  <body>
    <div class="bg-blue-300">
      {{ message }}
    </div>
  </body>
</html>

npm run css を実行後、画面を表示して、背景色の青が適応されていればOKです。

3-1. tailwindの変更を自動反映する

これでtailwindの設定まで完了しましたが、この状態だとtailwindのクラスを記述する毎に npm run css を実行しなければいけません。そこで自動的に反映されるようにします。

複数のnpm scripts を 並列実行するために npm-run-all を利用します。

npm install -D npm-run-all
package.json
"scripts": {
  "css": "tailwindcss -i ./src/input.css -o ./public/output.css --watch",
  "start": "nest start --watch",
  "start:dev": "run-p css start",
}

これでCSSの変更を監視してビルドしてくれるようになりました。 npm run start:dev した後、要素を追加したりtailwindのクラスを追加したりして、画面に反映されればOKです。

Discussion