sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.56k stars 1.91k forks source link

Expose `manifest_data` to be extended by other vite plugins #9383

Closed gu-stav closed 1 year ago

gu-stav commented 1 year ago

Describe the problem

I'd like to register new routes in svelte-kit, which come as part of a installed npm dependency. My current idea is to write a vite-plugin which resolves the routes folder of that dependency (inside node_modules) and extends the "router" in vite. For this I'd like to use the configResolved() hook (or any other).

Right now manifest_data is a private variable which is not exposed to other vite plugins. I think therefore there is no way that I could e.g. use the sync.all() / create_manifest_data() utility to re-create the routes/nodes as part of a different plugin.

Describe the proposed solution

I am by no means an expert in vite/ rollup, but I can see two ways:

  1. Expose the manifest as part of new_config:
new_config.define = {
        // ...
    __SVELTEKIT_EMBEDDED__: kit.embedded ? 'true' : 'false',
       __SVELTEKIT_MANIFEST: manifest_data
};
  1. Use a rollup API

I think this would give other plugins a way to access to the manifest:

function plugin() {
    return {
        name: 'test',
        buildStart() {
            // trigger loading a module. We could also pass an initial
            // "meta" object here, but it would be ignored if the module
            // was already loaded via other means
            this.load({ id: 'my-id' });
            // the module info is now available, we do not need to await
            // this.load
            const meta = this.getModuleInfo('my-id').meta;
            // we can also modify meta manually now
            meta.test = { some: 'data' };
        }
    };
}

All places accessing manifest_data would need to be updated to read from the stored option.

Alternatives considered

Importance

i cannot use SvelteKit without it

Additional Information

I am open to any other suggestions and hope this is concrete enough to be actionable.

Would you accept a PR for that or do you want to keep the manifest private?

Rich-Harris commented 1 year ago

We definitely don't want to expose the manifest data publicly. Can you describe your use case in more concrete terms?

gu-stav commented 1 year ago

Thanks for the quick reply, Rich. I suspected you'd say that and I understand your position, because it would make it very hard to change the fundamentals of svelte-kit, if you have to assume users are changing the manifest.

My use-case: I'm exploring how to use svelte-kit as an engine for a CMS that is installed by users through npm (not run as SAAS website). I've explored several directions how to make this possible but couldn't make any of them work:

1) Using a catch-all route

This is what e.g. https://outstatic.com/docs/getting-started does with next.js:

// /src/routes/outstatic/[[...ost]].svelte

import { CMS, load } from 'cms';

<CMS {...$$props} />

export const load;

This approach works well from a users perspective, because all they'd have to do is creating the route, import the component + a load function and extend e.g. the server hooks. It is also extensible.

Where this fails however: because everything needs to happen in one load function / hook I'd basically loose all the niceties svelte-brings in terms of data fetching. It is not easy to use form actions internally and code-splitting of the CMS component is hard of not impossible.

2) Using npm sub-child process

Users install cms as a dependency, which has a dependency on svelte-kit. When running a custom command (e.g. cms dev) a script takes care to run vite dev from the svelte-kit npm package. The svelte-config output and env paths would then be set to the original process.cwd() path.

This is obviously not a good approach for many reasons.

3) Programmatically run vite build, vite dev ...

Users install cms as a dependency, which has a dependency on svelte-kit. When running a custom command (e.g. cms dev) a script takes care to run vite.build() on the cms-dependency path taking the vite.config and svelte.config into account.

This doesn't work, because vite can not resolve all dependencies, because they are outside of the directory. Also I think it would be hard to re-create the dev-server.

4) Extend routes through a vite-plugin (what the original issues was about)

My latest idea was to hook into the vite build process and load routes from another npm dependency. In this case the integration into kit would be to add a new cms dependency and register a new vite plugin that resolves new routes from node_modules/cms/src/routes before building and merge them with the existing ones in ./src/routes.

Currently this approach sounds most appealing to me, but without access to the manifest I think it would be hard because I'd have to re-create big parts of the svelte-kit vite plugins.