我和团队完成了为项目实施多个主题的任务(请记住我们现在有一个单一主题项目)。
通过主题我不是指 CSS ,我的意思是不同的标记文件,某些特定内容的某些功能等等。(如果你不喜欢这个词在这种情况下,'主题'不使用它,我希望你能得到这样的想法:有些东西需要在整个代码库中重用,有些东西需要特定于主题)。总的来说,我们没有以可维护的方式构建它并实现其中大部分的问题,但是我们不知道如何制作多个 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’);
看起来没有问题只是在没有配置的情况下直接渲染,但是我们还需要指定把手需要从特定来源抓取特定主题的布局和部分 < / em>的
或
res.render(‘file.hbs’, { theme: ‘theme1’ });
我们正在使用快速把手的这种变体 - https://github.com/ericf/express-handlebars (也许你可以建议一个替代方案,它允许我上面描述的我们可以交换而不会破坏很多东西 - 我们的代码库非常庞大)?
您的任何帮助,想法或建议都将受到高度赞赏。
答案 0 :(得分:1)
您没有提到如何确定每个请求将使用哪个主题进行渲染,但我认为最简单的方法是覆盖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。