-
Notifications
You must be signed in to change notification settings - Fork 645
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
Marko 5 ESM Loading/Registering #1727
Comments
@adamchal I am curious how you plan to do bundling with this setup? Also for context we've mostly imagined that people should just be using the Marko require hook in order to import Marko files in nodejs rather than the |
I wrote a really basic ESM loader for Marko (code below), however it seems there would need to be some additional changes to Marko's compiled output to fully resolve some of the imported paths. Currently the output templates rely on nodes module resolution for commonjs. import { URL, pathToFileURL, fileURLToPath } from "url";
import compiler from "@marko/compiler";
import { cwd } from "process";
const baseURL = pathToFileURL(`${cwd()}/`).href;
const extensionRegex = /\.marko$/;
export function resolve(specifier, context, defaultResolve) {
const { parentURL = baseURL } = context;
return extensionRegex.test(specifier)
? {
url: new URL(specifier, parentURL).href,
}
: defaultResolve(specifier, context, defaultResolve);
}
export function getFormat(url, context, defaultGetFormat) {
return extensionRegex.test(url)
? {
format: "module",
}
: defaultGetFormat(url, context, defaultGetFormat);
}
export function transformSource(source, context, defaultTransformSource) {
const { url } = context;
return extensionRegex.test(url)
? {
source: compiler.compileSync(source, fileURLToPath(url), {
sourceMaps: "inline"
}).code,
}
: defaultTransformSource(source, context, defaultTransformSource);
} |
For a quick background, we have a significant amount of work that constitutes simple landing pages that do not maintain state or require UI. We started with some static site generators and over the years developed our own. We soon switched from Pug to Marko, because at the time it was the only template with support for async data and could generate static HTML without any undesired JS overhead in the output. Even still today, the only other one I have found is Eta. We also work on a lot of Next.js/Nuxt.js projects of course, but we try not to introduce these UI frameworks to places they don’t belong. We have also dabbled with Svelte and we have high hopes for Sveltekit and its ability to prerender all of the frontend JS away on some/all pages. It would be great if we could use the same framework to build complex UI+state application and simple landing pages. For our Marko use case, we currently use v4 in a CJS context with the @DylanPiercey thank you for the quick reply and sparking this solution! Ha, I didn’t even consider an ESM loader. The ESM loader has been such a painful and controversial topic, that I’ve just blocked it out. That said, we are already using ts-node/esm as a loader. Given the current inability to use more than one ESM loader, this would not work easily for us. My current ugly solution is to put all of the marko templates in an array, loop over them and This is not a reasonable solution, but since we do not need or use the intermediate compiled .marko.js files, the approach solves our problem. If we pursue an ESM loader approach, we would need to The biggest problem with these approaches is that invalidation becomes very difficult—especially in an ESM context. This is another ESM pain point, but the import cache workarounds are tedious. In a perfect world, we would want to be able to load, compile, and render the .marko templates directly in Node.js without having to worry about the intermediate .marko.js files and the limitations of the CJS/ESM loaders. |
@adamchal I know this isn't an ideal solve, but just stumbled upon https://github.com/node-loader/node-loader-core which is a utility to merge node loaders so you can run multiple. |
@DylanPiercey interesting find and might be workable—thanks! |
Marko Version
5.15.1
Details
Trying to render a Marko template to HTML using Node in a module (ESM) context. Minimal repo showcasing the issue.
Using
marko.load()
to load the Marko templateExpected Behavior
HTML output of test.marko logged to the console.
Actual Behavior
Possible Fix
However, if you
marko.load
the component before loading the template, it works.But, since components can reference other components, you’d have to load them in order of least dependent to avoid the error.
I have not found clear documentation on how to do this in Marko 5. Previously, in Marko 4, I would
require('marko/node-require').install()
and thenrequire
the template. This isn’t working for me in Marko 5 in a CommonJS context.But, I am only interested in the Node ESM output/context.
markoc
is able to compile the .marko templates without any issues, but the ESM output is not compatible with Node’s import requirements (no extensions to marko imports, etc.). I considered stringing Rollup or something else to transpile afterwards, but this started to feel like a lot of overkill for a template.Additional Info
Your Environment
Steps to Reproduce
Clone and run the sample repo: https://github.com/adamchal/marko-5-esm-issue
The text was updated successfully, but these errors were encountered: