diff --git a/README.md b/README.md index f3e68f9d..fe0e88f4 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,9 @@ Just write your HTML modules like you would in the latest Chrome: and ES Module Shims will make it work in [all browsers with any ES Module Support](#browser-support). +NOTE: `script[type="importmap"]` and `script[type="importmap-shim"]` should be placed before +any `script[type="module"]` or `script[type="module-shim"]` in the html. + Note that you will typically see a console error in browsers without import maps support like: ``` diff --git a/src/es-module-shims.js b/src/es-module-shims.js index 12a2d2db..129b8d02 100755 --- a/src/es-module-shims.js +++ b/src/es-module-shims.js @@ -64,6 +64,9 @@ async function topLevelLoad (url, source, polyfill) { } async function importShim (id, parentUrl = pageBaseUrl) { + await featureDetectionPromise; + // Make sure all the "in-flight" import maps are loaded and applied. + await importMapPromise; return topLevelLoad(resolve(id, parentUrl).r || throwUnresolved(id, parentUrl)); } diff --git a/test/dynamic-import-map-shim.html b/test/dynamic-import-map-shim.html new file mode 100644 index 00000000..501e6b1b --- /dev/null +++ b/test/dynamic-import-map-shim.html @@ -0,0 +1,16 @@ + + + + + diff --git a/test/dynamic-import-map-shim.js b/test/dynamic-import-map-shim.js new file mode 100644 index 00000000..2ddd0fb3 --- /dev/null +++ b/test/dynamic-import-map-shim.js @@ -0,0 +1,42 @@ +main(); +async function main() { + insertDynamicImportMap({ + "imports": { + "react-dom": "https://ga.jspm.io/npm:react-dom@17.0.2/dev.index.js" + }, + "scopes": { + "https://ga.jspm.io/": { + "scheduler": "https://ga.jspm.io/npm:scheduler@0.20.2/dev.index.js", + "scheduler/tracing": "https://ga.jspm.io/npm:scheduler@0.20.2/dev.tracing.js" + } + } + }); + + const reactStart = performance.now(); + const [React, ReactDOM] = await Promise.all([ + importShim('react'), + importShim('react-dom'), + ]); + const reactEnd = performance.now(); + + console.log(`React and ReactDOM loaded in ${(reactEnd - reactStart).toFixed(2)}ms`); + console.log({ React, ReactDOM }); + + setTimeout(async () => { + insertDynamicImportMap({ + "imports": { + "lodash": "https://ga.jspm.io/npm:lodash-es@4.17.21/lodash.js", + } + }) + + const lodash = await importShim("lodash") + console.log({ lodash }) + }, 1000) +} + +function insertDynamicImportMap(importMap) { + document.body.appendChild(Object.assign(document.createElement('script'), { + type: 'importmap-shim', + innerHTML: JSON.stringify(importMap) + })); +} diff --git a/test/server.mjs b/test/server.mjs index 4bc00089..1d8bfa35 100644 --- a/test/server.mjs +++ b/test/server.mjs @@ -94,7 +94,7 @@ http.createServer(async function (req, res) { mime = mimes[path.extname(filePath)] || 'text/plain'; const headers = filePath.endsWith('content-type-none.json') ? - {} : { 'content-type': mime } + {} : { 'content-type': mime, 'Cache-Control': 'no-cache' } res.writeHead(200, headers); fileStream.pipe(res); @@ -104,4 +104,4 @@ http.createServer(async function (req, res) { console.log(`Test server listening on http://localhost:${port}\n`); const openOptions = process.env.CI ? { app: ['firefox'] } : {}; -open(`http://localhost:${port}/test/${testName}.html`, openOptions); \ No newline at end of file +open(`http://localhost:${port}/test/${testName}.html`, openOptions);