https://github.com/samthor/html-modules-polyfill
HTML Modules Rewriter
https://github.com/samthor/html-modules-polyfill
Last synced: 8 months ago
JSON representation
HTML Modules Rewriter
- Host: GitHub
- URL: https://github.com/samthor/html-modules-polyfill
- Owner: samthor
- License: apache-2.0
- Created: 2019-08-16T04:44:54.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2022-12-09T22:55:03.000Z (over 3 years ago)
- Last Synced: 2025-03-18T02:44:47.915Z (over 1 year ago)
- Language: JavaScript
- Size: 118 KB
- Stars: 12
- Watchers: 4
- Forks: 2
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Rewrites HTML Modules, [as proposed here](https://github.com/w3c/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md), to equivalent JS modules.
This can enable use of HTML Modules inside a build system or in a development environment: as of August 2019, no browser has a native implementation.
# Why
HTML Modules are an interesting future proposal that let you wrap up script and template HTML easily (because HTML from a HTML Module is not automatically added to your global page), rather than having to create your own `` tags.
Inside a HTML Module, you can access the current scoped HTML with `import.meta.document`: see below for an example of exporting a chunk of HTML.
# Usage
This is published on NPM as [html-modules-polyfill](https://www.npmjs.com/package/html-modules-polyfill).
The package exports a single method, `rewrite`.
```js
const rewrite = require('html-modules-polyfill');
async function build() {
const htmlModuleSource = `
Content...
let blogPost = import.meta.document.querySelector("#blogPost");
export {blogPost}
`;
const rewritten = await rewrite(htmlSource);
// do something with generated source (e.g., use as output from Rollup plugin)
}
```
## Intended Use
This single method should be used as part of a Rollup plugin, or perhaps to dynamically rewrite HTML files when fetched as modules.
If you check out the repository, run `./demo/rewrite.js` to see the output for [the demo module](demo/module.html).
## Example Output
The output of the example above will be a single file (regardless of the number of top-level `` tags used) and look like:
```js
const template = document.createElement('template');
const moduleDocument = document.implementation.createHTMLDocument();
template.innerHTML = `
<div id="blogPost">
<p>Content...</p>
</div>
<script type="module">
let blogPost = import.meta.document.querySelector("#blogPost");
export {blogPost}
`;
moduleDocument.body.appendChild(template.content);
import.meta.document = moduleDocument;
let blogPost = import.meta.document.querySelector("#blogPost");
export default moduleDocument;
export { blogPost };
```
# Implementation
The rewriter uses JSDOM and Rollup to find and concatenate every `` found in the passed source, as well as providing the top-level `import.meta.document` based on the HTML itself.
These dependencies aren't exposed, you can't control their inputs, and are entirely internal dependencies.
Notably, the generated HTML still includes the source `<script type="module">` tags, even though they won't be executed by any browser inside a template.
## Explanation
We convert every found `<script type="module">` to a "virtual" import that is imported by a single, virtual entrypoint that we dynamically generate, which also includes the HTML template itself.
This entrypoint script _re-exports_ everything from each module, in order.
We then use Rollup to merge _just_ these virtual imports and the top-level script.
External scripts are imported without re-exporting: i.e., `<script type="module" src="foo.js">` becomes `import './foo.js';`.
# Further Work
Modern browsers provide a unique `import.meta` to every JS module, so adding `.document` property at run-time within a single module is fine.
However, since most further build tools don't understand `import.meta.document` at all (although you can write [a plugin for Rollup](https://github.com/rollup/rollup/pull/2785) which does), rewritten HTML Modules that are later bundled together will probably override each other's document.
We should add a flag to the rewriter to use a local variable name instead (and rewrite usage) so that Rollup and other tools can play nice.
Additionally, there's no source map support ([tracked here](https://github.com/samthor/html-modules-polyfill/issues/1)).