見出し画像

Node.js ExpressのテンプレートエンジンでFailed to lookup viewエラーになった時はどうすればいいか?

はじめに

こんにちは、SHIFT の開発部門に所属しているKatayamaです。

Node.js の Express にはテンプレートエンジンと呼ばれるものがあります。これは static な(静的な)テンプレートファイルを基に、そのファイル内の変数などを置き換えて HTML ファイルを作成してクライアント(ブラウザ)に返す機能です。

今回は、このテンプレートエンジンを利用している時に、"Failed to lookup view "./index.ejs" in views directory "/root/workspace/post-restaurant-reviews/views"" というような、views のエラー(ビューディレクトリ内のビューの検索失敗)が出た時の対処方法についてみていきたいと思います。

Failed to lookup view エラーになった時はどうすればいいか?

エラーの内容と元々の実装

エラーが発生する時の実装としてはこのようなコード。

// ./src/app.js
// ※ES Modulesを利用しているが、ES Modulesを利用しない場合は、"const express = require('express');"のように実装すればいい
import express from "express";
import router from "./routes/index";

const port = process.env.PORT;
const app = express();

app.set("view engine", "ejs");

app.use("/", router);

app.listen(port, () => {
  console.log(`Application listening at ${port}`);
});
// ./src/routes/index.js
// ※こちらも同様にES Modulesを利用している
import { Router } from "express";

const router = Router();

router.get("/", (req, res) => {
  res.render("./index.ejs");
});

export default router;

この時のエラーとしては以下。

Error: Failed to lookup view "./index.ejs" in views directory "/root/workspace/post-restaurant-reviews/views"
    at Function.render (/root/workspace/post-restaurant-reviews/node_modules/express/lib/application.js:580:17)
    at ServerResponse.render (/root/workspace/post-restaurant-reviews/node_modules/express/lib/response.js:1017:7)
    at /root/workspace/post-restaurant-reviews/dist/app.js:20:7
    at Layer.handle [as handle_request] (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/layer.js:95:5)
    at next (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/layer.js:95:5)
    at /root/workspace/post-restaurant-reviews/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/index.js:341:12)
    at next (/root/workspace/post-restaurant-reviews/node_modules/express/lib/router/index.js:275:10)

※ディレクトリ構成は以下(一部省略している)。

[root@localhost ...]# tree -I "node_modules|.git"
.
├── babel.config.js
├── package.json
├── src
│   ├── app.js
│   ├── routes
│   │   └── index.js
│   └── views
│       └── index.ejs
├── webpack.config.js
└── yarn.lock

※ES Modules を利用した実装のための設定については、Node.js で import・export(ES6 の構文)を使えるように webpack × Babel の設定をやってみたを参照。

対処方法

公式に、

This defaults to the views directory in the application root directory.

と書かれている通り、デフォルトでは views のディレクトリはそのアプリケーションのルートディレクトリになるので、./views 以下に view があるものとして動く。

この views ディレクトリを変えればいいので、以下のように追加で実装をする。

// ES Modulesを利用するパターン
import appRoot from "app-root-path";
// 省略

app.set("view engine", "ejs");
app.set("views", appRoot.resolve("src/views"));

app.use("/", router);

// 省略

"app.set('views', appRoot.resolve('src/views'));" の部分で、アプリケーションのルートディレクトリにある src/views 以下(./src/views)を views ディレクトリに設定することができ、これによりエラーが発生しなくなる。

app-root-pathは、相対パスから解放してくれるライブラリで、相対パスで書くのではなく、アプリケーションのどこからでもそのルートディレクトリのパスにアクセスできるようにする機能がある。今回は、「ルートディレクトリのパス+ src/views」というパスを作るのにこれを利用している。

・参考:Using template engines with Express

まとめとして

今回はテンプレートエンジンを利用する際に、views ディレクトリがデフォルトのルートディレクトリの直下にない時に発生するエラーの対処方法についてみてきた。自分でディレクトリの構成をカスタマイズしたい時などにはこうした設定が必要になるので忘れないようにしたい。

__________________________________

執筆者プロフィール:Katayama Yuta
SaaS ERPパッケージベンダーにて開発を2年経験。 SHIFTでは、GUIテストの自動化やUnitテストの実装などテスト関係の案件に従事したり、DevOpsの一環でCICD導入支援をする案件にも従事。 最近開発部門へ異動し、再び開発エンジニアに。座学で読み物を読むより、色々手を動かして試したり学んだりするのが好きなタイプ。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/