1
+ import { createHash } from 'crypto'
1
2
import fs from 'fs-extra'
2
3
import { createRequire } from 'module'
3
4
import ora from 'ora'
@@ -7,9 +8,9 @@ import { rimraf } from 'rimraf'
7
8
import type { OutputAsset , OutputChunk } from 'rollup'
8
9
import { pathToFileURL } from 'url'
9
10
import type { BuildOptions } from 'vite'
10
- import { resolveConfig } from '../config'
11
- import type { HeadConfig } from '../shared'
12
- import { serializeFunctions } from '../utils/fnSerialize'
11
+ import { resolveConfig , type SiteConfig } from '../config'
12
+ import { slash , type HeadConfig } from '../shared'
13
+ import { deserializeFunctions , serializeFunctions } from '../utils/fnSerialize'
13
14
import { bundle , failMark , okMark } from './bundle'
14
15
import { renderPage } from './render'
15
16
@@ -79,6 +80,8 @@ export async function build(
79
80
chunk . moduleIds . some ( ( id ) => id . includes ( 'client/theme-default' ) )
80
81
)
81
82
83
+ const metadataScript = generateMetadataScript ( pageToHashMap , siteConfig )
84
+
82
85
if ( isDefaultTheme ) {
83
86
const fontURL = assets . find ( ( file ) =>
84
87
/ i n t e r - r o m a n - l a t i n \. \w + \. w o f f 2 / . test ( file )
@@ -97,15 +100,6 @@ export async function build(
97
100
}
98
101
}
99
102
100
- // We embed the hash map and site config strings into each page directly
101
- // so that it doesn't alter the main chunk's hash on every build.
102
- // It's also embedded as a string and JSON.parsed from the client because
103
- // it's faster than embedding as JS object literal.
104
- const hashMapString = JSON . stringify ( JSON . stringify ( pageToHashMap ) )
105
- const siteDataString = JSON . stringify (
106
- JSON . stringify ( serializeFunctions ( { ...siteConfig . site , head : [ ] } ) )
107
- )
108
-
109
103
await Promise . all (
110
104
[ '404.md' , ...siteConfig . pages ]
111
105
. map ( ( page ) => siteConfig . rewrites . map [ page ] || page )
@@ -119,8 +113,7 @@ export async function build(
119
113
cssChunk ,
120
114
assets ,
121
115
pageToHashMap ,
122
- hashMapString ,
123
- siteDataString ,
116
+ metadataScript ,
124
117
additionalHeadTags
125
118
)
126
119
)
@@ -168,3 +161,51 @@ function linkVue() {
168
161
}
169
162
return ( ) => { }
170
163
}
164
+
165
+ function generateMetadataScript (
166
+ pageToHashMap : Record < string , string > ,
167
+ config : SiteConfig
168
+ ) {
169
+ if ( config . mpa ) {
170
+ return { html : '' , inHead : false }
171
+ }
172
+
173
+ // We embed the hash map and site config strings into each page directly
174
+ // so that it doesn't alter the main chunk's hash on every build.
175
+ // It's also embedded as a string and JSON.parsed from the client because
176
+ // it's faster than embedding as JS object literal.
177
+ const hashMapString = JSON . stringify ( JSON . stringify ( pageToHashMap ) )
178
+ const siteDataString = JSON . stringify (
179
+ JSON . stringify ( serializeFunctions ( { ...config . site , head : [ ] } ) )
180
+ )
181
+
182
+ const metadataContent = `window.__VP_HASH_MAP__=JSON.parse(${ hashMapString } );${
183
+ siteDataString . includes ( '_vp-fn_' )
184
+ ? `${ deserializeFunctions . toString ( ) } ;window.__VP_SITE_DATA__=deserializeFunctions(JSON.parse(${ siteDataString } ));`
185
+ : `window.__VP_SITE_DATA__=JSON.parse(${ siteDataString } );`
186
+ } `
187
+
188
+ if ( ! config . metaChunk ) {
189
+ return { html : `<script>${ metadataContent } </script>` , inHead : false }
190
+ }
191
+
192
+ const metadataFile = path . join (
193
+ config . assetsDir ,
194
+ 'chunks' ,
195
+ `metadata.${ createHash ( 'sha256' )
196
+ . update ( metadataContent )
197
+ . digest ( 'hex' )
198
+ . slice ( 0 , 8 ) } .js`
199
+ )
200
+
201
+ const resolvedMetadataFile = path . join ( config . outDir , metadataFile )
202
+ const metadataFileURL = slash ( `${ config . site . base } ${ metadataFile } ` )
203
+
204
+ fs . ensureDirSync ( path . dirname ( resolvedMetadataFile ) )
205
+ fs . writeFileSync ( resolvedMetadataFile , metadataContent )
206
+
207
+ return {
208
+ html : `<script type="module" src="${ metadataFileURL } "></script>` ,
209
+ inHead : true
210
+ }
211
+ }
0 commit comments