Skip to content

Instantly share code, notes, and snippets.

@u007
Last active August 26, 2024 03:50
Show Gist options
  • Save u007/0fd4b01296b0bda43e0015397ed2d90c to your computer and use it in GitHub Desktop.
Save u007/0fd4b01296b0bda43e0015397ed2d90c to your computer and use it in GitHub Desktop.
nuxt3 prerender on server side without reloading on frontend
export default defineNuxtRouteMiddleware((to, from) => {
if (import.meta.server) return
const nav = useNavStore();
// console.log('middlwae client', nav.clientSide)
if (nav.clientSide) {
return;
}
setTimeout(() => {
nav.setClientSide(true);
}, 200)
});
export default defineNuxtConfig({
//....
hooks: {
'pages:extend'(pages) {
function setMiddleware(pages: NuxtPage[]) {
for (const page of pages) {
if (/* some condition */ true) {
page.meta ||= {}
// Note that this will override any middleware set in `definePageMeta` in the page
page.meta.middleware = ['client']
}
if (page.children) {
setMiddleware(page.children)
}
}
}
setMiddleware(pages)
}
}
})
<template>
<ProductsProductList />
</template>
<script lang="ts" setup>
import superjson from 'superjson'
const $nav = useNavStore()
const sharedProductList = useState('productList', () => '')
// to support objectid
superjson.registerCustom<ObjectID, string>(
{
isApplicable: (v): v is ObjectID => v instanceof ObjectID,
serialize: v => v.toHexString(),
deserialize: v => {
try {
return new ObjectID(v);
} catch (error) {
console.warn(`Invalid ObjectID: ${v}. Returning null.`);
return new ObjectID('000000000000000000000000');
}
},
},
'objectid'
);
const loadProducsts = async() => {
// your async code to return list
}
const { data, pending: productsLoading, refresh } = await useAsyncData(
'products',
async () => {
if (typeof window !== 'undefined' && !$nav.clientSide) {
console.log('useAsyncData server only, skipped.')
return
}
console.log('useAsyncData runs...')
const [productsData,
// categoriesData
] = await Promise.allSettled([
loadProducts(),
// loadCategories(),
])
if (typeof window === 'undefined') {
// console.log('useAsyncData productsData', superjson.stringify(productsData.value))
const productRes = superjson.stringify(productsData.value)
sharedProductList.value = productRes
} else {
// update it to makesure it does not show when transition to another list or page
sharedProductList.value = superjson.stringify({ total: 0, list: [] })
}
// sharedCategoryList.value = superjson.stringify(categoriesData.value)
},
{
watch: [currentPage, categoryIds, props.search, props.categoryId, props.limit, props.showCategories],
deep: true,
server: true,
// server: true
})
onMounted(() => {
// console.log('data? sharedProductList', sharedProductList.value)
const productRes = sharedProductList.value ? superjson.parse(sharedProductList.value) : { list: [], total: 0 }
total.value = productRes.total
productList.value = productRes.list
// run any client side data
loadCategories()
// why the hell useasyncdata does not reload when this component is rerendered
refresh()
allowLoadMore.value = true
})
</script>
import { defineStore, acceptHMRUpdate } from 'pinia'
export const useNavStore = defineStore('nav', {
state: () => {
return {
loading: false,
clientSide: false,
}
},
actions: {
setClientSide(clientSide: boolean) {
this.clientSide = clientSide
}
},
})
if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useNavStore, import.meta.hot))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment