Add option to disable jsx -> htm conversion
I'm using wmr in the test suite for our Preact Devtools extension and I need to verify that it works with a range of Preact versions.
To do so I've set up multiple aliases:
{
"alias": {
"[email protected]": "/vendor/preact-10.0.0-rc.0/preact.js",
"[email protected]": "/vendor/preact.10.3.4/preact.js"
}
And than we can use that with standard imports:
import { h, render } from "[email protected]";
render(
<p>Rendered with 10.3.4</p>,
document.getElementById("app")
);
This works really well except for when I use JSX. JSX is transpiled to htm template strings, but by adding a import htm from "htm/preact" import, an additional version of Preact is pulled in.
import { html } from "/@npm/htm/preact"; // Pulls in wrong version
import { h, render } from "[email protected]";
render(
html`<p>Rendered with 10.3.4</p>`,
document.getElementById("app")
);
To solve this I can come up with two options:
- Transpile JSX to
createElementcalls
This is arguable the more verbose version, but it works. The parsing performance benefit of tagged template strings doesn't really come to play in my set up, so I'm good with createElement calls.
import { h, render } from "[email protected]";
render(
h("p", null, "Rendered with 10.3.4"),
document.getElementById("app")
);
- Inject
htm.bind(h)calls into every file
Another option could be to drop the htm/preact import and initialize the htm constructor anew in each file:
import htm from "/@npm/htm";
import { h, render } from "[email protected]";
const html = htm.bind(h);
render(
html`<p>Rendered with 10.3.4</p>`,
document.getElementById("app")
);
- Transpile to
htmlcalls, but don't injecthtm.bind(h)automatically
This closely ties to 2) and is probably a lot more flexible for the end user. Essentially he'd need to make sure that an html function is present in the module scope themselves.
Ooooh so this is 100% a bug in the npm resolution. Does it happen on master?
Yeah happens on master too. Not sure if it's a resolution issue too. htm can't know which preact version is used on the page. I'm passing the version via an url parameter so that I can run a test against multiple preact versions. So wmr is correct in resolving the preact import inside htm/preact via node resolution to node_modules.
Ah interesting, yeah that's kinda a funky case. A thought: what if we had the HTM plugin detect /** @jsx h */ at the top of files and insert htm.bind(h)? The default would be to pull in htm/preact`, but any file could opt out of it.
@developit ohh I like that very much! That's much better than my proposed solution!! 👍
I just thought of another idea: we could use the new jsxRuntime comment option from Babel to generate a module that pulls in a different h()/jsx().
@developit That sounds even better and more future proof. Love that 👍