mediamonks / pota

Pota :tipping_hand_person: tools to carry your projects
https://mediamonks.github.io/pota/
MIT License
12 stars 5 forks source link

Add support for multiple template engines #30

Open psimk opened 2 years ago

psimk commented 2 years ago

From @ThaNarie in https://github.com/mubanjs/muban-skeleton/issues/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

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 commented 2 years ago

Update

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: