Настройка Nunjucks для 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

Есть ли проблема с моей настройкой?


person Lanti    schedule 29.11.2016    source источник
comment
Попробуйте передать экземпляр приложения в nunjucks: nunjucks.configure(..., {express: app, autoescape: true}).   -  person Aikon Mogwai    schedule 29.11.2016
comment
Выдает app.set is not a function ошибку в app.set('view', NunjucksView); в файле node_modules\nunjucks\src\environment.js:288. Я думаю, что это просто оболочка для Express приложений, а не для Koa.   -  person Lanti    schedule 29.11.2016
comment
koa-views (и используемая им экспресс-библиотека) имеют проблемы. они не обобщают полностью. например, последний раз, когда я проверял, он не кэширует вложенные шаблоны nunjucks, что означает, что у вас есть вызовы fs-stat в производстве. я рекомендую использовать nunjucks напрямую. проверьте источник github.com/ohomer/koa-nunjucks -render/blob/master/index.js — это также может ответить на ваш вопрос.   -  person danneu    schedule 03.12.2016
comment
Спасибо за предложение. Я придумал решение, как заставить его работать без какой-либо другой библиотеки рендеринга:   -  person Lanti    schedule 04.12.2016


Ответы (1)


Я придумал решение использовать nunjucks без какой-либо другой библиотеки рендеринга в koa v2:

/*
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;

Суть

person Lanti    schedule 04.12.2016