You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When marking a package as an SSR external, it should also mark any sub-entry points of the same module as external.
While it's not explicitly documented, this is what I believe the intended behaviour is from reading prior issues and the source code.
// should be externalimportlodashfrom'lodash';// should also be externalimportomitfrom'lodash/omit';
Unfortunately, this feature (sub-entry externals) doesn't work when the package being marked as external isn't a top-level package inside node_modules. Package managers that use hoisting likely get around this issue, however pnpm and other package manages that don't hoist seem to break this feature.
In practice, this means that the behaviour of ssr.external is different depending on whether packages are top-level dependencies or not. Due to the way ssr.noExternal works, using ssr.external on nested deps is essential in more complex scenarios.
After debugging the source code, this issue seems to occur because import specifiers that exactly match the external are treated differently to package matches. Package matches have to go through a node resolve check in order to be externalised, however the resolve check runs from the project root, therefore always failing for non top-level packages.
Excerpt from the source code:
// copied from https://github.com/vitejs/vite/blob/9ac5075825212e5f4f3b262225ff4a3e46b8e8d1/packages/vite/src/node/ssr/ssrExternal.ts#L158// Returns true if it is configured as external, false if it is filtered// by noExternal and undefined if it isn't affected by the explicit configreturn(id: string)=>{const{ ssr }=configif(ssr){if(// If this id is defined as external, force it as external// Note that individual package entries are allowed in ssr.externalssr.external?.includes(id)){returntrue// <-- straight external match doesn't require more validation}constpkgName=getNpmPackageName(id)if(!pkgName){returnisExternalizable(id)}if(// A package name in ssr.external externalizes every// externalizable package entryssr.external?.includes(pkgName)){returnisExternalizable(id,true)// <-- package entry external match requires resolve check for some reason?}if(typeofnoExternal==='boolean'){return!noExternal}if(noExternalFilter&&!noExternalFilter(pkgName)){returnfalse}}returnisExternalizable(id)}
I have validated that changing the package entry check above to immediately return true rather than going through isExternalizable fixes this issue. Unless this breaks other Vite behaviour, I'd suggest that would be the easiest fix and I'd be happy to submit a PR doing this.
Alternatively, the node resolve algorithm inside isExternalizable could resolve from the dependent package location rather than the project root.
I think this issue is related to but not the same as #9710.
> ssr-external-repro@0.0.0 test /Users/mjones/projects/ssr-external-repro
> node test
node:internal/process/esm_loader:94
internalBinding('errors').triggerUncaughtException(
^
ReferenceError: require is not defined
at eval (/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/mapValues.js:3:36)
at instantiateModule (file:///Users/mjones/projects/ssr-external-repro/node_modules/.pnpm/vite@3.0.9/node_modules/vite/dist/node/chunks/dep-0fc8e132.js:50548:15)
Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
Describe the bug
When marking a package as an SSR external, it should also mark any sub-entry points of the same module as external.
While it's not explicitly documented, this is what I believe the intended behaviour is from reading prior issues and the source code.
e.g.
Unfortunately, this feature (sub-entry externals) doesn't work when the package being marked as external isn't a top-level package inside
node_modules
. Package managers that use hoisting likely get around this issue, howeverpnpm
and other package manages that don't hoist seem to break this feature.In practice, this means that the behaviour of
ssr.external
is different depending on whether packages are top-level dependencies or not. Due to the wayssr.noExternal
works, usingssr.external
on nested deps is essential in more complex scenarios.After debugging the source code, this issue seems to occur because import specifiers that exactly match the external are treated differently to package matches. Package matches have to go through a node resolve check in order to be externalised, however the resolve check runs from the project root, therefore always failing for non top-level packages.
Excerpt from the source code:
I have validated that changing the package entry check above to immediately return
true
rather than going throughisExternalizable
fixes this issue. Unless this breaks other Vite behaviour, I'd suggest that would be the easiest fix and I'd be happy to submit a PR doing this.Alternatively, the node resolve algorithm inside
isExternalizable
could resolve from the dependent package location rather than the project root.I think this issue is related to but not the same as #9710.
Reproduction
https://github.com/mattcompiles/vite-ssr-external-repro
System Info
Used Package Manager
pnpm
Logs
Click to expand!
Validations
The text was updated successfully, but these errors were encountered: