feat: experimental server persistent caching#10671
feat: experimental server persistent caching#10671Akryum wants to merge 59 commits intovitejs:mainfrom
Conversation
|
Will probably not work with Svelte as they use a custom cache for the |
|
Found a solution: cache the In the Svelte plugin:
Solution:
I tested on this svelte app: |
|
Tested with https://github.com/martpie/museeks (electron + React) |
|
Tested with https://github.com/yyx990803/vite-vs-next-turbo-hmr (React) |
|
Test on https://github.com/noeldemartin/umai (Vue) |
So I have tested again but on Chrome as I had a file descriptor limit issue. |
There was a problem hiding this comment.
Thanks a lot for this work. The api with custom exclude and config files is really what was missing in my implementation. And the lazy loading of cache values is a lot more coherent with the vite architecture.
I think what is missing is a check for environment variables. A simple first solution could be to exclude from the cache files that contains pattern like process.env or import.meta.env
| } else { | ||
| const saveKey = fileCacheInfo.relatedModules[loadCacheKey] | ||
| if (saveKey) { | ||
| loadResult = await _persistentCache.read(saveKey) |
There was a problem hiding this comment.
Can you explain a bit more the goal of this whole block? (maybe with an example of two ids for svelte)
I don't understand why the override of await pluginContainer.load(id, { ssr }) is only done when idWithoutHmrFlag !== file
Maybe a first version could only focus on the transform part and see if some plugins can migrate the heavy work from load to transform?
There was a problem hiding this comment.
The goal is to restore the result of plugin.load in case it needed side effects from plugin.transform. For example (not real requests):
transform:Foo.svelte=> put<style>part into an internal cache as side-effectload:Foo.svelte?type=css=> retrieve the content of<style>from the internal cache.
There was a problem hiding this comment.
I will bootstrap the a simple svelte template with the inspect plugin to better understand how it works and comeback here after.
There was a problem hiding this comment.
As I understand it, the load hook will return nothing for Foo.svelte?type=css when Foo.svelte was already cached (and thus, never processed by transform pipeline). By caching the load result, Vite can still access the Foo.svelte?type=css contents for the cached Foo.svelte module.
Since the load hook is always called (even for cached modules), this is a necessary workaround.
There was a problem hiding this comment.
Ideally, there would be a way for a load result to declare a "dependency" on another file's contents. This way, Vite wouldn't have to cache the load result of every file.
edit: Oh I just remembered that we have addWatchFile from the Rollup API. That could probably work. 🤔
|
I wonder about the option name actually. It's sort of an implementation detail that the cache is on the server object. Perhaps just |
| const includedInPersistentCache = | ||
| _persistentCache && | ||
| !file.includes(server.config.cacheDir) && | ||
| !file.includes('vite/dist/client') && |
There was a problem hiding this comment.
this line could use a comment as to either when it would occur or why we want to exclude it
There was a problem hiding this comment.
Well it excludes the vite client
There was a problem hiding this comment.
Well it excludes the vite client
That doesn't explain why 😆
Yes it's |
This comment was marked as outdated.
This comment was marked as outdated.
|
In the last meeting while discussing #10943, we thought it would be nice if all the caching logic is handled as an internal Vite plugin. It's not completely necessary for this PR but it would make it easier to maintain. It might involve adding hooks/options/metadata for the Vite plugin lifecycle, but they should be kept internal only. |
|
Hey @Akryum - we've been testing your branch on our codebase, and have run into an issue; refreshes after code has changed break the dev server if your code has circular imports. Here's a minimal reproduction! https://github.com/arilotter/vite-caching-circular-imports Let me know if I can help 😁 |
|
Leaving a comment for reference, this PR has proven that server persistent caching could bring a big perf boost to some projects. It wasn't merged as part of Vite 4 because we were unsure of the current caching invalidation logic being correct for all cases. I think we have two options moving forward (I think we should pursue both):
|
|
IMHO persistent caching in core might be preferable, even if it is an opt-in experiment and disabled by default initially.
Support for a basic level of caching that works for every project seems far more valuable than supporting niche caching logic for specific applications and circumstances. If there's still desire to have caching in core, I can work on adapting the bug reported by @arilotter as a failing test and try fixing it. |
|
Not knowing the details of the situation here, I also want to ask if being "unsure of the current caching invalidation logic being correct for all cases" is the issue, why isn't one of the potential avenues to pursue making it sufficiently robust? Or has there been some situation identified where it'd be impossible for Vite to cover all its bases (presumably even with configuration)? |
|
@Akryum would it be possible to re-test some of the examples you tried here using vite@4.3.0-beta.2? It would be great to know if the latest performance improvements reduce the need for caching, or how far we are from the ideal of a cached warm start to keep digging (or re-evaluate caching once more if we can't find a way to further speed up the dev server). |
Apologies if I'm misreading, but if it isn't being considered, please also keep in mind the potential impact of caching on full builds, not just the dev server. This has the potential to be important eg for monorepo tools that rely on full rebuilds of dependency packages on change (eg, |
@patak-dev, as someone who is fetching ~6000 modules per page, I can say that the speed increase in Vite 4.3.x is absolutely incredible. It's around 5 times faster! I could not believe it at first, but it's all real. It will make a huge difference to our productivity. |
|
@caghand thanks for getting back with metrics for your app! Happy to see 4.3 has such a big effect in your case. Would it be possible to share CPU profiles of cold and warm start with us? We should continue to check if there are other perf gains out there. You can use |
|
Continued in #14333 |










Description
Fixes #1309
I have seen loading speed increase of up to 5x faster in subsequent warm server starts on my computer. It's basically almost as fast as a page reload.
Try it
You can install it with a special release at
@akryum/vite@server-cache:It can be enabled with the new
experimental.serverPersistentCacheconfig.You can further customize the feature with an object:
If you encounter issues try clearing the cache:
Known issues
Page load might fail if theoptimizeDepscache (node_modules/.vite) is empty (workaround is to clear persistent cache and try again)Cached module HMRNow working!Demo
Screencast.from.28-10-2022.00.09.52.webm
On the app I'm testing this against, the page load goes from ~10s (cold start) to ~2s (cache hit).
Additional context
This is a PoC about using persistent caching in development.
The idea is to cache as close as possible to the slowest part of the module processing:
await pluginContainer.transform(), in order to avoid breaking stuff as much as possible.Implementation notes:
cacheVersionandcacheVersionFromFiles(using content hashing). By default it also adds the vite version, the vite config file, thedefinevalues, theenvvalues, the package lock file and thetsconfig.jsonfile.await pluginContainer.load()logic in case side effects fromawait pluginContainer.transform()would affect it. For example, the Svelte plugin adds CSS subrequests in an internal cache as a side-effect oftransform().importedModules.browserHashso that they are correct for the next server start.What is the purpose of this pull request?
Before submitting the PR, please make sure you do the following
fixes #123).