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

resolve svelte to a different module in SSR mode #6372

Closed
Rich-Harris opened this issue May 29, 2021 · 3 comments · Fixed by #6416
Closed

resolve svelte to a different module in SSR mode #6372

Rich-Harris opened this issue May 29, 2021 · 3 comments · Fixed by #6416

Comments

@Rich-Harris
Copy link
Member

Is your feature request related to a problem? Please describe.
In SSR mode, onMount, beforeUpdate and afterUpdate don't do anything. But build tools can't know that because they're not no-ops in the () => {} sense — the callbacks get pushed to an array which is then discarded, which isn't something that can be optimised away with static analysis — and as a result the code remains in the generated bundle.

If onMount etc were instead no-ops, the code could be removed, at least by tools like Rollup and Terser (the same isn't true for esbuild, sadly, but maybe one day).

This won't prevent Rollup from attempting to bundle (or create chunks for) dynamic imports inside those callbacks...

onMount(async () => {
  const mod = await import('./client-only-module.js');
  // client-only-module will appear in the SSR bundle even if `onMount` is correctly
  // treated as a no-op. this feels like something that could change though
});

...but it's nonetheless a significant improvement on the status quo.

Describe the solution you'd like
The solution is a two-parter:

  1. Expose an equivalent module to svelte (e.g. svelte/ssr) that re-exports most stuff from svelte, but replaces the relevant functions with no-ops
  2. Update Svelte bundler plugins like rollup-plugin-svelte and @sveltejs/vite-plugin-svelte to intercept imports to svelte and replace them with svelte/ssr. (This needs to happen for all modules in the graph, not just .svelte files.)

Describe alternatives you've considered
One alternative we discussed is detecting calls to onMount and similar functions, and simply removing them from the generated code. I'm opposed to this for Zalgo reasons: since this would only apply to onMount calls (and only inside components, since Svelte plugins have no authority to mess around with non-components, especially since they may not have been transformed to standard JS by the time the plugin sees them), it would fail to remove code like the following:

// lifecycle.js
import { onMount } from 'svelte';

export function useSomeLibrary(fn) {
  onMount(() => {
    const mod = await import('some-library');
    fn(mod);
  });
}
<!-- App.svelte -->
<script>
  import { useSomeLibrary } from './lifecycle.js';

  let div;

  useSomeLibrary(lib => {
    lib.init(div);
  });
</script>

<div bind:this={div}></div>

If that code is going to fail (because a build tool won't allow some-library to be bundled for the server, for example), it's better that it fails the same way whether you write it inside onMount in a component directly, or in the form shown above. Someone writing the onMount version would be horribly confused if they refactored it into useSomeLibrary to use in multiple components. Better to have more frequent failures than less frequent but unpredictable ones that cause people to lose faith in their understanding of the system as a whole.

How important is this feature to you?
It's come up in the context of SvelteKit, where building fails in some cases because of this issue.

@benmccann
Copy link
Member

This won't prevent Rollup from attempting to bundle (or create chunks for) dynamic imports inside those callbacks...

I actually think it might be sufficient. Example on Rollup REPL

@benmccann
Copy link
Member

@tanhauhau is there a reason you reopened this issue?

@dummdidumm
Copy link
Member

Seems there wasn't, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants