Express and Handlebars: Implementing multiple themes

为君一笑 提交于 2020-02-06 07:52:49

问题


I and the team got a task to implement multiple themes for our project (keeping in mind that we have a single-theme project right now).

By theme I don't mean just CSS, I mean different markup files, certain features for certain things, etc. (If you don't like the word 'theme' in this context don't use it, I hope you get the idea: some things need to be reused across the codebase, some things need to be specific to a theme). Overall, we have no problem of structuring it in a maintainable way and implementing the most of it, but we don't know how to make multiple express-handlebars configs, which we can switch based on certain factors.

Right now we have a pretty standard express-handlebars project structure like such:

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

What we want is something like this:

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

We use a pretty standard way to initialize express-handlebars in our app startup file like this:

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');

I was thinking to initialize several exphbs objects and switch them at runtime (request time) but this is not going to work since app.set would be an app-wide setting (long story short we host multiple websites with one app and can't afford change anything on app level, only on the express request level).

Desired behaviour is something like this:

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

looks like there's no problem just to render directly without a configuration, but then we also need to specify that handlebars needs to grab layouts and partials for a specific theme from a specific source

or

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

We're using this variant of express handlebars – https://github.com/ericf/express-handlebars (May be you can advice an alternative that allows what I described above that we can interchange and not break a lot of things - our code base is pretty huge)?

Any of your help, ideas or advice would be highly appreciated.


回答1:


You didn't mention how you would determine which theme each request would be rendered with but I think the simplest approach is to override the res.render() method.

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';
}

The nice thing about this is your calls in your controller will still be clean - res.render('feature/index.hbs') as long as you have that file in each theme folder you should be good.

You could make getThemeFromRequest a lot smarter and it could check to see if the template exists for that theme and if not render the file from the default theme which may help prevent a bunch of duplicate html.



来源:https://stackoverflow.com/questions/34866926/express-and-handlebars-implementing-multiple-themes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!