pug導入前環境

Webpack + Express + React + Typescript

pug導入の理由

導入前はExpressでSSRをし,クライアントからのリクエストに対しres.send(html)で単純にhtmlスクリプトを送信するだけだった.これではデータベースから取得した値をクライアント側に渡すことができない.そのため,テンプレートエンジンであるpug(or ejs)を導入したかった.

やりたいこと

単純にルートにアクセスされた時にhtmlテンプレートに値を渡してレンダリングしたい.今回やりたいこととしては,レンダリングさえしてくれれば良いので,htmlとしてdistに出力されなくて良い(これをしようとするとWebpackでHtmlWebpackPluginが必要)

server.ts
import express from 'express';
const postController = require('./controllers/postController');
const app = express();

app.get('/', postController.doGetPostForSsr);

//静的ファイル
app.use(express.static('dist'))

app.listen(process.env.PORT || 3000, function () {
  console.log('express app is started.');
});
postController.ts
import express from 'express';
const Posts = require('../models/Posts');
const ssrController = require('./ssrController');

module.exports = {
  doGetPostForSsr: (req: express.Request, res: express.Response) => {
    Posts.getPost().then((result) => {
      const elements = ssrController.ssr(result);
      res.render("html", elements);
    }).catch((err) => {console.log(err);})
  }
}

エラー地獄

ただテンプレートエンジン導入するのに1日かかりました....webpack嫌いになりそうでしたけど,自分の力のなさですね,勉強になりました.
どこでどーゆーエラーが出たってのもストーリー立てて説明すると途方もないので,結論の導入方法だけ記述します.

pug導入

pug導入にはExpress側とWebpack側それぞれに設定が必要でした.

Express側pug導入

server.ts
import express from 'express';
const postController = require('./controllers/postController');
const app = express();

app.engine('pug', require('pug').__express); //追加
app.set('view engine', 'pug'); //追加

app.get('/', postController.doGetPostForSsr);

//静的ファイル
app.use(express.static('dist'))

app.listen(process.env.PORT || 3000, function () {
  console.log('express app is started.');
});

これでExpressがpugを認識できるようになり,読み込んでくれるviewsディレクトリがルート直下に設定される?ぽいです.

Webpack側pug導入

npm install webpack-node-externals --save-dev
webpack.server.config.js
const nodeExternals = require('webpack-node-externals');

module.exports = {
  ...
  externals: [nodeExternals()],
  ...
}

これがないとよくわかりませんが,buildは問題なく通りますがアクセス時にCannot find module "../lib/utils.js"ってエラーが出るんですよね.これは【webpack】Cannot find module "../lib/utils.js"を参考にしました.

おわりに

今回の目的はpugコンパイルからのhtmlの出力ではなく,単なるレンダリングでしたので,pug-loaderは使いませんでしたが,いろいろいじっていたところ,htmlの出力をする場合はhtml-webpack-plugin, pug, pug-loader使ってwebpackで設定したらできました.これは調べたらすぐ出てくるのでここに書く必要はないかと.
HTMLもわからない状態から独学を初めて1年と2ヶ月程経つのかな?最初は全てフルスクラッチで記述していたので,最近やっとフレームワークの恩恵とMVCモデルの素晴らしさを理解することができてきました.(最初はサーバーサイドでjs動くってのが衝撃的だったの覚えてますね笑)これからはちょっとはインフラの方も理解できたらなと思います〜.