koajs / koa-hbs

Handlebars templates for Koa.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Best way to change layout at runtime?

chrisvariety opened this issue · comments

Hey,

First off: Thanks for making koa-hbs, it is super awesome and fits my needs exactly. ⭐

I am developing a site that has various themes in different layouts, and a different theme is used depending on what URL you hit.

I have this working:

  app.use(function *(next) {
    hbs.configure({
      defaultLayout: 'theme_' + (this.company.theme || 'simple'),
      viewPath: __dirname + '/views'
    });

    this.render = hbs.createRenderer();
    yield next;
  });

But I'm not sure the implications on creating a new renderer every request. Is this a legit technique? Seems like layout caching wouldn't work with this technique... maybe.

Is there a better way to specify the layout at runtime?

Unfortunately, I don't believe I can use the alternative layout syntax because the layout name is dynamic.

Thanks so much!

For now, I've settled on caching the renderers, e.g.

    if (!renderers[theme]) {
      var localHbs = hbs.create();
      localHbs.configure({
        defaultLayout: theme,
        viewPath: __dirname + '/views'
      });

      renderers[theme] = localHbs.createRenderer();
    }

... which I believe should have no performance impact? :fingerscrossed:

Do your routes require different markup or just styling? You should really only need one renderer for your application. Your method you have outlined will end up with a large memory footprint. Each template your are rendering from each renderer will be cached once for every instance it is called from.

If you just need different styling, you should be able to pass the company theme as part of the render context and use that to load the correct style sheet.

Wow, awesome... thanks for the super quick reply.

Unfortunately, each theme has different mark up as well (think Wordpress or Shopify themes) -- thus a whole new layout for each theme.

There's only two themes and four views currently, so this might not be too onerous in the short term... but it doesn't sound very scalable.

It's cool if there's no good solution here -- feel free to close this 'issue', I can see what I can come up with! 😄

You could really go a number of routes with hat requirement. You may consider having a very generic top level layout which basically has the HTML tag, stuff, and then {{{body}}} in the . Set that as your default layout, and then call different templates based on the theme. You could even namespace your templates in directories based on the theme and do some string wrangling in your call to render. You will have to be careful to keep your code DRY.

Alternatively, you could make a mod to koa-hbs where you can pass a layout param as part of the render context. You would need additional considerations for the current caching strategy.

Namespacing... I like it. Thanks @jwilm super helpful. I will try to restructure my views and see what I come up with!