vitrify 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +3 -3
- package/dist/bin/dev.js +26 -39
- package/dist/frameworks/vue/fastify-ssr-plugin.js +58 -19
- package/dist/frameworks/vue/prerender.js +4 -4
- package/dist/frameworks/vue/server.js +5 -1
- package/dist/hooks/index.js +1 -0
- package/dist/index.js +80 -94
- package/dist/plugins/index.js +2 -1
- package/dist/plugins/pinia/index.js +61 -0
- package/dist/plugins/quasar/index.js +226 -0
- package/dist/types/frameworks/vue/fastify-ssr-plugin.d.ts +6 -3
- package/dist/types/frameworks/vue/prerender.d.ts +3 -3
- package/dist/types/frameworks/vue/server.d.ts +4 -4
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/plugins/index.d.ts +13 -2
- package/dist/types/plugins/pinia/index.d.ts +5 -0
- package/dist/types/plugins/{quasar.d.ts → quasar/index.d.ts} +5 -5
- package/dist/types/vitrify-config.d.ts +87 -12
- package/package.json +37 -25
- package/src/node/bin/cli.ts +13 -7
- package/src/node/bin/dev.ts +30 -41
- package/src/node/frameworks/vue/fastify-ssr-plugin.ts +85 -28
- package/src/node/frameworks/vue/prerender.ts +6 -6
- package/src/node/frameworks/vue/server.ts +11 -2
- package/src/node/hooks/index.ts +19 -0
- package/src/node/index.ts +114 -130
- package/src/node/plugins/index.ts +20 -3
- package/src/node/plugins/pinia/index.ts +96 -0
- package/src/node/plugins/quasar/index.ts +318 -0
- package/src/node/vitrify-config.ts +120 -21
- package/src/vite/fastify/server.ts +3 -0
- package/src/vite/vue/RootComponent.vue +1 -1
- package/src/vite/vue/main.ts +52 -22
- package/src/vite/vue/ssr/app.ts +3 -2
- package/src/vite/vue/ssr/entry-server.ts +22 -41
- package/src/vite/vue/ssr/prerender.ts +2 -2
- package/dist/plugins/quasar.js +0 -217
- package/src/node/plugins/quasar.ts +0 -307
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url'
|
|
2
|
+
import type {
|
|
3
|
+
OnBootHook,
|
|
4
|
+
OnMountedHook,
|
|
5
|
+
OnTemplateRenderedHook,
|
|
6
|
+
VitrifyConfig
|
|
7
|
+
} from '../../vitrify-config.js'
|
|
8
|
+
import type { VitrifyPlugin } from '../index.js'
|
|
9
|
+
import { findDepPkgJsonPath } from 'vitefu'
|
|
10
|
+
import {
|
|
11
|
+
type QuasarFonts,
|
|
12
|
+
type QuasarComponents,
|
|
13
|
+
type QuasarDirectives,
|
|
14
|
+
type QuasarIconSets,
|
|
15
|
+
type QuasarPlugins,
|
|
16
|
+
type GlobalQuasarIconMapFn,
|
|
17
|
+
type QuasarIconSet
|
|
18
|
+
} from 'quasar'
|
|
19
|
+
import { QuasarResolver } from 'unplugin-vue-components/resolvers'
|
|
20
|
+
|
|
21
|
+
export interface QuasarPluginOptions {
|
|
22
|
+
framework: {
|
|
23
|
+
components?: (keyof QuasarComponents)[]
|
|
24
|
+
directives?: (keyof QuasarDirectives)[]
|
|
25
|
+
plugins?: (keyof QuasarPlugins)[]
|
|
26
|
+
lang?: string
|
|
27
|
+
iconSet?: QuasarIconSets | QuasarIconSet
|
|
28
|
+
iconMapFn?: GlobalQuasarIconMapFn
|
|
29
|
+
}
|
|
30
|
+
extras?: (QuasarIconSets | QuasarFonts)[]
|
|
31
|
+
disableSass?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const injectSsrContext: OnTemplateRenderedHook = ({
|
|
35
|
+
html,
|
|
36
|
+
ssrContext
|
|
37
|
+
}) =>
|
|
38
|
+
html
|
|
39
|
+
.replace(/(<html[^>]*)(>)/i, (found, start, end) => {
|
|
40
|
+
let matches
|
|
41
|
+
|
|
42
|
+
matches = found.match(/\sdir\s*=\s*['"]([^'"]*)['"]/i)
|
|
43
|
+
if (matches) {
|
|
44
|
+
start = start.replace(matches[0], '')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
matches = found.match(/\slang\s*=\s*['"]([^'"]*)['"]/i)
|
|
48
|
+
if (matches) {
|
|
49
|
+
start = start.replace(matches[0], '')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return `${start} ${ssrContext?._meta.htmlAttrs || ''} ${end}`
|
|
53
|
+
})
|
|
54
|
+
.replace(
|
|
55
|
+
/(<head[^>]*)(>)/i,
|
|
56
|
+
(_, start, end) => `${start}${end}${ssrContext?._meta.headTags || ''}`
|
|
57
|
+
)
|
|
58
|
+
.replace(
|
|
59
|
+
/(<\/head>)/i,
|
|
60
|
+
(_, tag) =>
|
|
61
|
+
`${ssrContext?._meta.resourceStyles || ''}${
|
|
62
|
+
ssrContext?._meta.endingHeadTags || ''
|
|
63
|
+
}${tag}`
|
|
64
|
+
)
|
|
65
|
+
.replace(/(<body[^>]*)(>)/i, (found, start, end) => {
|
|
66
|
+
let classes = ssrContext?._meta.bodyClasses || ''
|
|
67
|
+
|
|
68
|
+
const matches = found.match(/\sclass\s*=\s*['"]([^'"]*)['"]/i)
|
|
69
|
+
|
|
70
|
+
if (matches) {
|
|
71
|
+
if (matches[1].length > 0) {
|
|
72
|
+
classes += ` ${matches[1]}`
|
|
73
|
+
}
|
|
74
|
+
start = start.replace(matches[0], '')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return `${start} class="${classes.trim()}" ${
|
|
78
|
+
ssrContext?._meta.bodyAttrs || ''
|
|
79
|
+
}${end}${ssrContext?._meta.bodyTags || ''}`
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export const QuasarPlugin: VitrifyPlugin<QuasarPluginOptions> = async ({
|
|
83
|
+
ssr = false,
|
|
84
|
+
pwa = false,
|
|
85
|
+
options
|
|
86
|
+
}) => {
|
|
87
|
+
let plugins: string[] = []
|
|
88
|
+
const quasarConf: QuasarPluginOptions = options
|
|
89
|
+
return {
|
|
90
|
+
plugins: [
|
|
91
|
+
{
|
|
92
|
+
name: 'vite-plugin-quasar-transform',
|
|
93
|
+
enforce: 'pre',
|
|
94
|
+
transform: (code, id, options) => {
|
|
95
|
+
code = code
|
|
96
|
+
.replaceAll('__QUASAR_SSR__', ssr ? 'true' : 'false')
|
|
97
|
+
.replaceAll(
|
|
98
|
+
'__QUASAR_SSR_SERVER__',
|
|
99
|
+
ssr ? '(import.meta.env.SSR === true)' : 'false'
|
|
100
|
+
)
|
|
101
|
+
.replaceAll(
|
|
102
|
+
'__QUASAR_SSR_CLIENT__',
|
|
103
|
+
ssr ? '(import.meta.env.SSR === false)' : 'false'
|
|
104
|
+
)
|
|
105
|
+
.replaceAll(
|
|
106
|
+
'__QUASAR_SSR_PWA__',
|
|
107
|
+
ssr && pwa ? '(import.meta.env.SSR === false)' : 'false'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return code
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'vite-plugin-quasar-setup',
|
|
115
|
+
enforce: 'pre',
|
|
116
|
+
config: async (config: VitrifyConfig, env): Promise<VitrifyConfig> => {
|
|
117
|
+
const { vitrify: { urls } = {} } = config
|
|
118
|
+
|
|
119
|
+
// if (quasar) quasarConf = quasar
|
|
120
|
+
if (!quasarConf.framework.lang && config.vitrify?.lang)
|
|
121
|
+
quasarConf.framework.lang = config.vitrify.lang
|
|
122
|
+
|
|
123
|
+
const globalCss = quasarConf?.extras?.map(
|
|
124
|
+
(extra) => `@quasar/extras/${extra}/${extra}.css`
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
const localPackages = ['@quasar/extras', 'quasar']
|
|
128
|
+
// const localPackages: string[] = []
|
|
129
|
+
await (async () => {
|
|
130
|
+
for (const val of localPackages) {
|
|
131
|
+
const pkgDir = await findDepPkgJsonPath(
|
|
132
|
+
val,
|
|
133
|
+
fileURLToPath(config.vitrify!.urls!.app!)
|
|
134
|
+
)
|
|
135
|
+
if (pkgDir) urls!.packages![val] = new URL(`file://${pkgDir}`)
|
|
136
|
+
}
|
|
137
|
+
})()
|
|
138
|
+
|
|
139
|
+
const onMountedHooks: OnMountedHook[] = [
|
|
140
|
+
async (instance) => {
|
|
141
|
+
const {
|
|
142
|
+
proxy: { $q }
|
|
143
|
+
} = instance
|
|
144
|
+
if ($q.onSSRHydrated !== void 0) $q.onSSRHydrated()
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
const onBootHooks: OnBootHook[] = [
|
|
149
|
+
async ({ app, ssrContext, staticImports }) => {
|
|
150
|
+
// @ts-expect-error undefined
|
|
151
|
+
const quasarPlugins = await import('virtual:quasar-plugins')
|
|
152
|
+
// @ts-expect-error undefined
|
|
153
|
+
const directives = await import('virtual:quasar-directives')
|
|
154
|
+
// @ts-expect-error undefined
|
|
155
|
+
const { default: lang } = await import('virtual:quasar-lang')
|
|
156
|
+
const { default: iconSet } = await import(
|
|
157
|
+
// @ts-expect-error undefined
|
|
158
|
+
'virtual:quasar-iconSet'
|
|
159
|
+
)
|
|
160
|
+
const { default: iconMapFn } = await import(
|
|
161
|
+
// @ts-expect-error undefined
|
|
162
|
+
'virtual:quasar-iconMapFn'
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
app.use(
|
|
166
|
+
staticImports?.Quasar,
|
|
167
|
+
{
|
|
168
|
+
plugins: quasarPlugins,
|
|
169
|
+
directives,
|
|
170
|
+
lang,
|
|
171
|
+
iconSet,
|
|
172
|
+
config: {
|
|
173
|
+
iconMapFn
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
ssrContext
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Importing package.json is problematic
|
|
183
|
+
*/
|
|
184
|
+
const version = '?'
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* All components should have been auto-imported
|
|
188
|
+
*/
|
|
189
|
+
if (quasarConf?.framework?.plugins) {
|
|
190
|
+
if (!quasarConf.framework) quasarConf.framework = {}
|
|
191
|
+
quasarConf.framework.plugins = [
|
|
192
|
+
...new Set(quasarConf.framework.plugins)
|
|
193
|
+
]
|
|
194
|
+
plugins = quasarConf?.framework.plugins
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
vitrify: {
|
|
199
|
+
urls,
|
|
200
|
+
globalCss,
|
|
201
|
+
staticImports: {
|
|
202
|
+
quasar: ['Quasar']
|
|
203
|
+
},
|
|
204
|
+
hooks: {
|
|
205
|
+
onBoot: onBootHooks,
|
|
206
|
+
onMounted: onMountedHooks,
|
|
207
|
+
onTemplateRendered: [injectSsrContext]
|
|
208
|
+
},
|
|
209
|
+
sass: quasarConf.disableSass
|
|
210
|
+
? undefined
|
|
211
|
+
: {
|
|
212
|
+
global: ['quasar/src/css/index.sass']
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
resolve: {
|
|
216
|
+
alias: [
|
|
217
|
+
{
|
|
218
|
+
find: 'quasar/src/',
|
|
219
|
+
replacement: fileURLToPath(
|
|
220
|
+
new URL('./src/', config.vitrify!.urls!.packages!.quasar)
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
optimizeDeps: {
|
|
226
|
+
exclude: ['quasar']
|
|
227
|
+
},
|
|
228
|
+
define: {
|
|
229
|
+
__DEV__: process.env.NODE_ENV !== 'production' || true,
|
|
230
|
+
__QUASAR_VERSION__: `'${version}'`
|
|
231
|
+
},
|
|
232
|
+
ssr: {
|
|
233
|
+
noExternal: ['quasar']
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: 'quasar-virtual-modules',
|
|
240
|
+
enforce: 'pre',
|
|
241
|
+
config: async (config, env) => ({
|
|
242
|
+
resolve: {
|
|
243
|
+
alias: [
|
|
244
|
+
{
|
|
245
|
+
find: new RegExp('^quasar$'),
|
|
246
|
+
replacement: 'virtual:quasar'
|
|
247
|
+
}
|
|
248
|
+
// { find: new RegExp('^quasar$'), replacement: 'virtual:quasar' }
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
}),
|
|
252
|
+
resolveId(id) {
|
|
253
|
+
switch (id) {
|
|
254
|
+
case 'virtual:quasar-plugins':
|
|
255
|
+
return 'virtual:quasar-plugins'
|
|
256
|
+
case 'virtual:quasar-directives':
|
|
257
|
+
return 'virtual:quasar-directives'
|
|
258
|
+
case 'virtual:quasar-lang':
|
|
259
|
+
return 'virtual:quasar-lang'
|
|
260
|
+
case 'virtual:quasar-iconSet':
|
|
261
|
+
return 'virtual:quasar-iconSet'
|
|
262
|
+
case 'virtual:quasar-iconMapFn':
|
|
263
|
+
return 'virtual:quasar-iconMapFn'
|
|
264
|
+
case 'virtual:quasar':
|
|
265
|
+
return { id: 'virtual:quasar', moduleSideEffects: false }
|
|
266
|
+
default:
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
load(id) {
|
|
271
|
+
if (id === 'virtual:quasar-plugins') {
|
|
272
|
+
return `export { ${plugins.join(',')} } from 'quasar'`
|
|
273
|
+
} else if (id === 'virtual:quasar-directives') {
|
|
274
|
+
return `export * from 'quasar/src/directives.js'`
|
|
275
|
+
} else if (id === 'virtual:quasar-lang') {
|
|
276
|
+
return `import lang from 'quasar/lang/${
|
|
277
|
+
quasarConf?.framework?.lang || 'en-US'
|
|
278
|
+
}';
|
|
279
|
+
export default lang`
|
|
280
|
+
} else if (id === 'virtual:quasar-iconSet') {
|
|
281
|
+
return `${
|
|
282
|
+
typeof quasarConf.framework.iconSet === 'string'
|
|
283
|
+
? `import iconSet from 'quasar/icon-set/${
|
|
284
|
+
quasarConf?.framework.iconSet || 'material-icons'
|
|
285
|
+
}';
|
|
286
|
+
export default iconSet`
|
|
287
|
+
: `export default ${
|
|
288
|
+
quasarConf.framework.iconSet
|
|
289
|
+
? JSON.stringify(quasarConf.framework.iconSet)
|
|
290
|
+
: null
|
|
291
|
+
}`
|
|
292
|
+
}`
|
|
293
|
+
} else if (id === 'virtual:quasar-iconMapFn') {
|
|
294
|
+
return `export default ${
|
|
295
|
+
quasarConf?.framework.iconMapFn?.toString() ?? null
|
|
296
|
+
}`
|
|
297
|
+
} else if (id === 'virtual:quasar') {
|
|
298
|
+
return `export * from 'quasar/src/plugins.js';
|
|
299
|
+
export * from 'quasar/src/components.js';
|
|
300
|
+
export * from 'quasar/src/composables.js';
|
|
301
|
+
export * from 'quasar/src/directives.js';
|
|
302
|
+
export * from 'quasar/src/utils.js';
|
|
303
|
+
export * from 'quasar/src/composables.js';
|
|
304
|
+
export { default as Quasar } from 'quasar/src/install-quasar.js'`
|
|
305
|
+
}
|
|
306
|
+
return null
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
],
|
|
310
|
+
config: {
|
|
311
|
+
vitrify: {
|
|
312
|
+
unpluginVueComponents: {
|
|
313
|
+
resolvers: [QuasarResolver()]
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -1,51 +1,133 @@
|
|
|
1
1
|
import type { Alias, UserConfig as ViteUserConfig, ViteDevServer } from 'vite'
|
|
2
|
-
import type { QuasarConf } from './plugins/quasar.js'
|
|
3
2
|
import type { ComponentInternalInstance } from '@vue/runtime-core'
|
|
4
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
FastifyInstance,
|
|
5
|
+
FastifyReply,
|
|
6
|
+
FastifyRequest,
|
|
7
|
+
FastifyServerOptions
|
|
8
|
+
} from 'fastify'
|
|
5
9
|
import type { VitePWAOptions } from 'vite-plugin-pwa'
|
|
6
|
-
import {
|
|
10
|
+
import type { Options as unpluginVueComponentsOptions } from 'unplugin-vue-components'
|
|
7
11
|
import type { UserConfig as UnoCSSUserConfig } from '@unocss/core'
|
|
12
|
+
import type { VitrifyPlugin } from './plugins/index.js'
|
|
13
|
+
import type { Router } from 'vue-router'
|
|
14
|
+
import type { App } from '@vue/runtime-core'
|
|
15
|
+
import type { Pinia } from 'pinia'
|
|
16
|
+
import type { _UseQueryEntryNodeValueSerialized } from '@pinia/colada/index.js'
|
|
8
17
|
|
|
9
|
-
export type
|
|
18
|
+
export type SSRContext = {
|
|
19
|
+
// Quasar requires req and res on SSRContext instead of request and reply
|
|
20
|
+
req:
|
|
21
|
+
| FastifyRequest
|
|
22
|
+
| {
|
|
23
|
+
headers: Record<string, unknown>
|
|
24
|
+
url: string
|
|
25
|
+
}
|
|
26
|
+
res: FastifyReply | Record<string, unknown>
|
|
27
|
+
provide: Record<string, unknown>
|
|
28
|
+
initialState: {
|
|
29
|
+
provide?: Record<string, unknown>
|
|
30
|
+
pinia?: Record<string, unknown>
|
|
31
|
+
piniaColada?: Record<string, _UseQueryEntryNodeValueSerialized>
|
|
32
|
+
[key: string]: unknown
|
|
33
|
+
}
|
|
34
|
+
pinia?: Pinia
|
|
35
|
+
// Quasar internals
|
|
36
|
+
_modules: Set<unknown>
|
|
37
|
+
_meta: Record<string, any>
|
|
38
|
+
__qMetaList: unknown[]
|
|
39
|
+
/**
|
|
40
|
+
* Required for Quasar
|
|
41
|
+
*/
|
|
42
|
+
onRenderedList: (() => unknown)[]
|
|
43
|
+
onRendered: (fn: () => unknown) => void
|
|
44
|
+
/**
|
|
45
|
+
* Vue internals
|
|
46
|
+
*/
|
|
47
|
+
modules?: Map<unknown, unknown>
|
|
48
|
+
transports?: Record<string, unknown>
|
|
49
|
+
[key: string]: unknown
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type onAppCreatedHook = ({
|
|
10
53
|
app,
|
|
11
|
-
|
|
12
|
-
|
|
54
|
+
router,
|
|
55
|
+
ctx,
|
|
56
|
+
initialState,
|
|
57
|
+
ssrContext
|
|
13
58
|
}: {
|
|
14
|
-
app:
|
|
15
|
-
|
|
16
|
-
|
|
59
|
+
app: App
|
|
60
|
+
router: Router
|
|
61
|
+
ctx: {
|
|
62
|
+
pinia?: Pinia
|
|
63
|
+
[key: string]: unknown
|
|
64
|
+
}
|
|
65
|
+
initialState: {
|
|
66
|
+
provide?: Record<string, unknown>
|
|
67
|
+
pinia?: Record<string, unknown>
|
|
68
|
+
piniaColada?: Record<string, _UseQueryEntryNodeValueSerialized>
|
|
69
|
+
[key: string]: unknown
|
|
70
|
+
}
|
|
71
|
+
ssrContext?: SSRContext
|
|
17
72
|
}) => Promise<void> | void
|
|
73
|
+
|
|
18
74
|
export type OnBootHook = ({
|
|
19
75
|
app,
|
|
20
76
|
ssrContext,
|
|
21
77
|
staticImports
|
|
22
78
|
}: {
|
|
23
|
-
app:
|
|
24
|
-
ssrContext:
|
|
79
|
+
app: App
|
|
80
|
+
ssrContext: SSRContext
|
|
25
81
|
staticImports?: Record<string, any>
|
|
26
82
|
}) => Promise<void> | void
|
|
83
|
+
|
|
27
84
|
export type OnMountedHook = (
|
|
28
85
|
instance: ComponentInternalInstance
|
|
29
86
|
) => Promise<void> | void
|
|
30
87
|
export type StaticImports = Record<string, string[]>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
ssrContext: Record<string, any>
|
|
34
|
-
) => string
|
|
35
|
-
export type OnRenderedHook = (
|
|
36
|
-
html: string,
|
|
37
|
-
ssrContext: Record<string, any>
|
|
38
|
-
) => string
|
|
88
|
+
|
|
89
|
+
export type OnSetupFile = URL
|
|
39
90
|
export type OnSetupHook = (
|
|
40
91
|
fastify: FastifyInstance,
|
|
41
92
|
options?: {
|
|
42
93
|
vite?: ViteDevServer
|
|
43
94
|
}
|
|
44
95
|
) => any
|
|
45
|
-
|
|
96
|
+
|
|
97
|
+
export type Render = (
|
|
98
|
+
url: string,
|
|
99
|
+
manifest: Record<string, unknown>,
|
|
100
|
+
ssrContext: SSRContext,
|
|
101
|
+
renderToString: (app: App, ctx?: Record<string, any>) => Promise<string>
|
|
102
|
+
) => Promise<{
|
|
103
|
+
html: string
|
|
104
|
+
preloadLinks: string
|
|
105
|
+
app: App
|
|
106
|
+
}>
|
|
107
|
+
|
|
108
|
+
export type OnRenderedHook = ({
|
|
109
|
+
app,
|
|
110
|
+
ssrContext
|
|
111
|
+
}: {
|
|
112
|
+
app: App
|
|
113
|
+
ssrContext?: SSRContext
|
|
114
|
+
}) => Promise<void> | void
|
|
115
|
+
|
|
116
|
+
export type OnTemplateRenderedHook = ({
|
|
117
|
+
html,
|
|
118
|
+
ssrContext
|
|
119
|
+
}: {
|
|
120
|
+
html: string
|
|
121
|
+
ssrContext?: SSRContext
|
|
122
|
+
}) => Promise<string> | string
|
|
123
|
+
|
|
46
124
|
export interface VitrifyConfig extends ViteUserConfig {
|
|
47
125
|
vitrify?: {
|
|
48
126
|
lang?: string
|
|
127
|
+
/**
|
|
128
|
+
* Vitrify plugins
|
|
129
|
+
*/
|
|
130
|
+
plugins?: VitrifyPluginConfig[]
|
|
49
131
|
/**
|
|
50
132
|
* Global CSS imports
|
|
51
133
|
*/
|
|
@@ -71,6 +153,14 @@ export interface VitrifyConfig extends ViteUserConfig {
|
|
|
71
153
|
* Functions which run after rendering the app (SSR)
|
|
72
154
|
*/
|
|
73
155
|
onRendered?: OnRenderedHook[]
|
|
156
|
+
/**
|
|
157
|
+
* Functions which run after rendering the template (SSR)
|
|
158
|
+
*/
|
|
159
|
+
onTemplateRendered?: OnTemplateRenderedHook[]
|
|
160
|
+
/**
|
|
161
|
+
* Functions which run directly after initializing the application
|
|
162
|
+
*/
|
|
163
|
+
onAppCreated?: onAppCreatedHook[]
|
|
74
164
|
}
|
|
75
165
|
/**
|
|
76
166
|
* Global SASS variables
|
|
@@ -118,8 +208,12 @@ export interface VitrifyConfig extends ViteUserConfig {
|
|
|
118
208
|
* UnoCSS Configuration
|
|
119
209
|
*/
|
|
120
210
|
unocss?: UnoCSSUserConfig
|
|
211
|
+
/**
|
|
212
|
+
* unplugin-vue-components configuration
|
|
213
|
+
*/
|
|
214
|
+
unpluginVueComponents?: unpluginVueComponentsOptions
|
|
121
215
|
}
|
|
122
|
-
quasar?: QuasarConf
|
|
216
|
+
// quasar?: QuasarConf
|
|
123
217
|
}
|
|
124
218
|
|
|
125
219
|
export type VitrifyCommands = 'build' | 'dev' | 'test'
|
|
@@ -135,4 +229,9 @@ export type VitrifyConfigAsync = ({
|
|
|
135
229
|
command: VitrifyCommands
|
|
136
230
|
}) => Promise<VitrifyConfig>
|
|
137
231
|
|
|
232
|
+
type VitrifyPluginConfig = {
|
|
233
|
+
plugin: VitrifyPlugin<any>
|
|
234
|
+
options: any
|
|
235
|
+
}
|
|
236
|
+
|
|
138
237
|
export const defineConfig = (config: VitrifyConfig) => config
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
onMounted as onMountedVue,
|
|
9
9
|
getCurrentInstance
|
|
10
10
|
} from 'vue'
|
|
11
|
-
import {
|
|
11
|
+
import { onMounted } from 'virtual:vitrify-hooks'
|
|
12
12
|
import * as staticImports from 'virtual:static-imports'
|
|
13
13
|
import App from 'src/App.vue'
|
|
14
14
|
// import 'vitrify.sass'
|
package/src/vite/vue/main.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import createRouter from 'src/router'
|
|
2
|
-
import { createSSRApp, createApp as createVueApp, ref } from 'vue'
|
|
3
|
-
import { onBoot } from 'virtual:vitrify-hooks'
|
|
2
|
+
import { App, createSSRApp, createApp as createVueApp, ref } from 'vue'
|
|
3
|
+
import { onBoot, onAppCreated } from 'virtual:vitrify-hooks'
|
|
4
4
|
import routes from 'src/router/routes'
|
|
5
5
|
import * as staticImports from 'virtual:static-imports'
|
|
6
6
|
import 'virtual:uno.css'
|
|
7
|
-
|
|
8
7
|
import RootComponent from './RootComponent.vue'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import { parse } from 'devalue'
|
|
9
|
+
import type { SSRContext } from '../../node/vitrify-config'
|
|
10
|
+
import type { Pinia } from 'pinia'
|
|
11
|
+
|
|
12
|
+
declare global {
|
|
13
|
+
interface Window {
|
|
14
|
+
__INITIAL_STATE__: any
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
function capitalizeFirstLetter(string: string) {
|
|
@@ -17,18 +21,58 @@ function capitalizeFirstLetter(string: string) {
|
|
|
17
21
|
|
|
18
22
|
export async function createApp(
|
|
19
23
|
ssr?: 'client' | 'server',
|
|
20
|
-
ssrContext?:
|
|
24
|
+
ssrContext?: SSRContext
|
|
21
25
|
) {
|
|
22
|
-
let
|
|
26
|
+
let initialState: Record<string, any> | null = null
|
|
27
|
+
|
|
28
|
+
if (!import.meta.env.SSR && window?.__INITIAL_STATE__) {
|
|
29
|
+
initialState = window.__INITIAL_STATE__
|
|
30
|
+
|
|
31
|
+
for (const key in initialState) {
|
|
32
|
+
if (key === 'provide' || key === 'piniaColada') {
|
|
33
|
+
initialState[key] = JSON.parse(initialState[key])
|
|
34
|
+
} else {
|
|
35
|
+
initialState[key] = parse(initialState[key], {
|
|
36
|
+
PiniaColada_TreeMapNode: (data) => data
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Delete for security reasons
|
|
43
|
+
if (!import.meta.env.SSR && window.__INITIAL_STATE__)
|
|
44
|
+
delete window.__INITIAL_STATE__
|
|
45
|
+
|
|
46
|
+
let provide: Record<string, any> = {}
|
|
47
|
+
if (import.meta.env.SSR) {
|
|
48
|
+
if (ssrContext?.provide) {
|
|
49
|
+
provide = ssrContext?.provide
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
if (initialState) {
|
|
53
|
+
provide = initialState.provide
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let app: App
|
|
58
|
+
const ctx: {
|
|
59
|
+
pinia?: Pinia
|
|
60
|
+
[key: string]: unknown
|
|
61
|
+
} = {}
|
|
23
62
|
|
|
24
63
|
if (ssr) {
|
|
25
64
|
app = createSSRApp(RootComponent)
|
|
26
65
|
} else {
|
|
27
66
|
app = createVueApp(RootComponent)
|
|
28
67
|
}
|
|
68
|
+
|
|
29
69
|
const router = createRouter()
|
|
30
70
|
app.use(router)
|
|
31
71
|
|
|
72
|
+
for (const fn of onAppCreated) {
|
|
73
|
+
await fn({ app, router, ctx, initialState, ssrContext })
|
|
74
|
+
}
|
|
75
|
+
|
|
32
76
|
// Workaround to fix hydration errors when serving html files directly
|
|
33
77
|
router.beforeEach((to, from, next) => {
|
|
34
78
|
if (to.path.endsWith('.html')) {
|
|
@@ -38,20 +82,6 @@ export async function createApp(
|
|
|
38
82
|
next()
|
|
39
83
|
})
|
|
40
84
|
|
|
41
|
-
let initialState: Record<string, any>
|
|
42
|
-
let provide: Record<string, any> = {}
|
|
43
|
-
if (import.meta.env.SSR) {
|
|
44
|
-
if (ssrContext?.provide) {
|
|
45
|
-
provide = ssrContext?.provide
|
|
46
|
-
}
|
|
47
|
-
} else {
|
|
48
|
-
// @ts-expect-error undefined
|
|
49
|
-
if (window.__INITIAL_STATE__) {
|
|
50
|
-
// @ts-expect-error undefined
|
|
51
|
-
initialState = JSON.parse(window.__INITIAL_STATE__)
|
|
52
|
-
provide = initialState.provide
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
85
|
for (const key in provide) {
|
|
56
86
|
if (provide[key]?.value) {
|
|
57
87
|
const refValue = ref(provide[key].value)
|
package/src/vite/vue/ssr/app.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createApp } from '../../../node/frameworks/vue/server.js'
|
|
2
2
|
import { getAppDir } from '../../../node/app-urls.js'
|
|
3
|
-
import { onSetup, onRendered } from 'virtual:vitrify-hooks'
|
|
3
|
+
import { onSetup, onRendered, onTemplateRendered } from 'virtual:vitrify-hooks'
|
|
4
4
|
import { fastifySsrPlugin } from './fastify-ssr-plugin.js'
|
|
5
5
|
|
|
6
6
|
const getString = (str?: string) => str
|
|
@@ -14,9 +14,10 @@ export const setupApp = async () => {
|
|
|
14
14
|
baseUrl,
|
|
15
15
|
fastifyPlugin: fastifySsrPlugin,
|
|
16
16
|
onRendered,
|
|
17
|
+
onTemplateRendered,
|
|
17
18
|
mode: import.meta.env.MODE
|
|
18
19
|
})
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export { default as vitrifyConfig } from 'virtual:vitrify-config'
|
|
22
|
-
export { onRendered }
|
|
23
|
+
export { onRendered, onTemplateRendered }
|