Set "basedir" option for Pug in NestJS

Viewed 2424

I'm trying to use pug layouts in NestJS, however when extending a layout from an absolute path, pug requires the basedir option to be set.

In ExpressJS you would use app.locals.basedir = ..., what would be the equivalent in NestJS?

const server = await NestFactory.create<NestExpressApplication>(AppModule);
server.setViewEngine('pug');
server.setBaseViewsDir(join(__dirname, 'templates', 'views'));
await server.listen(config.server.port);

Using extends /layouts/index in a view would throw the following; the "basedir" option is required to use includes and extends with "absolute" paths.

I'm not looking to use relative paths, since this quickly becomes very messy. E.g. extends ../../../layouts/index

2 Answers

From what I can tell, you can achieve the same functionality as /layouts/index with just using layout/index so long as layout is a folder in your templates/views directory.

I've set up a git repo as a working example so you can test it out yourself and see if I need to go in more depth about anything.

EDIT 6/27/2019:

Thank you, I misunderstood your initial question.

With creating and express based application, you can send an express server to the NestFactory to use that server instance instead of having Nest create a plain instance for you. From here you can set up the express server as you normally would and get the desired functionality. I've modified the git repo to be able to test the scenario better and believe this is what you are looking for.

My main.ts

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication, ExpressAdapter } from '@nestjs/platform-express';
import * as express from 'express';
import { AppModule } from './app.module';
import { join } from 'path';

async function bootstrap() {
  // Creating and setting up the express instanced server
  const server = express();
  server.locals.basedir = join(__dirname, '..', 'views');
  // Using the express server instance in the nest factory
  const app = await NestFactory.create<NestExpressApplication>(AppModule, new ExpressAdapter(server));
  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  app.setViewEngine('pug');
  await app.listen(3000);
}
bootstrap();

Overall the folder set up is like so

src
|-app.controller.ts
|-app.module.ts
|-app.service.ts
|-main.ts
views
|-hello
  |-home.pug
|-message
  |-message.pug
|-templates
  |-layout.pug

And the beginning of my home.pug and message.pug files is extends /templates/layout

After looking around through the documentation, NestJS uses an express under the hood, and gives you access to the underlying instance with getHttpAdapter().getInstance().

Keeping that in mind, we can set the basedir as follows;

const express = server.getHttpAdapter().getInstance();
express.locals.basedir = join(__dirname, 'templates');
Related