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

monorepo compatibility #2973

Closed
martaver opened this issue Dec 2, 2021 · 10 comments
Closed

monorepo compatibility #2973

martaver opened this issue Dec 2, 2021 · 10 comments

Comments

@martaver
Copy link

martaver commented Dec 2, 2021

Describe the problem

Monorepos are becoming more common as more effort is invested into improved tooling. E.g. nx and bazel.

For the purposes of this feature request I'm excluding monorepo set ups such as yarn workspaces, lerna and pnpm that assume each 'package' has its own package.json and node_modules dir (even if its linked). I'm referring to monorepos that don't necessarily preserve the canonical structure of an app with a package.json at its source root.

The requirements for getting tools to work with monorepos means potentially supporting multiple apps that might live under the same source root and share the same node_modules.

The multiple app paradigm basically means that svelte_kit should support:

  • passing an arbitrary source root to build (at a path underneath package.json)
  • passing an arbitrary path for outputs (at a destination even outside source root)
  • ensuring that build/serve of different apps being served simultaneously are isolated under node_modules/.vite

bazel specifically, would require args like source_root_path and output_path to be able to be passed to svelte_kit binary as command arguments.

Vite already supports this kind of set up, they demonstrate ways to run multiple apps under a single vite configuration here: https://vitejs.dev/guide/build.html#multi-page-app and tout being monorepo friendly.

Also vite is already friendly towards dependencies located in the same repo: https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies

It should be possible to host multiple apps under a single vite configuration. Why not the same for svelte-kit?

Describe the proposed solution

In theory, Vite already has all the tools needed to be monorepo friendly. It's just a matter of allowing svelte_kit to be run the same way.

Already, running: node ../../node_modules/@sveltejs/kit/svelte-kit.js dev from a nested kind of works... (It'll error up until you refresh the browser, and then won't serve some routes properly).

Sveltekit could surface vite features like:

  • passing root from command args, or perhaps a path to a svelte.config.js, or...
  • specifying multiple *.html roots/apps in a single svelte.config.js file.
  • specifying arbitrary output paths for adapters
  • specifying vite cache path (or otherwise isolating caches of different apps)

Seems... possible.... but here be dragons...?

Alternatives considered

Git submodules

...j/k

Importance

would make my life easier

Additional Information

I think spending a little amount of time on this now will allow for early adoption for tools like nx and bazel.

@davemaul
Copy link

davemaul commented Dec 4, 2021

This would be awesome as SvelteKit currently seems not to support this kind of setup. In the mean time, do you have any workaround on your machine you'd like to share? 🙃

@martaver
Copy link
Author

martaver commented Dec 4, 2021

I'm afraid I don't have anything useful to share at the moment... the svelte-kit cli seems quite married to the idea that svelte.config.js will exist next to package.json and node_modules.

As soon as the source files and svelte.config.js are nested, svelte-kit complains that it can't find svelte.config.js.

I could put svelte.config.js in the root of the monorepo, and point everything to the right paths, but then that's still only allowing for a single app. Also there's the whole 'svelte-kit needs type: 'module' in package.json thing. I can't set my whole monorepo to type: "module" from the root package.json... but svelte-kit doesn't pick up the svelte.config if I set its extension to .mjs.

I was thinking maybe a single svelte.config.js in the root of the repo, and then passing a reference to the subdir of the app using args and process.argv.

In svelte.config.js I can prefix all files properties with the subpath of the app, but sveltekit won't allow the vite config's base or root properties to be set, and it still sets them expecting source files at <package_json_root>/src.

The result is that vite's serving allow list looks for src in the repo root, which is incorrect, and refuses to serve assets like app.css. Also, requests for other chunks get 403.

This whole thing would be a whole lot easier if there was just a single property that allowed the source_root path to be set, or if svelte-kit could be run with a --config <path to svelte.config.js> option.

@martaver
Copy link
Author

martaver commented Dec 4, 2021

