Replies: 9 comments 25 replies
-
Very interesting as i never work on such a large project. But sometimes VSCode starts to struggle even on my smaller projects but i assume its just typescript that is the bottleneck here. Having to rebuild everything every time is definately annoying. A more incremental way would help a lot. I've not experienced any performance issues regarding server routes, would love to understand why they are significantly slower in your case (again, my projects do not have that amount of throughput). |
Beta Was this translation helpful? Give feedback.
-
One thing I wish sveltekit did is being able to expose the return type of the response, it would make it easier to connect front/backend. i built svetch.ts but it uses AST Tree for that, it works and does swagger but I can't imagine how much it would take in your kind of project. |
Beta Was this translation helpful? Give feedback.
-
Does anyone have experience with an equivalent sized NextJS, Vue SSR, or Angular SSR project and can share numbers comparing build times and hot reload times? It would be interesting to see if this is even a svelte problem or just a constraint of large javascript projects in general. The build times don't honestly seem that bad for a project of this size. But i could see how the hot reloading and IDE issues would be problems. |
Beta Was this translation helpful? Give feedback.
-
Hi, Paolo here. Thanks for the detailed feedback. I will try to express my thoughts on some of your comments but consider I never worked on such large projects so take what i say with a grain of salt.
Svelte LSP is likely at least partially responsible about this but i'm not sure it's the main culprit. You made a comparison with Go but that's a different language and a different toolchain. Did you have any other experience with other frameworks at the same scale? Would be interesting to see how well Vue, React perform at the same scale. We are also trying to dive into the performance of the language server but as you might imagine is difficult to create a coherent very large project to test it. If you have any suggestions about such large projects possibly open source so that we can test on them that would be sweet. This same answer basically apply to points 2 and 3 too (although the
What kind of customization do you need? And what would be your ideal API for such customizations?
Can you elaborate a bit more about why this is not ideal? It is because you are separating the code for dev and the code for prod? Vite if famous for some small discrepancy between dev and prod and i guess that maybe between
Don't have much to say here...there's probably a bit of overhead because those could be generic endpoints while you can write more performant specific endpoints directly in node but i think this is definitely something we should look into.
Technically you could pre-compile them to JS and mount them. The reason it's not ideal to do so is because the compiled output depends on the version of the compiler. This means that if you compile that library with a compiler that has a bug in it and a future version fixes that bug upgrading to the new version in your project doesn't actually fix the bug for your precompiled component.
I suggest you to take a look at MSW... it's a fantastic mocking suite that allow you to have a service worker for api calls from the browser but also a node server to mock requests on the server side, you can use the same handlers for both and it's very declarative.
Personally i would use a different approach here...there's no reason to mock sveltekit requests....you need to mock the request at the data layer. When sveltekit goes and fetch from your external api/db/whatever that's where you return the mocked data. This way you let sveltekit do his job with that fake data that you provide.
I've encountered this problem myself and i copied the same solution page: async ({ page, javaScriptEnabled, context }, use, testInfo) => {
// automatically wait for kit started event after navigation functions if js is enabled
const page_navigation_functions = ['goto', 'goBack', 'reload'] as const;
page_navigation_functions.forEach((fn) => {
const pageFn = page[fn];
if (!pageFn) {
throw new Error(`function does not exist on page: ${fn}`);
}
// substitute the actual function with a new function that waits
// for the selector that we've set in +layout.svelte
page[fn] = async function (...args: Parameters<typeof pageFn>) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const res = await pageFn.call(page, ...args);
if (
javaScriptEnabled &&
(args[1] as { waitForStarted: boolean })?.waitForStarted !== false
) {
// eslint-disable-next-line playwright/no-wait-for-selector
await page.waitForSelector('body[data-kit-started]', { timeout: 15000 });
}
return res;
};
});
await use(page);
}, and then you just need to add this to your root layout onMount(() => {
document.body.setAttribute('data-kit-started', '');
}); this will make sure that every playwright navigation will wait for svelte to hydrate before start interacting with the page. |
Beta Was this translation helpful? Give feedback.
-
Keep an eye out for Rolldown which will replace Rollup, improving build and dev server speeds (where bundling is concerned). |
Beta Was this translation helpful? Give feedback.
-
6) UI kit Icons
Large icon libraries are pretty common, so this is one I've investigated in the past. The first thing to note is that there are four different ways to build icon libraries that I've seen:
When people run into scaling issues with icons, I've always seen that falling into the last bucket. My first recommendation would be to avoid this structure and go with one of the others. I personally like the CSS approach and avoiding JS altogether
If you have a standalone library, it will generally be pre-bundled by Vite on the first server-startup. There are two ways to export files from a package. You can use what's called an umbrella export where they are all exported from the main entry point or you can have an export per-file. What is very important here is that you never mix-and-match. If you have an umbrella export, then prebundling will be a one-time cost and while you will have to wait a bit (~20-30s perhaps), you shouldn't have to pay that cost when subsequently changing the code, restarting the server, etc. With the direct export a prebundling will happen each time you import a new file from the package, but it should be very short and quick. If you do both, then you will repeatedly pay the larger cost for pre-bundling the whole library everytime you import a new file. For more details about this see: https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies If you must have a |
Beta Was this translation helpful? Give feedback.
-
4) SvelteKit adapters - dev vs prod differencesCan you please expand upon what you were trying to accomplish and what exactly was different in dev vs prod? |
Beta Was this translation helpful? Give feedback.
-
Vercel recently(10/22/24) had a blog post about how they improved build times and developer experience by adopting a microfrontend approach you may find interesting How Vercel adopted microfrontends |
Beta Was this translation helpful? Give feedback.
-
Hmm Interesting, I can say this because I do work as part of a very large project. Yahoo Finance is completely written on Sveltekit now, and we have several hundred pages, I haven't seen any of the scale issues mentioned but we don't use sveltekit for our micro services though. |
Beta Was this translation helpful? Give feedback.
-
Hello, everyone!
I want to share some of the challenges We've faced over the past few years of working with the Svelte/Kit framework, which I think are worth discussing and highlighting to make the future of this framework even better.
First, let me introduce myself. I work as a JavaScript developer at N company. We've been using SvelteKit quite successfully in our work, starting back when it was still in the alpha version. We have around 15+ frontend services built on this framework, a UI kit, micro frontends, and our own application template.
We've also developed our own meta-meta framework around SvelteKit to fine-tune it for production use. We've integrated tracing for microservices, logging, Prometheus for metrics collection, various plugins for handling authorization, automatic generation swagger schemas, and many other useful features.
Next, I'll list the issues we've encountered.
1) IDE
Our IDEs, which we use, have stopped responding efficiently. It takes about a minute for Svelte LSP to initialize. Our laptops are overheating badly. Autocomplete works very slowly or doesn’t work at all. This affects both the autocomplete in component markup, such as props, and in script tags, where autocomplete has become very unresponsive. For some colleagues, Svelte LSP even stops working because it runs out of RAM. This issue affects VS Code, WebStorm, Nvim, and Zed.
Our largest project (in terms of code) has 3,768 Svelte components with 304,411 lines of code and 15,328 TypeScript files with 437,593 lines of code. It might not sound like much compared to the GraphQL service written in Go by a neighboring team, which has 1,714,120 lines of Go code, and everything works as smoothly as it did the first time.
I understand that the issue might not be entirely with Svelte LSP or Svelte itself, but could be rooted elsewhere, such as the fact that the entire JavaScript tooling ecosystem is written in JavaScript and runs on single-threaded Node.js. However, I wanted to highlight that in large projects, the IDE becomes extremely unresponsive, and it would be great if the team supporting the Svelte ecosystem was aware of this.
2) Build speed
Building the application for production takes 10 minutes, and Svelte-check takes an additional 10 minutes. This is quite slow, and it's hard to find a workaround. Neither esbuild, swc, nor rspack currently have good support for Svelte. As projects grow and evolve, this build time is likely to increase.
3) Responsiveness of the development server
The cold start for
npm run dev
(Vite) takes 1:30 minutes, while the hot restart takes 1 minute. This is also quite slow, especially when you need to restart the server after changing the configuration. Along with the IDE, my MacBook Pro starts to struggle.4) SvelteKit adapters
SvelteKit has excellent adapters for various use cases. We used
adapter-node
, which allows some customization of the Node.js server, but only to a limited extent. At the end of the build process, you can replace the entry point inbuild/index.js
and override what you need there (SvelteKit adapter-node documentation).This can lead to discrepancies between server behavior during development and production, which has repeatedly caused bugs. We managed to work around this issue similarly to how SvelteKit handles the dev mode for Vite (SvelteKit Vite dev mode code).
However, I dislike such workarounds and would prefer having an API for server customization in both dev and production modes.
Here’s a snippet demonstrating a custom plugin approach for Vite:
This snippet helps maintain consistency between development and production environments, but it’s not ideal. It would be better to have a built-in API that allows more straightforward customization in both modes.
5) Runtime perfomance
I appreciate that SvelteKit allows you to write API endpoints out of the box (SvelteKit server routes). However, as experience has shown, this approach isn't always the most performant. For a load of 11k RPS, it required around 200 pods just to proxy requests to other backends and render HTML. This is a significant amount of resources for relatively simple tasks. As a result, we decided that the best approach would be to write endpoints directly on the Node.js server, bypassing SvelteKit.
6) UI kit
Our UI kit isn't the largest, but it contains many icons (about 2,000). Svelte doesn’t currently support compiling libraries to publish as pre-built JavaScript, which means these components are recompiled every time. I’m not sure what can be done about this, but it seems like unnecessary overhead.
Update
7) Playwright testing
I remembered some additional challenges related to testing. On our most demanding project, we have 6,159 Playwright tests. We encountered several issues when testing a SvelteKit application.
SSR: When there’s a lot of server-side rendering (SSR) in a project, and the page is returned already rendered, it’s not very clear how to mock API calls on the SSR side. We’ve had to implement various workarounds and heavily modify the Node.js server to enable such mocks.
Since client-side load functions (
+page.js
) started serializing responses, it has become impossible to mock them effectively.Additionally, SSR in SvelteKit can lead to flaky tests. For example, a Playwright selector might click a button before hydration is complete, causing the test to fail because the event handler hasn’t been attached yet.
It would be helpful to have a section in the documentation addressing this issue, offering best practices for handling SSR-related testing challenges.
Update 20/09/2024
8) Microfrontends + Svelte kit
From everything mentioned above, it suggests that the project should be split. And that micro-frontends might be the solution. However, after searching for ready-made solutions, you find nothing.
There is vite-plugin-federation, but it is completely incompatible with SvelteKit. I tried to dig into it and combine them, but without success. The problem is that SvelteKit and Federation handle and generate chunks differently.
If you think about it, a micro-frontend is just a small SPA application. And if you remember, a Svelte component (v4) is a regular class that can be instantiated programmatically, then we have a plan.
In principle, Vite is enough for us to create micro-frontends using Vite's capabilities.
In the service that will expose microfrontends, We can create a file called
manifest.ts
and export an object from it with dynamic imports of components.And in the host application, where we want to embed the micro-frontend, we can do something like this:
This is a simplified example. There are some pitfalls with this approach, but it will work. Thanks to Vite, which has a Vite preload feature that will automatically load all dependent chunks of JS and CSS when importing the micro-frontend.
Beta Was this translation helpful? Give feedback.
All reactions