-
-
Notifications
You must be signed in to change notification settings - Fork 128
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
Separate SSR app render and HTML transform phases with client build in between #267
base: main
Are you sure you want to change the base?
Separate SSR app render and HTML transform phases with client build in between #267
Conversation
|
||
// Now that the SSR apps have run (which may have created client assets), we can run the client build. | ||
buildLog('Build for client...') | ||
await viteBuild(mergeConfig(viteConfig, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we reset process.env.VITE_SSG
and process.env.SSR
before running the client build?
EDIT: ppl can use import.meta.env.SSR
and import.meta.env.VITE_SSG
in their code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about deregistering jsdom
?
EDIT: check this line https://github.com/antfu/vite-ssg/blob/main/src/client/index.ts#L24
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary to reverse the build order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are to support use cases such as the one I have provided, then yes, reversing the build order is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about deregistering
jsdom
?EDIT: check this line https://github.com/antfu/vite-ssg/blob/main/src/client/index.ts#L24
how about deregistering
jsdom
?EDIT: check this line https://github.com/antfu/vite-ssg/blob/main/src/client/index.ts#L24
I'm not sure I understand the feedback. That line looks like it's checking for the existence of the window object in order to determine whether it should do a client build. Nothing about that would be changed by my PR, as far as I can tell.
Here is a visual example to demonstrate (with pseudocode) the use case that this PR makes possible: export async function performCachedRequest(request) {
if (import.meta.env.SSR) {
if (isInCache(request)) {
return JSON.parse(await fs.readFile(`/generated/cache/${getCacheKey(request)}.json`)).toString('utf-8'))
} else {
const response = await makeRequest(request)
await fs.writeFile(`../generated/cache/${getCacheKey(request)}.json`, JSON.stringify(response))
return response;
}
}
return import(`../generated/cache/${getCacheKey(request)}`)
} <template><div>{{ myData.title }}</div><template>
<script>
import { performCachedRequest } from './perform-cached-request'
export default {
async setup() {
const myData = await performCachedRequest({ my: 'request' })
return { myData }
}
}
</script> It's an extremely basic caching mechanism that utilizes local files to achieve something not unlike the asyncData caching in Nuxt, but in a way less opinionated way. As you run the site build, it will run Now, in order for this example to work, vite would have to bundle up all the files in I will note that it does not seem like there was a particular reason the client build was being run first, and I don't think changing this carries any negative consequences. It just required some minor restructuring to make it possible. |
@antfu if you wouldn't mind reviewing - thanks! |
Haven't looking deep into it, but it seems to break my site https://github.com/antfu/antfu.me. Could you help checking out which change is breaking it? Thanks. |
This PR restructures the build script to run two separate queues.
SSR app render
First, we run
vue/server-renderer
for each route. When this queue completes, we will have the raw HTML output rendered out into files within the vite-ssg-temp dir. Why did I bother to write this HTML out to files, you ask? One goal of this PR is to reduce the likelihood of OOM errors. Since some static sites can grow to include hundreds or thousands of routes, each with their own initialState payload , responsible memory usage is crucial to avoid scalability issues. By writing the HTML to files, we avoid holding these very large strings in memory. We can load each HTML string as we need it during the next step.HTML Transforms
With all the
vue/server-renderer
output in temp files, we can now read the HTML for each route and apply all the built in transformations (formatting, preload, critters, etc) in a separate queue.Why Do This
As mentioned above, part of the reasoning here is to improve stability of the build job by keeping some of these large strings in temp files instead of clogging up memory.
Another reason is to accommodate operations occurring during SSR that may affect the client distributable. At present, the client build occurs first, then all SSR renders occur afterward. This means that the SSR render process cannot write / alter files that would potentially be desired in the client build, as the client build has already been run.
For example: say my SSR application keeps track of all network requests run during build and writes those payloads to json files. I could then use dynamic imports in my client application to resolve those json files as a caching layer, right? Except here's the problem: vite doesn't know about those json files because they got written during the SSR build, so the json files will be missing from the distributable. My PR solves this by first running all the SSR renders, then running the client build. So by the time the client build runs, all the SSR renders have run.