wmr
wmr copied to clipboard
Duplicate preact-iso entries
Reported via slack:
When I import useLocation from preact-iso directly and use it, it always gives an empty object {}. But when imported from preact-iso/router, it works perfectly.
Looks like the module is loaded twice.
with dev server, or prerender build? i’ve had occasional issues with the dev server / prefresh (notably with aliased imports, or resolver plugins) but the prerender build usually works fine.
There are two levels of fix here: the easy quick fix is to remove (and stop recommending usage of) the specific entry modules from preact-iso (so never import preact-iso/router). The longer-term fix is that, when we're compiling an npm module in WMR, compilation should never inline files that can be accessed via "exports" - effectively, any file addressable via a package's export map must be marked as external to all other files in that package.
Mhmm, I experience no problems at all using imports from preact-iso/*, e.g.:
import lazy, { ErrorBoundary } from 'preact-iso/lazy';import { useLocation, LocationProvider, Route, Router, LocationHook, RoutableProps } from 'preact-iso/router';import prerender, { PrerenderOptions } from 'preact-iso/prerender';import hydrate from 'preact-iso/hydrate';
My package.json includes "preact-iso": "^2.0.0" in dependencies.
In my WMR experience using an NPM package dependency which contains an export map, it is critical that if / when a JS file within that package imports another "local" JS file (from the same package), the import MUST be done via the "absolute" export map path instead of the file's relative path (otherwise: duplicate JS load in WMR dev server => weird errors at runtime, particularly with modules that hoist some internal state at the module root).
So my guess is that the developer who reported this bug also imports from index (which itself imports via relative paths instead of absolute export-mapped ones):
https://github.com/preactjs/wmr/blob/a46fcce45f0b532bff02022d86144c2c5c7a996f/packages/preact-iso/index.js#L1-L3
...which obviously conflicts with the export map:
https://github.com/preactjs/wmr/blob/a46fcce45f0b532bff02022d86144c2c5c7a996f/packages/preact-iso/package.json#L13-L19
@danielweck Right - the issue here is still present even when using the exports correctly:
import lazy, { ErrorBoundary } from 'preact-iso/lazy'; // imports a bundled copy of `preact-iso/lazy`
import { hydrate } from 'preact-iso'; // imports a bundled copy of `preact-iso`, which contains a second copy of lazy
The solution for this is basically that we need to treat any relative path imports within export-map-enabled packages as export mapped ones, including specifiers that reference files that are the right-hand-side of the export map. With that fixed, import 'preact-iso' would return this module:
export { Router, LocationProvider, useLocation, Route } from '/@npm/preact-iso/router';
export { default as lazy, ErrorBoundary } from '/@npm/preact-iso/lazy';
export { default as hydrate } from '/@npm/preact-iso/hydrate';