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
Proposal: Allow fallback to SPA in universal mode's generate #2690
Comments
I implemented a first draft of this functionality in a module: // modules/spa-fallback.js
const { writeFile } = require('fs-extra')
const { join } = require('path')
module.exports = function installSPAFallback () {
this.nuxt.hook('generate:done', async generator => {
let { html } = await this.nuxt.renderRoute('/', {spa: true})
await writeFile(join(generator.distPath, '__spa-fallback.html'), html, 'utf8')
})
} // nuxt.config.js
{
// ...
modules: ['~/modules/spa-fallback'],
generate: {
subFolders: false,
// ...
}
} Now when you use the following config on Firebase hosting: // firebase.json
{
"hosting": {
"public": "./dist",
"cleanUrls": true,
"trailingSlash": false,
"rewrites": [
{"source": "**", "destination": "/__spa-fallback.html"}
]
}
} You can test this locally by running |
Hi. I love the idea behind this proposal. Currently, we generate a |
Hi @pi0! I've actually tried that before, but it didn't work when |
It does work on |
What if we change it to something like this and always call it (Both SSR and SPA generates) async afterGenerate() {
const { fallback } = this.options.generate // Defaults to 404.html
if (!fallback) {
return // Disabled
}
const fallbackPath = join(this.distPath, fallback)
if (existsSync(fallbackPath)) {
return // Prevent conflicts
}
const { html } = await this.nuxt.renderRoute('/', {spa: true})
await writeFile(fallbackPath, html, 'utf8')
} |
Right! I guess that would work really well, solving two issues instead of one:
|
What's your idea @Atinux @alexchopin @clarkdo? |
I love this idea! I think we could call it |
@Atinux Great! I would like to be able to configure it, since we might choose to only route Maybe have the Let me know what you think, will draft a PR for this tonight. |
@jeroenvisser101 Actually since it's on SPA mode, it will try to match the url, and if it does not match anything, it will show the 404 page too :) |
Actually defaulting
I think they will, since |
I think making by default a |
@jeroenvisser101 exactly, the point here is to not show a 404 page to the user while your are generating the website behind. |
Totally, let's do this.
This could be nice just in case someone has a use case where this is needed, maybe different hosting that requires special paths. |
I have been digging the same idea for a while and I am glad that someone not only thinks the same way, but also came up with implementation. |
@DreaMinder Cache invalidation would be as easy as doing |
@DreaMinder I think this is a very specific use case (but still one that we share, obviously). We've been thinking about this and something that we think we could do is building better build-caching so rebuilds are faster (e.g. only changed data has to be loaded). We've also been experimenting with plugins that add additional metadata to the dist folder, GlobalID-like identifiers that specify what resources have been used on which routes, but this hasn't been stable yet. This metadata would then be used to determine which files to delete/update, and we'd only re-render those files.
We have determined some resources change quite often (e.g. e-commerce store, changing stock wouldn't trigger a rebuild), but we still do queries once the component has been mounted, so we do still load the most up-to-date data for the user. Once the result comes back we merge the data with the preloaded data. |
This would break BC. We could adopt the following:
|
Fixed in #2698 |
It's now live with v1.3.0! |
Woooh! 🎉 |
@jeroenvisser101 Would love to see a simple demo of this setup in examples if possible! |
@stursby I like that, let me see if I can make time for that this week |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Intro
We're using Nuxt.js to build a site. We have an GraphQL API that we query to get all the content. Nuxt.js is then used to generate a 'prerendered' version of the site, that will be interactive once fully loaded. Consecutive page loads (user navigating around the site) only load GraphQL data (and if needed, additional JS).
Problem
Now, we were anticipating that the 'universal' mode would allow us to generate routes for all dynamic pages, but when someone adds new data, some problems arise.
Imagine the following on the
async-data
example when being served on a static hosting (e.g. Netlify, Firebase Hosting) being built by runningnuxt generate
:We serve the generated
index.html
through Firebase Hosting, the page will become interactive but no additional queries are performed on the client side.We query the posts and show all post titles with a link to their respective routes.
/posts/1
is generated, but all the others are not and exists only in the databaseWe query the post by id, and we render the component.
Now, there are two ways this could go:
index.html
, but since it assumes that it was correctly generated, upon becoming interactive, it won't notice the route doesn't match the rendered content, and shows the wrong content (the homepage).Proposal
So to solve this issue and to make Nuxt.js more flexible when used in 'universal' mode but deployed statically, I'd want to suggest a configuration option where—aside from the generated pages—a HTML file with the SPA template (with the loader and without any data) would be returned which would allow us to route all 'Not found' traffic to the SPA template.
This would allow us to build a platform where data changes trigger rebuilds of the site (e.g. run
nuxt generate
asynchronously) but where the route would function instantly.I'd love to get your thoughts on this, to see if you have a better suggestion on handling cases like these. Thanks!
The text was updated successfully, but these errors were encountered: