es-module-shims: Scripts of type "module-shim" don't seem to have access to specifier defined in importmap

Hi Guy,

In attempting to write a es-module-shims-plugin to parse JSX, I’m finding that files imported via <script type="module-shim"> can't seem to resolve specifiers declared in a <script type="importmap">`. For example,

Working

// ./jsx-app.js
export default 'hello world'

Ad then in the HTML file

<script type="importmap">
{
  "imports": {
    "react": "https://ga.jspm.io/npm:react@18.2.0/index.js"
  }
}
</script>

<script type="module-shim">
      import app from './jsx-app.js'
      console.log(app)
</script>

But this errors

// ./jsx-app.js
import React from 'react'
export default 'hello world'

(The HTML is the same), I get the following error:

es-module-shims.js:440 Uncaught Error: Unable to resolve specifier 'react' imported from http://localhost:3000/test/jsx-app.js
    at throwUnresolved (es-module-shims.js:440:11)
    at _resolve (es-module-shims.js:397:71)
    at es-module-shims.js:825:32
    at Array.map (<anonymous>)
    at es-module-shims.js:821:45

Changing the script type to “module”, and I see that React can be resolved from the imported module (./jsx-app.js):

<script type="module">
      import app from './jsx-app.js'
      console.log(app)
</script>

Please let me know if this issue makes sense - I was expecting to be able to resolve specifiers from the scripts imported via type “module-shim”

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Comments: 24 (7 by maintainers)

Most upvoted comments

load.r is a blank string load.r === '' // true

However I can fix the issue by changing the fetch hook:

async fetch(url, options) {
  const res = await fetch(url, options)
  if (!res.ok) return res
  const source = await res.text()
  const transformed = url.includes('http://localhost') ? await compile(url, source) : source
  return new Response(new Blob([transformed], { type: 'application/javascript' }))
}

Looking at the docs I see that I should return the res, not the res text if I want to escape this hook. This works:

async fetch(url, options) {
  const res = await fetch(url, options)
  if (!res.ok) return res
  if (url.includes('http://localhost')) {
    const source = await res.text()
    const transformed = await compile(url, source)
    return new Response(new Blob([transformed], { type: 'application/javascript' }))
  }
  return res
}