vitrify 0.2.0 → 0.2.1
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 +4 -3
- package/dist/{vue → frameworks/vue}/fastify-ssr-plugin.js +0 -0
- package/dist/{vue → frameworks/vue}/prerender.js +1 -1
- package/dist/{vue → frameworks/vue}/server.js +0 -0
- package/dist/index.js +16 -4
- package/dist/plugins/quasar.js +1 -1
- package/dist/types/{vue → frameworks/vue}/fastify-ssr-plugin.d.ts +1 -1
- package/dist/types/{vue → frameworks/vue}/prerender.d.ts +1 -1
- package/dist/types/{vue → frameworks/vue}/server.d.ts +1 -1
- package/package.json +2 -2
- package/src/node/frameworks/vue/fastify-ssr-plugin.ts +137 -0
- package/src/node/frameworks/vue/prerender.ts +49 -0
- package/src/node/frameworks/vue/server.ts +38 -0
- package/src/vite/vue/ssr/fastify-ssr-plugin.ts +1 -1
- package/src/vite/vue/ssr/prerender.ts +1 -1
- package/src/vite/vue/ssr/server.ts +6 -3
package/dist/bin/cli.js
CHANGED
|
@@ -13,8 +13,8 @@ cli
|
|
|
13
13
|
.option('--productName [productName]', 'Product name')
|
|
14
14
|
.action(async (options) => {
|
|
15
15
|
const { build } = await import('./build.js');
|
|
16
|
-
let prerender;
|
|
17
16
|
let appDir;
|
|
17
|
+
let prerender, ssrFunctions;
|
|
18
18
|
if (options.appDir) {
|
|
19
19
|
if (options.appDir.slice(-1) !== '/')
|
|
20
20
|
options.appDir += '/';
|
|
@@ -59,14 +59,15 @@ cli
|
|
|
59
59
|
...args,
|
|
60
60
|
outDir: new URL('ssr/server/', baseOutDir).pathname
|
|
61
61
|
});
|
|
62
|
-
prerender =
|
|
62
|
+
({ prerender, ssrFunctions } = await import(new URL('ssr/server/prerender.mjs', baseOutDir).pathname));
|
|
63
63
|
prerender({
|
|
64
64
|
outDir: new URL('static/', baseOutDir).pathname,
|
|
65
65
|
templatePath: new URL('static/index.html', baseOutDir).pathname,
|
|
66
66
|
manifestPath: new URL('static/ssr-manifest.json', baseOutDir)
|
|
67
67
|
.pathname,
|
|
68
68
|
entryServerPath: new URL('ssr/server/entry-server.mjs', baseOutDir)
|
|
69
|
-
.pathname
|
|
69
|
+
.pathname,
|
|
70
|
+
ssrFunctions
|
|
70
71
|
});
|
|
71
72
|
break;
|
|
72
73
|
default:
|
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
|
-
import { routesToPaths } from '
|
|
2
|
+
import { routesToPaths } from '../../helpers/routes.js';
|
|
3
3
|
export const prerender = async ({ outDir, templatePath, manifestPath, entryServerPath, ssrFunctions }) => {
|
|
4
4
|
const promises = [];
|
|
5
5
|
const template = (await fs.readFile(templatePath)).toString();
|
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -197,10 +197,6 @@ export const baseConfig = async ({ ssr, appDir, publicDir, command = 'build', mo
|
|
|
197
197
|
plugins.unshift({
|
|
198
198
|
name: 'html-transform',
|
|
199
199
|
enforce: 'pre',
|
|
200
|
-
config: (config, env) => {
|
|
201
|
-
if (config.vitrify?.productName)
|
|
202
|
-
productName = config.vitrify?.productName;
|
|
203
|
-
},
|
|
204
200
|
transform: (code, id) => {
|
|
205
201
|
if (id.endsWith('App.vue')) {
|
|
206
202
|
code =
|
|
@@ -232,6 +228,21 @@ export const baseConfig = async ({ ssr, appDir, publicDir, command = 'build', mo
|
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
});
|
|
231
|
+
plugins.unshift({
|
|
232
|
+
name: 'product-name',
|
|
233
|
+
enforce: 'post',
|
|
234
|
+
config: (config, env) => {
|
|
235
|
+
if (config.vitrify?.productName)
|
|
236
|
+
productName = config.vitrify?.productName;
|
|
237
|
+
},
|
|
238
|
+
transformIndexHtml: {
|
|
239
|
+
enforce: 'post',
|
|
240
|
+
transform: (html) => {
|
|
241
|
+
html = html.replace('<!--product-name-->', productName);
|
|
242
|
+
return html;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
});
|
|
235
246
|
}
|
|
236
247
|
const alias = [
|
|
237
248
|
{ find: 'src', replacement: srcDir.pathname },
|
|
@@ -285,6 +296,7 @@ export const baseConfig = async ({ ssr, appDir, publicDir, command = 'build', mo
|
|
|
285
296
|
? {
|
|
286
297
|
input: [
|
|
287
298
|
new URL('ssr/entry-server.ts', frameworkDir).pathname,
|
|
299
|
+
new URL('ssr/prerender.ts', frameworkDir).pathname,
|
|
288
300
|
new URL('ssr/server.ts', frameworkDir).pathname
|
|
289
301
|
],
|
|
290
302
|
output: {
|
package/dist/plugins/quasar.js
CHANGED
|
@@ -289,7 +289,7 @@ export const QuasarPlugin = async ({ ssr = false, pwa = false }) => {
|
|
|
289
289
|
export * from 'quasar/src/composables.js';
|
|
290
290
|
export * from 'quasar/src/directives.js';
|
|
291
291
|
export * from 'quasar/src/utils.js';
|
|
292
|
-
export { default as Quasar } from 'quasar/src/
|
|
292
|
+
export { default as Quasar } from 'quasar/src/install-quasar.js'`;
|
|
293
293
|
}
|
|
294
294
|
return null;
|
|
295
295
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FastifyPluginCallback, FastifyRequest, FastifyReply } from 'fastify';
|
|
2
2
|
import type { ViteDevServer } from 'vite';
|
|
3
|
-
import type { SsrFunction } from '
|
|
3
|
+
import type { SsrFunction } from '../../vitrify-config.js';
|
|
4
4
|
export interface FastifySsrOptions {
|
|
5
5
|
baseUrl?: string;
|
|
6
6
|
provide?: (req: FastifyRequest, res: FastifyReply) => Promise<Record<string, unknown>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { FastifyInstance } from 'fastify';
|
|
3
|
-
import type { SsrFunction } from '
|
|
3
|
+
import type { SsrFunction } from '../../vitrify-config.js';
|
|
4
4
|
export declare const createApp: ({ setup, appDir, baseUrl, ssrFunctions }: {
|
|
5
5
|
setup: (fastify: FastifyInstance) => any;
|
|
6
6
|
appDir: URL;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitrify",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Stefan van Herwijnen",
|
|
6
6
|
"description": "Pre-configured Vite CLI for your framework",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
},
|
|
104
104
|
"files": [
|
|
105
105
|
"dist",
|
|
106
|
-
"src/node/
|
|
106
|
+
"src/node/frameworks",
|
|
107
107
|
"src/vite",
|
|
108
108
|
"!dist/**/*.test.js",
|
|
109
109
|
"!dist/**/test.js"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FastifyPluginCallback,
|
|
3
|
+
FastifyRequest,
|
|
4
|
+
FastifyReply
|
|
5
|
+
} from 'fastify'
|
|
6
|
+
import fastifyStatic from 'fastify-static'
|
|
7
|
+
import { readFileSync } from 'fs'
|
|
8
|
+
// import { injectSsrContext } from '../helpers/ssr.js'
|
|
9
|
+
import type { ViteDevServer } from 'vite'
|
|
10
|
+
import type { SsrFunction } from '../../vitrify-config.js'
|
|
11
|
+
|
|
12
|
+
export interface FastifySsrOptions {
|
|
13
|
+
baseUrl?: string
|
|
14
|
+
provide?: (
|
|
15
|
+
req: FastifyRequest,
|
|
16
|
+
res: FastifyReply
|
|
17
|
+
) => Promise<Record<string, unknown>>
|
|
18
|
+
vite?: ViteDevServer
|
|
19
|
+
cliDir?: URL
|
|
20
|
+
appDir?: URL
|
|
21
|
+
productName?: string
|
|
22
|
+
ssrFunctions?: SsrFunction[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
26
|
+
fastify,
|
|
27
|
+
options,
|
|
28
|
+
done
|
|
29
|
+
) => {
|
|
30
|
+
if (import.meta.env.MODE === 'development') {
|
|
31
|
+
if (!options.vite) throw new Error('Option vite cannot be undefined')
|
|
32
|
+
const middie = (await import('middie')).default
|
|
33
|
+
await fastify.register(middie)
|
|
34
|
+
fastify.use(options.vite.middlewares)
|
|
35
|
+
|
|
36
|
+
fastify.get('*', async (req, res) => {
|
|
37
|
+
try {
|
|
38
|
+
// const url = req.originalUrl
|
|
39
|
+
const url = req.raw.url
|
|
40
|
+
const ssrContext = {
|
|
41
|
+
req,
|
|
42
|
+
res
|
|
43
|
+
}
|
|
44
|
+
// always read fresh template in dev
|
|
45
|
+
// template = readFileSync(resolve('index.html'), 'utf-8')
|
|
46
|
+
const template = readFileSync(
|
|
47
|
+
new URL('index.html', options.cliDir)
|
|
48
|
+
).toString()
|
|
49
|
+
|
|
50
|
+
// template = await vite.transformIndexHtml(url, template)
|
|
51
|
+
const entryUrl = new URL('ssr/entry-server.ts', options.cliDir).pathname
|
|
52
|
+
const render = (await options.vite!.ssrLoadModule(entryUrl)).render
|
|
53
|
+
let manifest
|
|
54
|
+
// TODO: https://github.com/vitejs/vite/issues/2282
|
|
55
|
+
try {
|
|
56
|
+
manifest = {}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
manifest = {}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const [appHtml, preloadLinks] = await render(url, manifest, ssrContext)
|
|
62
|
+
const html = template
|
|
63
|
+
.replace(`<!--preload-links-->`, preloadLinks)
|
|
64
|
+
.replace(`<!--app-html-->`, appHtml)
|
|
65
|
+
.replace('<!--product-name-->', options.productName || 'Product name')
|
|
66
|
+
|
|
67
|
+
res.code(200)
|
|
68
|
+
res.type('text/html')
|
|
69
|
+
res.send(html)
|
|
70
|
+
// res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
|
|
71
|
+
} catch (e: any) {
|
|
72
|
+
console.error(e.stack)
|
|
73
|
+
options.vite && options.vite.ssrFixStacktrace(e)
|
|
74
|
+
res.code(500)
|
|
75
|
+
res.send(e.stack)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
} else {
|
|
79
|
+
options.baseUrl = options.baseUrl || '/'
|
|
80
|
+
fastify.register(fastifyStatic, {
|
|
81
|
+
root: new URL('./dist/ssr/client', options.appDir).pathname,
|
|
82
|
+
wildcard: false,
|
|
83
|
+
index: false,
|
|
84
|
+
prefix: options.baseUrl
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
fastify.get(`${options.baseUrl}*`, async (req, res) => {
|
|
88
|
+
const url = req.raw.url
|
|
89
|
+
const provide = options.provide ? await options.provide(req, res) : {}
|
|
90
|
+
const ssrContext: Record<string, any> = {
|
|
91
|
+
req,
|
|
92
|
+
res,
|
|
93
|
+
provide
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// template = readFileSync(new URL('../client/index.html', import.meta.url).pathname).toString()
|
|
97
|
+
// manifest = JSON.parse(readFileSync(new URL('../client/ssr-manifest.json', import.meta.url)).toString())
|
|
98
|
+
// render = (await import(new URL('./entry-server.mjs', import.meta.url).pathname)).render
|
|
99
|
+
const template = readFileSync(
|
|
100
|
+
new URL('./dist/ssr/client/index.html', options.appDir).pathname
|
|
101
|
+
).toString()
|
|
102
|
+
const manifest = JSON.parse(
|
|
103
|
+
readFileSync(
|
|
104
|
+
new URL('./dist/ssr/client/ssr-manifest.json', options.appDir)
|
|
105
|
+
).toString()
|
|
106
|
+
)
|
|
107
|
+
const render = (
|
|
108
|
+
await import(
|
|
109
|
+
new URL('./dist/ssr/server/entry-server.mjs', options.appDir).pathname
|
|
110
|
+
)
|
|
111
|
+
).render
|
|
112
|
+
|
|
113
|
+
const [appHtml, preloadLinks] = await render(url, manifest, ssrContext)
|
|
114
|
+
|
|
115
|
+
if (!ssrContext.initialState) ssrContext.initialState = {}
|
|
116
|
+
ssrContext.initialState.provide = provide
|
|
117
|
+
|
|
118
|
+
let html = template
|
|
119
|
+
.replace(`<!--preload-links-->`, preloadLinks)
|
|
120
|
+
.replace(`<!--app-html-->`, appHtml)
|
|
121
|
+
|
|
122
|
+
if (options.ssrFunctions?.length) {
|
|
123
|
+
for (const ssrFunction of options.ssrFunctions) {
|
|
124
|
+
html = ssrFunction(html, ssrContext)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
res.code(200)
|
|
129
|
+
res.type('text/html')
|
|
130
|
+
res.send(html)
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
done()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { fastifySsrPlugin }
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import { routesToPaths } from '../../helpers/routes.js'
|
|
3
|
+
import type { SsrFunction } from '../../vitrify-config.js'
|
|
4
|
+
|
|
5
|
+
export const prerender = async ({
|
|
6
|
+
outDir,
|
|
7
|
+
templatePath,
|
|
8
|
+
manifestPath,
|
|
9
|
+
entryServerPath,
|
|
10
|
+
ssrFunctions
|
|
11
|
+
}: {
|
|
12
|
+
outDir: string
|
|
13
|
+
templatePath: string
|
|
14
|
+
manifestPath: string
|
|
15
|
+
entryServerPath: string
|
|
16
|
+
ssrFunctions: SsrFunction[]
|
|
17
|
+
}) => {
|
|
18
|
+
const promises = []
|
|
19
|
+
const template = (await fs.readFile(templatePath)).toString()
|
|
20
|
+
const manifest = await fs.readFile(manifestPath)
|
|
21
|
+
const { render, getRoutes } = await import(entryServerPath)
|
|
22
|
+
const routes = await getRoutes()
|
|
23
|
+
const paths = routesToPaths(routes).filter(
|
|
24
|
+
(i) => !i.includes(':') && !i.includes('*')
|
|
25
|
+
)
|
|
26
|
+
for (const url of paths) {
|
|
27
|
+
const filename =
|
|
28
|
+
(url.endsWith('/') ? 'index' : url.replace(/^\//g, '')) + '.html'
|
|
29
|
+
console.log(`Generating ${filename}`)
|
|
30
|
+
const ssrContext = {
|
|
31
|
+
req: { headers: {}, url },
|
|
32
|
+
res: {}
|
|
33
|
+
}
|
|
34
|
+
const [appHtml, preloadLinks] = await render(url, manifest, ssrContext)
|
|
35
|
+
|
|
36
|
+
let html = template
|
|
37
|
+
.replace(`<!--preload-links-->`, preloadLinks)
|
|
38
|
+
.replace(`<!--app-html-->`, appHtml)
|
|
39
|
+
|
|
40
|
+
if (ssrFunctions?.length) {
|
|
41
|
+
for (const ssrFunction of ssrFunctions) {
|
|
42
|
+
html = ssrFunction(html, ssrContext)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
promises.push(fs.writeFile(outDir + filename, html, 'utf-8'))
|
|
47
|
+
}
|
|
48
|
+
return Promise.all(promises)
|
|
49
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify'
|
|
2
|
+
import fastify from 'fastify'
|
|
3
|
+
import type { SsrFunction } from '../../vitrify-config.js'
|
|
4
|
+
// import { setup } from 'virtual:fastify-setup'
|
|
5
|
+
import { fastifySsrPlugin } from './fastify-ssr-plugin.js'
|
|
6
|
+
// import { getPkgJsonDir } from '../app-urls.js'
|
|
7
|
+
|
|
8
|
+
export const createApp = ({
|
|
9
|
+
setup,
|
|
10
|
+
appDir,
|
|
11
|
+
baseUrl,
|
|
12
|
+
ssrFunctions
|
|
13
|
+
}: {
|
|
14
|
+
setup: (fastify: FastifyInstance) => any
|
|
15
|
+
appDir: URL
|
|
16
|
+
baseUrl?: string
|
|
17
|
+
ssrFunctions?: SsrFunction[]
|
|
18
|
+
}) => {
|
|
19
|
+
const app = fastify({
|
|
20
|
+
logger: true
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
app.register(fastifySsrPlugin, {
|
|
24
|
+
baseUrl,
|
|
25
|
+
appDir,
|
|
26
|
+
ssrFunctions
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
setup(app)
|
|
30
|
+
|
|
31
|
+
return app
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// const app = createApp({
|
|
35
|
+
// setup
|
|
36
|
+
// })
|
|
37
|
+
|
|
38
|
+
// app.listen(process.env.PORT || 3000, process.env.HOST || '127.0.0.1')
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { createApp } from '../../../node/vue/server.js'
|
|
2
|
-
import {
|
|
1
|
+
import { createApp } from '../../../node/frameworks/vue/server.js'
|
|
2
|
+
import { getAppDir } from '../../../node/app-urls.js'
|
|
3
3
|
import { setup } from 'virtual:fastify-setup'
|
|
4
|
+
import ssrFunctions from 'virtual:ssr-functions'
|
|
4
5
|
|
|
5
6
|
// const appDir = getPkgJsonDir(import.meta.url)
|
|
6
7
|
const getString = (str?: string) => str
|
|
7
8
|
let baseUrl = getString(__BASE_URL__)
|
|
9
|
+
const appDir = getAppDir()
|
|
8
10
|
|
|
9
11
|
const app = createApp({
|
|
10
12
|
setup,
|
|
11
13
|
appDir,
|
|
12
|
-
baseUrl
|
|
14
|
+
baseUrl,
|
|
15
|
+
ssrFunctions
|
|
13
16
|
})
|
|
14
17
|
|
|
15
18
|
app.listen(process.env.PORT || 3000, process.env.HOST || '127.0.0.1')
|