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

fix: externalize transitive cjs only deps during dev ssr #289

Merged
merged 7 commits into from Mar 16, 2022

Conversation

dominikg
Copy link
Member

see #281

i'm still getting an error though when adding bytemd to a sveltekit project

this is rendered in the html output of localhost:3000 after a brief flash of an unstyled editor.

500
The requested module '/node_modules/.pnpm/codemirror-ssr@0.0.6/node_modules/codemirror-ssr/mode/gfm/gfm.js?v=9e01fcfd' does not provide an export named 'default'
SyntaxError: The requested module '/node_modules/.pnpm/codemirror-ssr@0.0.6/node_modules/codemirror-ssr/mode/gfm/gfm.js?v=9e01fcfd' does not provide an export named 'default'

@benmccann
Copy link
Member

I was thinking that this is probably something that should be fixed purely in Vite. Vite is already including the packages in externals, but it's just that they're listed as parent > child so either we should make it understand that syntax or stop generating that syntax in that code path

@dominikg
Copy link
Member Author

dominikg commented Mar 1, 2022

totally fine with fixing it in vite 👍 anyone got an idea why it's failing for codemirror-ssr though?

@benmccann
Copy link
Member

I didn't look at that one yet, but codemirror is probably the hardest library I've ever encountered to get working in Vite, so I'm not terribly surprised or worried about that one. I shared with the bytemd how we got the main codemirror package working for svelte.dev

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ben made vitejs/vite#7154 which should also fix this, but I think we should also merge this one as when someone turns on prebundleSvelteLibraries, they would hit this issue too.

Comment on lines 214 to 231
if (configEnv.command === 'serve') {
// during dev, we have to externalize transitive cjs only dependencies, see https://github.com/sveltejs/vite-plugin-svelte/issues/281
const optimizedTransitiveDeps = extraViteConfig.optimizeDeps?.include
?.filter((x) => x.includes('>'))
.map((x) => x.substring(x.lastIndexOf('>') + 1).trim());
if (optimizedTransitiveDeps?.length) {
// @ts-expect-error ssr still flagge in vite
if (!extraViteConfig.ssr.external) {
// @ts-expect-error ssr still flagge in vite
extraViteConfig.ssr.external = [];
}
// @ts-expect-error ssr still flagge in vite
extraViteConfig.ssr.external.push(
// @ts-expect-error ssr still flagge in vite
...optimizedTransitiveDeps.filter((x) => !config.ssr?.noExternal?.includes(x))
);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could move this into buildSSROptionsForSvelte() and build the list of externals from scratch, since if prebundleSvelteLibraries is turned off, there won't be parent > child syntax to handle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved it and cleaned up. not sure i follow the prebundleSvelteLibraries problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If prebundleSvelteLibraries is set to true, buildOptimizeDepsForSvelte() will early return here:

if (options.experimental.prebundleSvelteLibraries) {
return {
include,
exclude,
esbuildOptions: {
plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
}
};
}

Skipping the below code that handles adding parent > child to optimizeDeps.include so there won't be any > syntax to handle in configuring ssr.external later on, which brings up the initial issue where nested deps (e.g. child) weren't added to ssr.external when it should.

To showcase this visually with the current PR's changes:

If prebundleSvelteLibraries: false (default)

  • optimizeDeps.include: ["svelte-dep > cjs-dep"]
  • optimizeDeps.exclude: ["svelte-dep"]
  • ssr.noExternal: ["svelte-dep"]
  • ssr.external: ["cjs-dep"]

If prebundleSvelteLibraries: true

  • optimizeDeps.include: []
  • optimizeDeps.exclude: []
  • ssr.noExternal: ["svelte-dep"]
  • ssr.external: [] <- should have cjs-dep

So we have to reconstruct the ssr.external without relying on optimizeDeps.include 😵

@benmccann
Copy link
Member

I wonder if we shouldn't focus on getting Vite to externalize everything by default. I took a stab at that earlier (vitejs/vite#6698), but one of the tests was failing and I didn't have time to investigate.

@dominikg
Copy link
Member Author

is externalizing everything ok? if that was the case, why is vite doing this dance with noExternal in the first place?

@benmccann
Copy link
Member

I believe it should be okay. At this point, I think the dance really isn't necessary and is just legacy that no one's taken the time to cleanup yet. Pretty much everything is already externalized and I'm not sure it would have any user visible changes. I think it's really just a single test that needs to be removed or updated. The failing test is optimize-missing-deps, which I'm really confused about because I'm not sure how anything can happen one way or another to a dependency that's missing. I don't really understand what it's supposed to be testing. At most I think we'd just need to special case missing dependencies and everything else can be externalized

@bluwy
Copy link
Member

bluwy commented Mar 15, 2022

I think it would be great if we can find a way to externalize everything by default. I checked the failing test and it seems like Jest is interfering it with it's own transformation. Perhaps the CJS/ESM check Vite has avoided this specific edge case, but it looks like a Jest issue to me if things are working locally without Jest. I haven't looked too deep yet.

@benmccann
Copy link
Member

Ah, if Jest was doing a transform that would explain a lot because it looked like I was getting code that was different than what was on disk. Another thing I noticed is that one of the package.json files in that test has ESM code, but is missing "type": "module"

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dominikg dominikg merged commit 3d22f89 into main Mar 16, 2022
@dominikg dominikg deleted the fix/externalize-cjs-ssr branch March 16, 2022 14:28
@github-actions github-actions bot mentioned this pull request Mar 16, 2022
...new Set(svelteDeps.flatMap((dep) => Object.keys(dep.pkg.dependencies || {})))
];
// @ts-expect-error ssr still flagged in vite
ssr.external = transitiveDepsOfSvelteLibs;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't suggesting to change anything here, but rather in Vite. I'm not entirely sure this is safe. I hope it is, but I can't figure out how to externalize all deps and get Vite's optimize-missing-deps test to pass, so there might be a real issue there around deps that haven't been optimized yet

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be safe to fix this here so it works in Vite 2.8 at the meantime. Having this handled in Vite 2.9 ootb would be great though so perhaps later on we can remove this.

@github-actions github-actions bot mentioned this pull request Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants