koa v2 的 Nunjucks 设置

Nunjucks setup for koa v2

我有一个 Koa v2 应用程序,其中 koa-views@next 作为渲染器和 nunjucks 模板引擎。这是我的工作设置,没有任何问题,我只是混淆了 views 文件夹的双重声明:

const Koa = require('koa');
const nunjucks = require('nunjucks');
const path = require('path');
const router = require('koa-router')();
const views = require('koa-views');

const app = new Koa();

const index = require('./routes/index');

app.use(views(path.join(__dirname, 'views'), {
  extension: 'njk',
  map: { njk: 'nunjucks' },
}));
nunjucks.configure(path.join(__dirname, 'views'), {
  autoescape: true,
});

router.use('/', index.routes(), index.allowedMethods());
app
  .use(router.routes())
  .use(router.allowedMethods());

app.listen(3000);

但是如果我不这样做,渲染就不会工作。如果我取消注释 nunjucks.configure 块,我会收到以下错误:

Template render error: (unknown path)
Error: template not found: layout.njk

我的设置有问题吗?

我想出了一个解决方案,可以在 koa v2 中使用 nunjucks 而无需任何其他渲染器库:

/*
USAGE:

import njk from './nunjucks';

// Templating - Must be used before any router
app.use(njk(path.join(__dirname, 'views'), {
  extname: '.njk',
  noCache: process.env.NODE_ENV !== 'production',
  throwOnUndefined: true,
  filters: {
    json: function (str) {
      return JSON.stringify(str, null, 2);
    },
    upperCase: str => str.toUpperCase(),
  },
  globals: {
    version: 'v3.0.0',
  },
}));

*/

// Inspired by:
// https://github.com/ohomer/koa-nunjucks-render/blob/master/index.js
// https://github.com/beliefgp/koa-nunjucks-next/blob/master/index.js

const Promise = require('bluebird');
const nunjucks = require('nunjucks');

function njk(path, opts) {
  const env = nunjucks.configure(path, opts);

  const extname = opts.extname || '';

  const filters = opts.filters || {};
  //console.time('benchmark');
  const f = Object.keys(filters).length;
  let i = 0;
  while (i < f) {
    env.addFilter(Object.keys(filters)[i], Object.values(filters)[i]);
    i += 1;
  }
  //console.timeEnd('benchmark');

  const globals = opts.globals || {};
  const g = Object.keys(globals).length;
  let j = 0;
  while (j < g) {
    env.addFilter(Object.keys(globals)[j], Object.values(globals)[j]);
    j += 1;
  }

  return (ctx, next) => {
    ctx.render = (view, context = {}) => {
      context = Object.assign({}, ctx.state, context);
      return new Promise((resolve, reject) => {
        env.render(`${view}${extname}`, context, (err, res) => {
          if (err) {
            return reject(err);
          }
          ctx.body = res;
          return resolve();
        });
      });
    };
    return next();
  };
}

module.exports = njk;

Gist