feat(native-federation): honor esmsInitOptions.shimMode:false — native import map injection - #1127
Conversation
|
Hi thanks for this! However I'd recommend against using this runtime in favor of the orchestrator. It's fragile and right now it's EOL. If you want to know more about this, have a look at our docs! That orchestrator does allow you to opt-out of shimMode as well. |
… main script tag The builder serializes esmsInitOptions into the esms-options tag but hardcodes the main bundle as <script type="module-shim">, so shimMode: false is dead on arrival: the browser skips module-shim (an unknown type), and es-module-shims force-enables shim mode when it sees any -shim script. A host that wants to run its module graph natively - for example through @softarc/native-federation-orchestrator with a native import map - never can. Emit <script type="module"> when esmsInitOptions.shimMode === false. With shimMode true or unset the output is byte-for-byte unchanged.
f87e39d to
af7166b
Compare
|
Thanks a lot for the feedback! I tried the orchestrator as suggested — it I have re-scoped this PR down to exactly that part: one commit, +5/−1 in Here is a reproducible demo on your examples workspace (nf 21.2.3 + Is there an easier approach that doesn't require touching |
|
Fair, and acceptable. I don't think there is another way. |
Motivation
Native Federation always drives the module graph through es-module-shims'
shim mode: the builder hardcodes the main bundle as
<script type="module-shim">and the runtime always injects<script type="importmap-shim">. In shim mode es-module-shims fetches everymodule and re-executes it from
blob:URLs — stack traces point at blobs,DevTools source-map resolution suffers, and every module is fetched and
rewritten twice.
Import maps themselves are baseline in all evergreen browsers today. The one
thing Native Federation additionally needs — appending a further import map
after module loading has begun (when a remote is loaded at runtime) — is
supported natively in Chrome 133+ and Safari 18.4+ (Firefox gates multiple
import maps behind a pref at the time of writing). On those platforms a page
can run its whole federated module graph natively: real URLs in stack traces,
exact source maps, no double fetch, no blob rewriting.
esmsInitOptionsalready acceptsshimMode: falseand the builder alreadyserializes it into the
esms-optionstag — but the option was dead end toend: the runtime still injected
importmap-shim(which only es-module-shimsreads), and the hardcoded
module-shimscript type both prevented nativeexecution and made es-module-shims' auto-detection force shim mode back on.
Change
native-federation-runtime:appendImportMaphonors the page's shimmode. When the
esms-optionstag explicitly contains"shimMode": false, inject a NATIVE<script type="importmap">insteadof
importmap-shim. The native map is an inline script the browserparses, so under a nonce-based
script-srcit must carry the page's CSPnonce — the runtime propagates the nonce from any nonced script on the
page (with
'strict-dynamic'the nonce is redundant but harmless; the.nonceIDL property is read because browsers hide the contentattribute).
native-federationbuilder: the index transform follows. WithesmsInitOptions.shimMode === false, the main bundle is emitted as<script type="module">instead of the hardcodedmodule-shim, so thebrowser executes it natively. Injection order is safe by Native
Federation's own bootstrap pattern:
initFederation()appends the importmap before
import('./bootstrap')pulls in anything that uses sharedpackages.
Default unchanged in both places: without an
esms-optionstag, or withshimModetrue or unset, behavior is byte-for-byte as before(
module-shim+importmap-shim).Usage
Nothing else changes; removing the option (or setting
true) restores shimmode. Users who need older-browser coverage simply keep the default.