prefresh/vite: runtimeCode is not defined
cyyynthia opened this issue · 5 comments
While working on a project of mine bundled with Vite using the preact preset, I've encountered strange errors which seemed to be from prefresh/vite.
Upon closer inspection of the error message and the lib's code, I've found that in the vite/src/index.js file, line 24 there is indeed a reference to a runtimeCode
variable, which indeed is not define anywhere, leading to an unpleasant error :(
Oh waw, that is completely my mistake 😅 fix incoming!
Updated to 2.2.0, it seems like the issue is gone for npm (and probably yarn) users, but a it seems to create an issue with pnpm now, although minor (at least I think). pnpm has a strict policy on imports and projects can only import packages that are directly mentioned in the package.json. Indirect dependencies are not accessible.
Because the import is injected into the main script, vite attemps to find prefresh/vite, which is not a direct dependency of mine and therefore fails to import (it's a dependency of preact/preset-vite). A quick fix is to add prefresh/vite to my package.json, but it then defeats the purpose of the preset which is supposed to handle everything for you in my opinion.
Hmm, yes this issue is solved when you're using @prefresh/vite
directly through https://github.com/JoviDeCroock/prefresh/blob/main/packages/vite/src/runtime.js, no clue how we'd do something like that for the preset though
no clue how we'd do something like that for the preset though
After looking into it a bit today, it seems like it will be hard to fix (at least with the current state of node & esm). I've managed to get some progress on getting it to load when using the preset and pnpm (I'm mentioning the preset specifically since it applies to my case, but the issue will happen in any scenario where prefresh isn't a direct dependency of a project).
The "fix" is relatively simple as it consists of using require.resolve
to resolve the fullpath of the lib within the transform logic, passing this fullpath to Rollup's resolve
method, and use the result as the thing we're importing.
Better than words, some code:
// file: /packages/vite/src/index.js
// note: because Rollup's resolve method is async, the transform method must also become async
const prefreshRuntime = await this.resolve(require.resolve('@prefresh/vite/runtime'))
const prefreshUtils = await this.resolve(require.resolve('@prefresh/vite/utils'))
const prelude = `
${'import'} ${JSON.stringify(prefreshRuntime.id)};
${'import'} { flushUpdates } from ${JSON.stringify(prefreshUtils.id)};
...
`
While it managed to get Vite to successfully lookup the file, this causes 2 problems:
require.resolve
does not work in es modules, andimport.meta.resolve
is still experimental- This causes the
.js
file to be loaded instead of the.mjs
one, which causes some errors as Vite expects an es module (Uncaught SyntaxError: The requested module '[...]/@prefresh/vite/utils/index.js' does not provide an export named 'flushUpdates'
)
For now, other than telling pnpm users to install @prefresh/vite
along with the preset, I unfortunately don't think there's a magic solution yet :(
Thank you so much for looking into this @cyyynthia and for the in-depth explanation. This is much appreciated