Skip to content

Commit ebe197e

Browse files
authored
feat: allow change the HTML filename (#459)
1 parent 3b2a70c commit ebe197e

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

examples/multiple-pages-with-store/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dev": "DEBUG='vite-ssg:*' vite",
66
"build": "DEBUG='vite-ssg:*' vite-ssg build",
77
"build:nested": "NESTED_PAGES=true DEBUG='vite-ssg:*' vite-ssg build",
8+
"build:test": "LOG_ROUTES=true NESTED_PAGES=true DEBUG='vite-ssg:*' vite-ssg build",
89
"serve": "vite preview"
910
},
1011
"dependencies": {

examples/multiple-pages-with-store/vite.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ const config: UserConfig = {
2727
script: 'async',
2828
dirStyle: process.env.NESTED_PAGES === 'true' ? 'nested' : 'flat',
2929
formatting: 'prettify',
30+
htmlFileName: process.env.LOG_ROUTES === 'true'
31+
? (filename) => {
32+
console.log(`Generating HTML file: ${filename}`)
33+
return undefined
34+
}
35+
: undefined,
3036
},
3137
}
3238

src/node/build.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { mergeConfig, resolveConfig, build as viteBuild } from 'vite'
1717
import { serializeState } from '../utils/state'
1818
import { getBeasties } from './critical'
1919
import { renderPreloadLinks } from './preload-links'
20-
import { buildLog, getSize, routesToPaths } from './utils'
20+
import { buildLog, getSize, prepareHtmlFileName, routesToPaths } from './utils'
2121

2222
export type Manifest = Record<string, string[]>
2323

@@ -55,6 +55,7 @@ export async function build(ssgOptions: Partial<ViteSSGOptions> = {}, viteConfig
5555
concurrency = 20,
5656
rootContainerId = 'app',
5757
base,
58+
htmlFileName,
5859
}: ViteSSGOptions = mergedOptions
5960

6061
const beastiesOptions = mergedOptions.beastiesOptions ?? {}
@@ -196,9 +197,12 @@ export async function build(ssgOptions: Partial<ViteSSGOptions> = {}, viteConfig
196197
? `${route}index`
197198
: route).replace(/^\//g, '')}.html`
198199

199-
const filename = dirStyle === 'nested'
200-
? join(route.replace(/^\//g, ''), 'index.html')
201-
: relativeRouteFile
200+
const filename = await prepareHtmlFileName(
201+
dirStyle === 'nested'
202+
? join(route.replace(/^\//g, ''), 'index.html')
203+
: relativeRouteFile,
204+
htmlFileName,
205+
)
202206

203207
await fs.mkdir(resolve(out, dirname(filename)), { recursive: true })
204208
await fs.writeFile(resolve(out, filename), formatted, 'utf-8')

src/node/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ViteSSGOptions } from 'vite-ssg'
12
import type { RouteRecordRaw } from 'vue-router'
23
import { blue, gray, yellow } from 'ansis'
34

@@ -10,6 +11,18 @@ export function getSize(str: string) {
1011
return `${(str.length / 1024).toFixed(2)} KiB`
1112
}
1213

14+
export async function prepareHtmlFileName(
15+
filename: string,
16+
htmlFileName?: ViteSSGOptions['htmlFileName'],
17+
) {
18+
filename = filename.replace(/\\/g, '/')
19+
if (!htmlFileName)
20+
return filename
21+
22+
const newFileName = await htmlFileName(filename)
23+
return newFileName || filename
24+
}
25+
1326
export function routesToPaths(routes?: Readonly<RouteRecordRaw[]>) {
1427
if (!routes)
1528
return ['/']

src/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ export interface ViteSSGOptions {
113113
* @default 20
114114
*/
115115
concurrency?: number
116+
117+
/**
118+
* Given a Vue route, `vite-ssg` will use the route path to generate the HTML file, this function
119+
* will allow you to change that HTML filename.
120+
*
121+
* For example, using `unplugin-vue-router/vite` plugin on Windows, the `catch all` (`[...all].vue`)
122+
* page will throw an error since the file (`:all(.*).html`) is not a valid file name on Windows
123+
* filesystem. Old `vite-plugin-pages` plugin allows us to change the route styles to Nuxt, but this
124+
* feature is still missing at `unplugin-vue-router/vite`.
125+
*
126+
* Beware that this function is called for every route; you can return `undefined` to keep the
127+
* default behavior for unchanged routes.
128+
*
129+
* Beware also that you will need to handle the new file in your backend server, as the file name
130+
* will not match the route name.
131+
*
132+
* The provided HTML filename will always be relative to the output directory.
133+
*
134+
* @param filename The file name including the `.html` extension.
135+
* @return The new file name, or `undefined` to keep the default behavior.
136+
*/
137+
htmlFileName?: (filename: string) => string | undefined | Promise<string | undefined>
116138
}
117139

118140
type PartialKeys<T, Keys extends keyof T> = Omit<T, Keys> & Partial<Pick<T, Keys>>

0 commit comments

Comments
 (0)