Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple template engines #30

Open
psimk opened this issue Mar 14, 2022 · 1 comment
Open

Add support for multiple template engines #30

psimk opened this issue Mar 14, 2022 · 1 comment
Assignees
Labels
enhancement New feature or request muban-webpack-scripts @pota/muban-webpack-scripts

Comments

@psimk
Copy link

psimk commented Mar 14, 2022

From @ThaNarie in mubanjs/muban-skeleton#44


Currently, the skeleton can only render TS templates – which will stay the preferred way of working.

However, certain projects might benefit from other template languages – like Twig or Handlebars – that better connect with the CMS used in a project.

Since we're using express already to render templates "on the server", and @muban/storybook does support server-side template rendering, we could leverage that to basically support any template engine that express supports – and potentially more.

Goals

  • Be able to render a page, using multiple nested templates
  • Still allow our current "data" setup for pages, but those are passed to templates
  • Still allow defining types for the nested template structure, even though it's not used in the TS templates anymore
  • Add an endpoint to render individual templates "on the server", and configure storybook to load those (instead of the TS templates currently defined in the stories)

Approach (WIP)

In the MubanWebpackConfig > finalDevServer, make the setupMiddlewares allow for different types of template engines (or abstract it away as "plugins").

Example for handlebars:

devServer.app.engine('.hbs', engine({ extname: '.hbs'}));
devServer.app.set('view engine', '.hbs');
devServer.app.set('views', './views');

middlewares.unshift({
  name: 'pages',
  path: '/',
  middleware: ((req, res, next) => {
    res.render('home');
  }),
});

Update the MubanPagePlugin > generatePageAssets to (also) output the raw "page data" instead of (only) the rendered HTML, so the middleware above can make use of this data to render the page based on chosen template engine.

Currently running into issues also setting this in compilation.hooks.processAssets.tapPromise

assets[page.replace('.html', '.json')] = JSON.stringify(pageData);

TypeError: Invalid value used as weak map key

@ThaNarie
Copy link
Member

Update

  • Implemented twing-loader as webpack loader to keep the flow as similar as the ts templates as possible.
  • Added a .twig version of all default skeleton templates, the site is rendering

The twing-loader configuration is a mess though, unclear as of why (maybe partly esm, and partly no webpack 5 support?).

Issue 1 - the environment module path

Either way, the loader config requires a path to a twigEnvironment.js file (environmentModulePath), that exports an instance of TwingEnvironment.

This environment instance is used in two places:

  1. inside the actual loader code – which is using require. This file should be exported as .cjs to be properly loaded.
  2. inside the proceseed twig file from the loader output – which is using webpack_require, expecting a esm module.

Regarding 2) it is possible to load a .cjs file extension and use commonjs exports, but the webpack should be informed that it is indeed a commonjs file. Which means the babel-loader config should accept cjs in the regexp, and the file should be located in the src folder.
Which is something we'd rather not do, since it's more of a loader config file, and not a source file. But otherwise there is no way for webpack to correctly load and process this file (as cjs).

It seems that in this "more modern esm project setup" the twing-loader requires both a cjs and esm version of the environment file. Which is super annoying, but doable if we keep them in the package. If we would expose the loader configuration to outside the project, this would become more cumbersome.

issue 2 - exporting files into the lib folder

The location for the twigEnvironment file should probably be the muban-webpack scripts, positioned in the lib folder when published to npm.

Getting the .cjs file there alone already is an issue, and exporting the .js file (as esm) additionally makes it even more complex.

If we keep it as a .ts file there, it will always be transpiled and renamed to .js. It seems that the TypeScript 4.7 Beta allows two new extensions, .cts and .mts, outputting as the respective js extensions. However, adding an additional TS export config just for this one config file might be a bit overkill.

Maybe we should just create those file in the root of the package folder, and not use TS to transpile and copy them over?

Next steps

I wonder if it would make sense to create a standalone repro of the above issues, and see if the package owner is willing to explain or invest some time into fixing it. Otherwise we have to make some changes in our forked version. Either accepting two config paths, or do internal replacements based on convention, or include esbuild in the loader to transpile a temp cjs file from a passed esm file...

Anyhow:

  • Decide if/how we want to support moving the twigEnvironment to the project level.
  • Decide if/how we want to create or transpile two versions of this configuration file.
  • Decide how we are going to configure the twing-loader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request muban-webpack-scripts @pota/muban-webpack-scripts
Projects
None yet
Development

No branches or pull requests

2 participants