Skip to content

Expose registered components during SSR compilation #4854

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

Closed
AlbertMarashi opened this issue May 18, 2020 · 6 comments
Closed

Expose registered components during SSR compilation #4854

AlbertMarashi opened this issue May 18, 2020 · 6 comments

Comments

@AlbertMarashi
Copy link

AlbertMarashi commented May 18, 2020

Is your feature request related to a problem? Please describe.
@Rich-Harris https://twitter.com/PromatiaGov/status/1262183956004220928

Svelte needs to expose which components the SSR compiler has come across during SSR Rendering. This will let the server-side renderer know which components have been registered, so the page can preload the necessary components on the client-side;

eg:

const { html, css, head, registeredComponents } = App.render()

Registered components may just be a new Set() with the unique ID of the component (perhaps a file path) - vue-loader uses some sort of module identifier that is the same across client & server-side I think.

This can allow Svelte routers and code-split svelte apps to enable faster loading speeds, as the necessary client-side scripts can be preloaded. The svelte-loader and rollup loader can make use of these, by matching the module's ID to a client-manifest. This would mean that svelte-loader would also need to be updated I believe.

vue-loader exposes a _registeredComponents, which is used by the server-side renderer and matched with the client manifest to find which async files should be preloaded on the website:

console.log(context._registeredComponents) // prints below

image

client-manifest
The number value of each module ID links to a specific output script
image

client manifest generator plugin
image

Not sure what would be the best way to go across this

Describe the solution you'd like
Not sure

Describe alternatives you've considered
Have tried to do route-level matching, but it's hard.

How important is this feature to you?
Pretty important feature for SSR, could be used by Sapper as well.

@AlbertMarashi
Copy link
Author

AlbertMarashi commented May 18, 2020

Looks like they are just hashing the file path. I'll have a look as to how this may be implemented in svelte

@AlbertMarashi
Copy link
Author

Using https://www.npmjs.com/package/hash-sum

They are using the loader/compiler request URL instead of the filepath

const hash = require('hash-sum')

module.exports = function(source, map) { //svelte-loader
   const { request } = this
   const id = hash(request) // feed this to compiler options in SSR mode, then compiler can know the client hash (as they should be identical), and match to client manifest
}

@AlbertMarashi
Copy link
Author

AlbertMarashi commented May 18, 2020

PR would solve this issue, and enable the feature, but it must be integrated to svelte-loader too
EDIT: PR solves the issue & does not need to be implemented in svelte-loader

@stale
Copy link

stale bot commented Dec 24, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale-bot label Dec 24, 2021
@soerenmeier
Copy link

+1 for adding this. In the vite docs something like this get's described.
Maybe instead of adding it to svelte it could be added to the svelte vite plugin.

For the meantime I'm using the following Plugin but that is not a fix
export function usedSsrComponents(dirname) {
    return {
        transform(code, id, options) {
            if (!options?.ssr || !id.endsWith('.svelte'))
                return;

            const file = relative(dirname, id);

            const initFnSign = 'create_ssr_component(($$result, $$props, $$bindings, slots) => {';

            let idx = code.indexOf(initFnSign);
            if (idx < 0)
                return;
            idx += initFnSign.length;

            code = `
import { getContext as __modulesGetContext } from 'svelte';
${ code.substr(0, idx) }
(() => {
const ctx = __modulesGetContext('modules');
if (ctx && ctx instanceof Set) {
    ctx.add('${ file }');
}
})();
${ code.substr(idx) }
`;

            return code;
        }
    };
}

This then matches nicely to the ssr manifest that get's generated by vite.

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

No branches or pull requests

5 participants