Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: top-level await does not work with libraries when enabled (and is not supported out of the box) #1614

Open
2 tasks done
trusktr opened this issue Aug 26, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@trusktr
Copy link

trusktr commented Aug 26, 2024

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Current behavior 😯

Use npm create solid to make a basic app, then put a top-level await something in a module, and you'll get an error during npm run build like so:

 ERROR  Transform failed with 1 error:                                                                               10:24:53 AM
/Users/trusktr/src/showcase/.vinxi/build/ssr/ssr.js:1:17460: ERROR: Top-level await is not available in the configured target environment ("es2019")

Expected behavior 🤔

It should just work out of the box. It works in all JS runtimes and browsers out of the box.

Steps to reproduce 🕹

Problem 1:

Steps:

  1. npm create solid
  2. put an await something() at the top level of a module
  3. run npm run build
  4. see error in terminal after loading the app in browser

The error will look something like this:

 ERROR  Transform failed with 1 error:                                                                               10:24:53 AM
/Users/trusktr/src/showcase/.vinxi/build/ssr/ssr.js:1:17460: ERROR: Top-level await is not available in the configured target environment ("es2019")

To fix the problem, the following will not work:

export default defineConfig({
	vite: {
		build: { target: 'esnext' },
	},
})

but one would think that it would, because this is what we see when we look at intellisense:

Screenshot 2024-08-24 at 10 54 43 AM

In the screenshot we can see that the auto-completion in VS Code will give us a strong hint that setting this option will work. But that's not the case (when it comes to application code).

Instead, we must set a different option of the same name at another location, which is not so obvious considering that Vite uses esbuild and one may very well assume the vite esbuild config will do the trick:

export default defineConfig({
	server: {
		esbuild: { options: { target: 'esnext' } },
	},
})

Problem 2:

If you import a library from npm that has top-level await, there's no way to make it work. Setting either of the two options above will not work!

Steps:

  1. npm create solid
  2. npm install yoga-layout
  3. npm run dev
  4. see error in terminal after loading the app in browser

The error will look something like this,

✘ [ERROR] Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)

    node_modules/yoga-layout/dist/src/index.js:13:26:
      13 │ const Yoga = wrapAssembly(await loadYoga());
         ╵                           ~~~~~

8:19:44 PM [vite] error while updating dependencies:
Error: Build failed with 1 error:
node_modules/yoga-layout/dist/src/index.js:13:26: ERROR: Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)
    at failureErrorWithLog (/Users/trusktr/src/showcase/node_modules/vite/node_modules/esbuild/lib/main.js:1472:15)
    at /Users/trusktr/src/showcase/node_modules/vite/node_modules/esbuild/lib/main.js:945:25
    at /Users/trusktr/src/showcase/node_modules/vite/node_modules/esbuild/lib/main.js:1353:9
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

which as you can imagine is frustrating because yoga-layout is a 3rd-party library, and the neither of the two target configs is helping.

The error says my target environment is chrome87. Why is that, if I've specified esnext, when is comes to the node_modules dependency?

Context 🔦

All JS runtimes support top-level await natively for a long time now. Solid Start should too!

Your environment 🌎

npmPackages:
❯ npm ls
showcase@ /Users/trusktr/src/showcase
├── @babel/plugin-proposal-decorators@7.24.7
├── @solidjs/router@0.14.3
├── @solidjs/start@1.0.6
├── @types/three@0.167.2
├── lume@0.3.0-alpha.43
├── prettier@3.3.3
├── solid-js@1.8.21
├── vinxi@0.4.1
└── yoga-layout@3.1.0
@trusktr trusktr added the bug Something isn't working label Aug 26, 2024
@trusktr trusktr changed the title [Bug?]: top-level await support is not supported out of the box, does not work with libraries [Bug?]: top-level await is not supported out of the box, does not work with libraries Aug 26, 2024
@trusktr trusktr changed the title [Bug?]: top-level await is not supported out of the box, does not work with libraries [Bug?]: top-level await is not supported out of the box, and does not work with libraries when enabled Aug 26, 2024
@trusktr trusktr changed the title [Bug?]: top-level await is not supported out of the box, and does not work with libraries when enabled [Bug]: top-level await is not supported out of the box, and does not work with libraries when enabled Aug 26, 2024
@trusktr
Copy link
Author

trusktr commented Aug 26, 2024

Reproduction: https://github.com/lume/showcase/tree/solid-start-issue-1614

git clone git@github.com:lume/showcase.git
cd showcase
git checkout solid-start-issue-1614
npm ci
npm run dev # see error in terminal after loading the app in browser

@trusktr trusktr changed the title [Bug]: top-level await is not supported out of the box, and does not work with libraries when enabled [Bug]: top-level await does not work with libraries when enabled (and is not supported out of the box) Aug 26, 2024
@trusktr
Copy link
Author

trusktr commented Aug 26, 2024

Workaround:

A workaround is to do a native import() inside eval() (to avoid the compiler handling it):

// If using typescript, type-only `import` will be fine
import type {Node} from 'yoga-layout'

function getYoga() {
	const [yoga, setYoga] = createSignal<typeof import('yoga-layout')>()
	const promise = eval("import('https://unpkg.com/yoga-layout@3.1.0/dist/src/index.js')")
	promise.then(setYoga)
	return yoga
}

// ...

			const yoga = getYoga()

			createEffect(() => {
				const yogaModule = yoga()
				if (!yogaModule) return
				const {default: Yoga, Direction, FlexDirection, Gutter} = yogaModule

				// ... use yoga as before ...
			})

@trusktr
Copy link
Author

trusktr commented Aug 26, 2024

This seems somehow related to the issue of effects not running. https://discord.com/channels/722131463138705510/1275456175462420614

In the above case, I was able to cause effects not to run due to the presence of await import() inside of components, and was able to workaround by setting ssr:false in app.config (only for dev mode, prod mode is not working at all), although maybe this is just a secondary effect of the real issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants
@trusktr and others