Merge pull request #430 from nagisa77/codex/add-server-side-rendering-for-index.vue

Enable SSR initial render for home and post pages
This commit is contained in:
Tim
2025-08-08 12:58:05 +08:00
committed by GitHub
2 changed files with 36 additions and 30 deletions

View File

@@ -107,7 +107,7 @@
</template>
<script>
import { ref, onMounted, watch } from 'vue'
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useScrollLoadMore } from '~/utils/loadMore'
import { stripMarkdown } from '~/utils/markdown'
@@ -131,7 +131,7 @@ export default {
SearchDropdown,
ClientOnly: () => import('vue').then(m => m.defineAsyncComponent(() => import('vue').then(() => ({ template: '<slot />' }))))
},
setup() {
async setup() {
const route = useRoute()
/**
@@ -170,14 +170,11 @@ export default {
const allLoaded = ref(false)
/**
* -------- 2. CLIENTSIDE ONLY: LDRS REGISTER --------
* 这里使用动态 import 避免 SSR 阶段触发 HTMLElement 未定义错误
* -------- 2. INIT FETCH FOR SSR --------
* 服务端渲染阶段也需要获取首页内容和选项
*/
onMounted(async () => {
// 首次加载
fetchContent()
await loadOptions()
})
await loadOptions()
await fetchContent()
/**
* -------- 3. FETCH OPTION HELPERS --------

View File

@@ -126,7 +126,7 @@ import Dropdown from '../components/Dropdown.vue'
export default {
name: 'PostPageView',
components: { CommentItem, CommentEditor, BaseTimeline, ArticleTags, ArticleCategory, ReactionsGroup, DropdownMenu, VueEasyLightbox, Dropdown },
setup() {
async setup() {
const route = useRoute()
const postId = route.params.id
const router = useRouter()
@@ -150,27 +150,35 @@ export default {
const commentSort = ref('NEWEST')
const isFetchingComments = ref(false)
// record default metadata from the main document
const defaultTitle = document.title
const metaDescriptionEl = document.querySelector('meta[name="description"]')
const defaultDescription = metaDescriptionEl ? metaDescriptionEl.getAttribute('content') : ''
const headerHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0
// record default metadata from the main document (client only)
const defaultTitle = process.client ? document.title : ''
const metaDescriptionEl = process.client
? document.querySelector('meta[name="description"]')
: null
const defaultDescription = process.client && metaDescriptionEl
? metaDescriptionEl.getAttribute('content')
: ''
const headerHeight = process.client
? parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0
: 0
watch(title, t => {
document.title = `OpenIsle - ${t}`
})
if (process.client) {
watch(title, t => {
document.title = `OpenIsle - ${t}`
})
watch(postContent, c => {
if (metaDescriptionEl) {
metaDescriptionEl.setAttribute('content', stripMarkdownLength(c, 400))
}
})
watch(postContent, c => {
if (metaDescriptionEl) {
metaDescriptionEl.setAttribute('content', stripMarkdownLength(c, 400))
}
})
onBeforeUnmount(() => {
document.title = defaultTitle
if (metaDescriptionEl) metaDescriptionEl.setAttribute('content', defaultDescription)
window.removeEventListener('scroll', updateCurrentIndex)
})
onBeforeUnmount(() => {
document.title = defaultTitle
if (metaDescriptionEl) metaDescriptionEl.setAttribute('content', defaultDescription)
window.removeEventListener('scroll', updateCurrentIndex)
})
}
const lightboxVisible = ref(false)
const lightboxIndex = ref(0)
@@ -294,7 +302,7 @@ export default {
})
isWaitingFetchingPost.value = false;
if (!res.ok) {
if (res.status === 404) {
if (res.status === 404 && process.client) {
router.replace('/404')
}
return
@@ -581,10 +589,11 @@ export default {
router.push(`/users/${author.value.id}`)
}
await fetchPost()
onMounted(async () => {
const hash = location.hash
const id = hash.startsWith('#comment-') ? hash.substring('#comment-'.length) : null
await fetchPost()
if (id) expandCommentPath(id)
updateCurrentIndex()
window.addEventListener('scroll', updateCurrentIndex)