Skip to content

Commit 23276ba

Browse files
brc-ddkiaking
andauthored
feat: emit 404.html on build (#729) (#740)
close #729 Co-authored-by: Kia Ishii <kia.king.08@gmail.com>
1 parent 263607b commit 23276ba

File tree

4 files changed

+48
-33
lines changed

4 files changed

+48
-33
lines changed

Diff for: src/client/app/router.ts

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { reactive, inject, markRaw, nextTick, readonly } from 'vue'
22
import type { Component, InjectionKey } from 'vue'
3-
import { PageData } from '../shared'
3+
import { PageData, notFoundPageData } from '../shared'
44
import { inBrowser, withBase } from './utils'
55
import { siteDataRef } from './data'
66

@@ -21,15 +21,6 @@ export const RouterSymbol: InjectionKey<Router> = Symbol()
2121
// matter and is only passed to support same-host hrefs.
2222
const fakeHost = `http://a.com`
2323

24-
const notFoundPageData: PageData = {
25-
relativePath: '',
26-
title: '404',
27-
description: 'Not Found',
28-
headers: [],
29-
frontmatter: {},
30-
lastUpdated: 0
31-
}
32-
3324
const getDefaultRoute = (): Route => ({
3425
path: '/',
3526
component: null,
@@ -109,7 +100,7 @@ export function createRouter(
109100
}
110101
}
111102
} catch (err: any) {
112-
if (!err.message.match(/fetch/)) {
103+
if (!err.message.match(/fetch/) && !href.match(/^[\\/]404\.html$/)) {
113104
console.error(err)
114105
}
115106

Diff for: src/node/build/build.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ export async function build(
4949
// as JS object literal.
5050
const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap))
5151

52-
for (const page of siteConfig.pages) {
52+
const pages = ['404.md', ...siteConfig.pages]
53+
54+
for (const page of pages) {
5355
await renderPage(
5456
siteConfig,
5557
page,

Diff for: src/node/build/render.ts

+34-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { pathToFileURL } from 'url'
55
import escape from 'escape-html'
66
import { normalizePath, transformWithEsbuild } from 'vite'
77
import { RollupOutput, OutputChunk, OutputAsset } from 'rollup'
8-
import { HeadConfig, createTitle } from '../shared'
8+
import { HeadConfig, PageData, createTitle, notFoundPageData } from '../shared'
99
import { slash } from '../utils/slash'
1010
import { SiteConfig, resolveSiteDataByRoute } from '../config'
1111

@@ -52,28 +52,41 @@ export async function renderPage(
5252
const pageHash = pageToHashMap[pageName.toLowerCase()]
5353
const pageClientJsFileName = `assets/${pageName}.${pageHash}.lean.js`
5454

55-
// resolve page data so we can render head tags
56-
const { __pageData } = await import(
57-
pathToFileURL(path.join(config.tempDir, pageServerJsFileName)).toString()
58-
)
59-
const pageData = JSON.parse(__pageData)
55+
let pageData: PageData
56+
let hasCustom404 = true
57+
58+
try {
59+
// resolve page data so we can render head tags
60+
const { __pageData } = await import(
61+
pathToFileURL(path.join(config.tempDir, pageServerJsFileName)).toString()
62+
)
63+
pageData = JSON.parse(__pageData)
64+
} catch (e) {
65+
if (page === '404.md') {
66+
hasCustom404 = false
67+
pageData = notFoundPageData
68+
} else {
69+
throw e
70+
}
71+
}
6072

61-
let preloadLinks = config.mpa
62-
? appChunk
63-
? [appChunk.fileName]
73+
let preloadLinks =
74+
config.mpa || (!hasCustom404 && page === '404.md')
75+
? appChunk
76+
? [appChunk.fileName]
77+
: []
78+
: result && appChunk
79+
? [
80+
...new Set([
81+
// resolve imports for index.js + page.md.js and inject script tags
82+
// for them as well so we fetch everything as early as possible
83+
// without having to wait for entry chunks to parse
84+
...resolvePageImports(config, page, result, appChunk),
85+
pageClientJsFileName,
86+
appChunk.fileName
87+
])
88+
]
6489
: []
65-
: result && appChunk
66-
? [
67-
...new Set([
68-
// resolve imports for index.js + page.md.js and inject script tags for
69-
// them as well so we fetch everything as early as possible without having
70-
// to wait for entry chunks to parse
71-
...resolvePageImports(config, page, result, appChunk),
72-
pageClientJsFileName,
73-
appChunk.fileName
74-
])
75-
]
76-
: []
7790

7891
let prefetchLinks: string[] = []
7992

Diff for: src/shared/shared.ts

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ export const APPEARANCE_KEY = 'vitepress-theme-appearance'
1616
// @ts-ignore
1717
export const inBrowser = typeof window !== 'undefined'
1818

19+
export const notFoundPageData: PageData = {
20+
relativePath: '',
21+
title: '404',
22+
description: 'Not Found',
23+
headers: [],
24+
frontmatter: {},
25+
lastUpdated: 0
26+
}
27+
1928
function findMatchRoot(route: string, roots: string[]): string | undefined {
2029
// first match to the routes with the most deep level.
2130
roots.sort((a, b) => {

0 commit comments

Comments
 (0)