Appearance
Import maps
Status: target state. The current gateway does not serve a centralized import map. Each package's browser bundle includes its dependencies bundled in. This page documents what import maps would do and why it's a known target.
Today: each package bundles its own
Every Matrix browser package's dist/browser/ is a self-contained bundle. If @open-matrix/chat and @open-matrix/director both depend on @open-matrix/core's browser modules, both bundles include their own copy.
Trade-offs:
- Pro: Hermetic. A package's behavior doesn't change based on what other packages are loaded.
- Pro: No coordination required. Packages can publish independently.
- Con: Larger total payload when multiple Matrix apps load in the same page (the platform shell hosts several at once).
- Con: Two copies of
@open-matrix/corein the same browser context can breakinstanceofchecks across packages.
Target state: shared modules via import maps
The browser's import maps spec lets a page declare:
html
<script type="importmap">
{
"imports": {
"@open-matrix/core": "/_shared/@open-matrix/core@1.0.2/dist/browser/index.js",
"@open-matrix/chat-component": "/_shared/@open-matrix/chat-component@0.2.3/dist/browser/index.js"
}
}
</script>Subsequent import '@open-matrix/core' from any package's bundle resolves to the shared URL. The browser fetches each module once across the page.
For Matrix this would mean:
- The gateway serves a path like
/_shared/<package>@<version>/...that reads from a Host-level shared module store. - The platform shell injects an import map at page load referencing all shared dependencies.
- Package bundles are built to not include shared deps (a build flag), relying on the import map to resolve them.
Why it's not done yet
Three blockers:
- Cross-package version compatibility. With shared modules, two packages installed at incompatible
@open-matrix/coreversions can't coexist on one page. Today's bundle-everything approach hides this; an import map exposes it. The discovery-metadatarequires/providescapability resolution (target state in the package catalog) is a prerequisite. - Build pipeline coordination. Each package's build must know which modules to externalize. That requires a project-wide convention.
- Cache strategy. Shared modules want long cache lifetimes. The current gateway emits
cache-control: no-cacheon everything. Distinguishing immutable shared modules from per-package files requires a layered cache-control policy.
These are not technically hard but each requires alignment across many packages.
Workaround today
Packages that absolutely need to share state with another package use one of:
- Same-package mounting. If two surfaces really need to share a class, mount them from the same package.
- Bus-based coordination. Send messages over Matrix RR. Different package versions can interoperate by contract.
- Globals. If a package defines a known global identifier (e.g.
window.__matrix_runtime__), other packages can find it. This is fragile and discouraged.
Production reality
The biggest current cost of bundle-everything is the platform shell (@open-matrix/matrix-web) loading multiple webapp packages in nested iframes / module contexts. Each loads its own copy of core libraries.
For most use cases the cost is tolerable: each app is a single-digit MB. A shell loading 5 apps consumes maybe 30 MB of asset bytes — slow on first load, fine on warm cache.
When this becomes the bottleneck, import maps become priority.
See also
Source: Target-state planning in
WORKSTREAMS/package-structure/. No import-map serving code exists inprojects/matrix-3/packages/system-gateway-http/today.