Express 和 Handlebars:实现多个主题

Express and Handlebars: Implementing multiple themes

我和团队的任务是为我们的项目实施多个主题(请记住,我们现在有一个单一主题的项目)。

主题我的意思不仅仅是CSS,我指的是不同的标记文件,某些事物的某些特征等等(如果你不喜欢这个词 'theme' 在这个上下文中不要使用它,我希望你明白这个想法:有些东西需要在代码库中重用,有些东西需要特定于主题)。总的来说,我们在以可维护的方式构建它并实现大部分方面没有问题,但我们不知道如何制作多个 express-handlebars 配置,我们可以根据这些配置进行切换某些因素

现在我们有一个非常标准的 express-handlebars 项目结构,如下所示:

views/
 index
 layouts/
  main.hbs
 content.hbs
 whatever.hbs

我们想要的是这样的:

views/
 themes
  theme1
   layouts/
    main.hbs
   index.hbs
   content.hbs
  theme2
   layouts/
    main.hbs
   index

我们使用非常标准的方式在我们的应用程序启动文件中初始化 express-handlebars,如下所示:

var handlebars = exphbs.create({
  defaultLayout: 'main',
  extname: '.hbs',
  helpers: require('./server/hbsHelpers')
});

app.engine('.hbs', handlebars.engine);
app.set('view engine', '.hbs');
app.set('views', __dirname + '/views');

我正在考虑初始化几个 exphbs 对象并在运行时(请求时)切换它们,但这不会起作用,因为 app.set 将是一个应用程序-广泛的设置(长话短说,我们用一个应用程序托管多个网站,无法在应用程序级别进行任何更改,只能在明确请求级别进行更改)。

期望的行为是这样的:

res.render(‘/theme1/file.hbs’);

貌似不配置直接渲染没问题,但是我们还需要指定handlebars需要从特定的特定主题中抓取特定主题的布局和局部来源

res.render(‘file.hbs’, { theme: ‘theme1’ });

我们正在使用这种变体的快速车把 – https://github.com/ericf/express-handlebars (也许你可以建议一个替代方案,允许我上面描述的我们可以互换而不破坏很多东西 - 我们的代码库非常庞大)?

非常感谢您的任何帮助、想法或建议。

您没有提到如何确定每个请求将呈现哪个主题,但我认为最简单的方法是重写 res.render() 方法。

app.use(function(req, res, next) {
  // cache original render
  var _render = res.render;

  res.render = function(view, options, done) {
    // custom logic to determine which theme to render
    var theme = getThemeFromRequest(req);
    // ends up rendering /themes/theme1/index.hbs
    _render.call(this, 'themes/' + theme + '/' + view, options, done);
  };
  next();
});

function getThemeFromRequest(req) {
  // in your case you probably would get this from req.hostname or something
  // but this example will render the file from theme2 if you add ?theme=2 to the url
  if(req.query && req.query.theme) {
    return 'theme' + req.query.theme;
  }
  // default to theme1
  return 'theme1';
}

这样做的好处是您在控制器中的调用仍然是干净的 - res.render('feature/index.hbs') 只要您在每个主题文件夹中都有该文件就应该是好的。

你可以让 getThemeFromRequest 更聪明,它可以检查是否存在该主题的模板,如果不存在,则从默认主题呈现文件,这可能有助于防止一堆重复 html.