Actually, using the single svelte.config.js approach (with my monorepo's package.json set to type: "module") the following configuration seems to work:

import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';

const dir = process.argv[process.argv.length-1];

// const dir = 'apps/sveltekit-www';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://github.com/sveltejs/svelte-preprocess
	// for more information about preprocessors
	preprocess: preprocess(),		

	kit: {
		adapter: adapter({  }),		

		// hydrate the <div id="svelte"> element in src/app.html
		target: '#svelte',
		appDir: dir,
		files: {
			template: `${dir}/src/app.html`,
			routes: `${dir}/src/routes`,
			assets: `${dir}/static`,
			lib: `${dir}/src/lib`,
			serviceWorker: `${dir}/src/service-worker.ts`,
			hooks: `${dir}/src/hooks.ts`
		},
		vite: {
			cacheDir: `node_modules/.vite/${dir}`,
			server: {
				fs: {
					allow: [
						dir
					]
				}
			}
		}
	},
};

export default config;

This allows for a nested sveltekit project to be targeted from command line args, like:
yarn svelte-kit dev path/to/app

Probably breaks a few other things, but seems to work for now.

I haven't found a way to change the location of the .svelte-kit cache dir, so running dev on multiple svelte-kit instances at the same time will probably overwrite and cause conflicts with this set up.

@davemaul
Copy link

davemaul commented Dec 4, 2021

Thank you for your effort! I'll see if I give it a try. For now it's just unsatisfactory to work with SvelteKit in a monorepo setup.

@martaver
Copy link
Author

martaver commented Dec 5, 2021

So, the above config shows that svelte-kit cli can actually be run against source files in a subdir with no (apparent) problems. I can even run storybook against it and debug the app with source maps.

The ideal solution would allow for individual apps to each have their own svelte.config.js in case they need tweaking. Apps could always inherit settings from a base config themselves.

To get to this point, we would need to allow svelte-kit cli to:

  • accept a path to svelte.config.js as arg from command line, and update config files paths accordingly.
  • accept output path for adapter
  • isolate caches in .svelte-kit and node_modules/.vite dirs by pre/suffixing them with subdir path
  • ensure vite dev server has app’s source root added to server.fs.allow in its config.

Also, the need to put type: “module” messes with other non-esm code. Not sure how best to isolate the sveltekit app in a monorepo where the rest is all commonjs. Would allowing svelte.config.js be defined as svelte.config.mjs work?

@Tam2
Copy link

Tam2 commented Dec 17, 2021

@martaver are you running a monorepo via Nx? I'm using Nx and have tried to create a shared component library but getting all sorts of weird bugs trying to run in a monorepo

@jtlapp
Copy link

jtlapp commented Apr 7, 2022

I'm also having trouble running svelte-kit in a (pnpm) monorepo. I get these errors for some but not all components:

Sourcemap for "/Users/joe/repos/cavesite-new/packages/frontend/src/common/VariableFlash.svelte" points to missing source files
Sourcemap for "/Users/joe/repos/cavesite-new/packages/frontend/src/components/HeaderBar.svelte" points to missing source files
Sourcemap for "/Users/joe/repos/cavesite-new/packages/frontend/src/common/Notice.svelte" points to missing source files
Sourcemap for "/Users/joe/repos/cavesite-new/packages/frontend/src/dialogs/LoginDialog.svelte" points to missing source files
Sourcemap for "/Users/joe/repos/cavesite-new/packages/frontend/src/components/RouteTab.svelte" points to missing source files

Googling around tells me to downgrade vite, but I don't know how to do that without downgrading svelte-kit. A svelte-kit user also suggested downgrading vite in a discussion I opened.

@Rich-Harris
Copy link
Member

Rich-Harris commented Apr 24, 2022

Since this issue was raised, we added outDir, which solves the shared cache thing. We could add a --config option, though it adds some complexity — are things like config.kit.files.lib resolved against dirname(config_file) or process.cwd()?, etc — so I'd prefer it if we were able to avoid that.

You could always do this sort of thing:

import config from '../../svelte.config.mjs';
export default config;

(This makes it easier to have package/app-level overrides, as well.)

Does that suffice?

@Rich-Harris
Copy link
Member

Going to close this as I believe the issue is now solved

@cristipp
Copy link

cristipp commented Feb 3, 2024

New to vite & sveltekit. I hit this issue while configuring an nx monorepo. Neither @martaver nor @Rich-Harris workarounds worked for me. What works is to start the dev server from the app dir (cd apps/vqapp && nx run vqapp:serve). I had to also modify vite.config.js to allow serving @fs files in non strict mode. Hope this helps.

export default defineConfig({
   server: {
    port: 4200,
    host: 'localhost',
    fs: {
      strict: false
    }
  },
})

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

6 participants