Native ES modules
Bundlers resolve the bare js-message import normally. Native browser ESM resolves it through a standard import map, with no build or transpilation step.
<script type="importmap">
{
"imports": {
"js-message": "./node_modules/js-message/index.js",
"js-message/": "./node_modules/js-message/"
}
}
</script>
<script type="module">
import Message from 'js-message';
const ready = new Message({
type: 'page.ready',
data: { path: location.pathname }
});
console.log(ready.JSON);
</script>This map is complete because js-message has zero runtime dependencies, so it needs no dependency or scope entries. The paths are relative to the HTML document. Serve the app over HTTP(S), and configure the server to expose these node_modules files; file:// is not supported.
Browser-global entry
<script src="./node_modules/js-message/js-message-vanilla.js"></script>
<script>
const message = new Message();
message.type = 'legacy.ready';
message.data = { ok: true };
</script>The side-effect file assigns the class to globalThis.Message. It is behaviorally tested against the module class, including object and JSON loading, optional fields, malformed-input recovery, and serializable errors.
HTML script elements are not self-closing. The explicit </script> prevents the browser from treating later markup as script content.
WebSockets and workers
const socket = new WebSocket(url);
socket.addEventListener('message', (event) => {
const message = new Message(event.data);
if (message.type === 'error') {
console.error(message.data.err);
return;
}
dispatch(message.type, message.data);
});In a worker, use the ES-module entry or load the global file through your existing worker strategy. The global entry targets globalThis, not only window.