@monkeyplus/flow 5.0.0-rc.199 → 5.0.0-rc.2
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/build.config.ts +25 -0
- package/dist/app/entry.d.ts +2 -2
- package/dist/app/entry.mjs +2 -3
- package/dist/app/flow.d.ts +3 -12
- package/dist/app/flow.mjs +0 -3
- package/dist/core/runtime/nitro/flow.d.ts +0 -1
- package/dist/core/runtime/nitro/flow.mjs +14 -9
- package/dist/core/runtime/nitro/renderer.mjs +18 -82
- package/dist/head/runtime/plugin.mjs +1 -0
- package/dist/index.mjs +772 -543
- package/dist/pages/runtime/helpers/index.d.ts +1 -1
- package/dist/pages/runtime/helpers/index.mjs +3 -14
- package/dist/pages/runtime/index.d.ts +3 -10
- package/dist/pages/runtime/index.mjs +4 -12
- package/dist/pages/runtime/plugin.mjs +53 -0
- package/dist/vite-client/runtime/injectManifest.d.ts +26 -0
- package/dist/vite-client/runtime/injectManifest.mjs +104 -0
- package/dist/vite-client/runtime/plugin.d.ts +2 -0
- package/dist/vite-client/runtime/plugin.mjs +27 -0
- package/package.json +40 -55
- package/src/app/composables/index.ts +20 -0
- package/src/app/entry.ts +36 -0
- package/src/app/flow.ts +157 -0
- package/src/app/index.ts +5 -0
- package/src/auto-imports/module.ts +143 -0
- package/src/auto-imports/presets.ts +49 -0
- package/src/auto-imports/transform.ts +48 -0
- package/src/core/app.ts +90 -0
- package/src/core/builder.ts +60 -0
- package/src/core/flow.ts +93 -0
- package/src/core/modules.ts +32 -0
- package/src/core/nitro.ts +206 -0
- package/src/core/plugins/import-protection.ts +49 -0
- package/src/core/plugins/unctx.ts +31 -0
- package/src/core/runtime/nitro/flow.ts +43 -0
- package/src/core/runtime/nitro/paths.ts +20 -0
- package/src/core/runtime/nitro/renderer.ts +74 -0
- package/src/core/templates.ts +119 -0
- package/src/core/vite/builder/css.ts +28 -0
- package/src/core/vite/builder/dev-bundler.ts +248 -0
- package/src/core/vite/builder/index.ts +96 -0
- package/src/core/vite/builder/manifest.ts +33 -0
- package/src/core/vite/builder/plugins/analyze.ts +32 -0
- package/src/core/vite/builder/plugins/cache-dir.ts +13 -0
- package/src/core/vite/builder/plugins/dynamic-base.ts +64 -0
- package/src/core/vite/builder/plugins/virtual.ts +45 -0
- package/src/core/vite/builder/server.ts +164 -0
- package/src/core/vite/builder/types/index.ts +13 -0
- package/src/core/vite/builder/utils/index.ts +53 -0
- package/src/core/vite/builder/utils/warmup.ts +27 -0
- package/src/core/vite/builder/utils/wpfs.ts +7 -0
- package/src/core/vite/builder/vite-node.ts +110 -0
- package/src/core/vite/client/index.ts +63 -0
- package/src/dirs.ts +8 -0
- package/src/head/module.ts +37 -0
- package/src/head/runtime/composables.ts +16 -0
- package/src/head/runtime/index.ts +1 -0
- package/src/head/runtime/plugin.ts +12 -0
- package/src/index.ts +2 -0
- package/src/pages/module.ts +55 -0
- package/src/pages/runtime/helpers/chunks.ts +0 -0
- package/src/pages/runtime/helpers/index.ts +33 -0
- package/src/pages/runtime/index.ts +9 -0
- package/src/pages/runtime/plugin.ts +65 -0
- package/src/pages/templates.ts +20 -0
- package/src/pages/utils.ts +49 -0
- package/src/vite-client/module.ts +84 -0
- package/src/vite-client/runtime/injectManifest.ts +188 -0
- package/src/vite-client/runtime/plugin.ts +33 -0
- package/dist/app/entry.async.d.ts +0 -3
- package/dist/app/entry.async.mjs +0 -1
- package/dist/chunks/dev-bundler.mjs +0 -277
- package/dist/core/runtime/client.manifest.d.mts +0 -2
- package/dist/core/runtime/client.manifest.mjs +0 -6
- package/dist/core/runtime/vite-node-shared.d.mts +0 -1
- package/dist/core/runtime/vite-node-shared.d.ts +0 -8
- package/dist/core/runtime/vite-node-shared.mjs +0 -3
- package/dist/core/runtime/vite-node.d.mts +0 -2
- package/dist/core/runtime/vite-node.mjs +0 -41
- package/dist/pages/runtime/pages.mjs +0 -123
- /package/dist/pages/runtime/{pages.d.ts → plugin.d.ts} +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { join, normalize, resolve } from 'pathe';
|
|
2
|
+
import * as vite from 'vite';
|
|
3
|
+
import fse from 'fs-extra';
|
|
4
|
+
import { withoutTrailingSlash } from 'ufo';
|
|
5
|
+
import { logger } from '@monkeyplus/flow-kit';
|
|
6
|
+
import { debounce } from 'perfect-debounce';
|
|
7
|
+
import { cacheDirPlugin } from './plugins/cache-dir';
|
|
8
|
+
import type { ViteBuildContext, ViteOptions } from './types';
|
|
9
|
+
import { wpfs } from './utils/wpfs';
|
|
10
|
+
import { bundleRequest } from './dev-bundler';
|
|
11
|
+
import { writeManifest } from './manifest';
|
|
12
|
+
import { isCSS, isDirectory, readDirRecursively } from './utils';
|
|
13
|
+
|
|
14
|
+
export const buildServer = async(ctx: ViteBuildContext) => {
|
|
15
|
+
// const _resolve = (id: string) => resolveModule(id, { paths: ctx.flow.options.modulesDir });
|
|
16
|
+
|
|
17
|
+
const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
|
|
18
|
+
configFile: false,
|
|
19
|
+
define: {
|
|
20
|
+
'process.server': true,
|
|
21
|
+
'typeof window': '"undefined"',
|
|
22
|
+
'typeof document': '"undefined"',
|
|
23
|
+
'typeof navigator': '"undefined"',
|
|
24
|
+
'typeof location': '"undefined"',
|
|
25
|
+
'typeof XMLHttpRequest': '"undefined"',
|
|
26
|
+
},
|
|
27
|
+
ssr: {
|
|
28
|
+
noExternal: [
|
|
29
|
+
...ctx.flow.options.build.transpile,
|
|
30
|
+
// TODO: Use externality for production (rollup) build
|
|
31
|
+
/\/esm\/.*\.js$/,
|
|
32
|
+
/\.(es|esm|esm-browser|esm-bundler).js$/,
|
|
33
|
+
'/__vue-jsx',
|
|
34
|
+
'#app',
|
|
35
|
+
/(nuxt|nuxt3)\/(dist|src|app)/,
|
|
36
|
+
/@monkeyplus\/flow\/(dist|src|app)/,
|
|
37
|
+
/@nuxt\/nitro\/(dist|src)/,
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
build: {
|
|
41
|
+
outDir: resolve(ctx.flow.options.buildDir, 'dist/server'),
|
|
42
|
+
manifest: true,
|
|
43
|
+
rollupOptions: {
|
|
44
|
+
external: ['#internal/nitro'],
|
|
45
|
+
output: {
|
|
46
|
+
entryFileNames: 'server.mjs',
|
|
47
|
+
preferConst: true,
|
|
48
|
+
format: 'module',
|
|
49
|
+
},
|
|
50
|
+
onwarn(warning, rollupWarn) {
|
|
51
|
+
if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code))
|
|
52
|
+
rollupWarn(warning);
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
server: {
|
|
57
|
+
// https://github.com/vitest-dev/vitest/issues/229#issuecomment-1002685027
|
|
58
|
+
preTransformRequests: false,
|
|
59
|
+
cors: true,
|
|
60
|
+
},
|
|
61
|
+
plugins: [
|
|
62
|
+
cacheDirPlugin(ctx.flow.options.rootDir, 'server'),
|
|
63
|
+
],
|
|
64
|
+
} as ViteOptions);
|
|
65
|
+
|
|
66
|
+
await ctx.flow.callHook('vite:extendConfig', serverConfig, { isClient: false, isServer: true });
|
|
67
|
+
|
|
68
|
+
ctx.flow.hook('nitro:build:before', async() => {
|
|
69
|
+
if (ctx.flow.options.dev)
|
|
70
|
+
return;
|
|
71
|
+
|
|
72
|
+
const clientDist = resolve(ctx.flow.options.buildDir, 'dist/client');
|
|
73
|
+
|
|
74
|
+
// Remove public files that have been duplicated into buildAssetsDir
|
|
75
|
+
// TODO: Add option to configure this behavior in vite
|
|
76
|
+
const publicDir = join(ctx.flow.options.srcDir, ctx.flow.options.dir.public);
|
|
77
|
+
let publicFiles: string[] = [];
|
|
78
|
+
if (await isDirectory(publicDir)) {
|
|
79
|
+
publicFiles = readDirRecursively(publicDir).map((r) => r.replace(publicDir, ''));
|
|
80
|
+
for (const file of publicFiles) {
|
|
81
|
+
try {
|
|
82
|
+
fse.rmSync(join(clientDist, file));
|
|
83
|
+
}
|
|
84
|
+
catch {}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Copy doubly-nested /_nuxt/_nuxt files into buildAssetsDir
|
|
89
|
+
// TODO: Workaround vite issue
|
|
90
|
+
if (await isDirectory(clientDist)) {
|
|
91
|
+
const nestedAssetsPath = withoutTrailingSlash(join(clientDist, ctx.flow.options.app.buildAssetsDir));
|
|
92
|
+
|
|
93
|
+
if (await isDirectory(nestedAssetsPath)) {
|
|
94
|
+
await fse.copy(nestedAssetsPath, clientDist, { recursive: true });
|
|
95
|
+
await fse.remove(nestedAssetsPath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const onBuild = () => ctx.flow.callHook('build:resources', wpfs);
|
|
101
|
+
|
|
102
|
+
// Production build
|
|
103
|
+
if (!ctx.flow.options.dev) {
|
|
104
|
+
const start = Date.now();
|
|
105
|
+
logger.info('Building server...');
|
|
106
|
+
await vite.build(serverConfig);
|
|
107
|
+
await onBuild();
|
|
108
|
+
logger.success(`Server built in ${Date.now() - start}ms`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// if (!ctx.flow.options.ssr) {
|
|
113
|
+
// await onBuild();
|
|
114
|
+
// return;
|
|
115
|
+
// }
|
|
116
|
+
// console.log(serverConfig.plugins);
|
|
117
|
+
|
|
118
|
+
// Start development server
|
|
119
|
+
const viteServer = await vite.createServer(serverConfig);
|
|
120
|
+
ctx.ssrServer = viteServer;
|
|
121
|
+
|
|
122
|
+
await ctx.flow.callHook('vite:serverCreated', viteServer, { isClient: false, isServer: true });
|
|
123
|
+
|
|
124
|
+
// Close server on exit
|
|
125
|
+
ctx.flow.hook('close', () => viteServer.close());
|
|
126
|
+
|
|
127
|
+
// Initialize plugins
|
|
128
|
+
await viteServer.pluginContainer.buildStart({});
|
|
129
|
+
// console.log(viteServer.1);
|
|
130
|
+
|
|
131
|
+
// if (ctx.flow.options.experimental.viteNode) {
|
|
132
|
+
// logger.info('Vite server using experimental `vite-node`...');
|
|
133
|
+
// await prepareDevServerEntry(ctx);
|
|
134
|
+
// }
|
|
135
|
+
// else {
|
|
136
|
+
// Build and watch
|
|
137
|
+
const _doBuild = async() => {
|
|
138
|
+
const start = Date.now();
|
|
139
|
+
const { code, ids } = await bundleRequest({ viteServer }, resolve(ctx.flow.options.appDir, 'entry'));
|
|
140
|
+
await fse.ensureFile(resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'));
|
|
141
|
+
await fse.writeFile(resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'), code, 'utf-8');
|
|
142
|
+
// Have CSS in the manifest to prevent FOUC on dev SSR
|
|
143
|
+
await writeManifest(ctx, ids.filter(isCSS).map((i) => i.slice(1)));
|
|
144
|
+
const time = (Date.now() - start);
|
|
145
|
+
logger.success(`Vite server built in ${time}ms`);
|
|
146
|
+
await onBuild();
|
|
147
|
+
ctx.flow.callHook('bundler:change', {} as any);
|
|
148
|
+
};
|
|
149
|
+
const doBuild = debounce(_doBuild);
|
|
150
|
+
|
|
151
|
+
// Initial build
|
|
152
|
+
await _doBuild();
|
|
153
|
+
|
|
154
|
+
// Watch
|
|
155
|
+
viteServer.watcher.on('all', (_event, file) => {
|
|
156
|
+
file = normalize(file); // Fix windows paths
|
|
157
|
+
if (file.indexOf(ctx.flow.options.buildDir) === 0) return;
|
|
158
|
+
doBuild();
|
|
159
|
+
});
|
|
160
|
+
ctx.flow.hook('app:templatesGenerated', () => doBuild());
|
|
161
|
+
|
|
162
|
+
// ctx.nuxt.hook('builder:watch', () => doBuild())
|
|
163
|
+
// }
|
|
164
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InlineConfig, SSROptions, ViteDevServer } from 'vite';
|
|
2
|
+
import type { Flow, Nuxt } from '@monkeyplus/flow-schema';
|
|
3
|
+
|
|
4
|
+
export interface ViteOptions extends InlineConfig {
|
|
5
|
+
ssr?: SSROptions
|
|
6
|
+
}
|
|
7
|
+
export interface ViteBuildContext {
|
|
8
|
+
flow: Flow
|
|
9
|
+
nuxt: Nuxt
|
|
10
|
+
config: ViteOptions
|
|
11
|
+
// clientServer?: ViteDevServer
|
|
12
|
+
ssrServer?: ViteDevServer
|
|
13
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { promises as fsp, readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { join } from 'pathe';
|
|
4
|
+
|
|
5
|
+
export function uniq<T>(arr: T[]): T[] {
|
|
6
|
+
return Array.from(new Set(arr));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Copied from vue-bundle-renderer utils
|
|
10
|
+
const IS_JS_RE = /\.[cm]?js(\?[^.]+)?$/;
|
|
11
|
+
const IS_MODULE_RE = /\.mjs(\?[^.]+)?$/;
|
|
12
|
+
const HAS_EXT_RE = /[^./]+\.[^./]+$/;
|
|
13
|
+
const IS_CSS_RE = /\.(?:css|scss|sass|postcss|less|stylus|styl)(\?[^.]+)?$/;
|
|
14
|
+
|
|
15
|
+
export function isJS(file: string) {
|
|
16
|
+
return IS_JS_RE.test(file) || !HAS_EXT_RE.test(file);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isModule(file: string) {
|
|
20
|
+
return IS_MODULE_RE.test(file) || !HAS_EXT_RE.test(file);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isCSS(file: string) {
|
|
24
|
+
return IS_CSS_RE.test(file);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function hashId(id: string) {
|
|
28
|
+
return `$id_${hash(id)}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function hash(input: string, length = 8) {
|
|
32
|
+
return createHash('sha256')
|
|
33
|
+
.update(input)
|
|
34
|
+
.digest('hex')
|
|
35
|
+
.slice(0, length);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function readDirRecursively(dir: string) {
|
|
39
|
+
return readdirSync(dir).reduce((files, file) => {
|
|
40
|
+
const name = join(dir, file);
|
|
41
|
+
const isDirectory = statSync(name).isDirectory();
|
|
42
|
+
return isDirectory ? [...files, ...readDirRecursively(name)] : [...files, name];
|
|
43
|
+
}, []);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function isDirectory(path: string) {
|
|
47
|
+
try {
|
|
48
|
+
return (await fsp.stat(path)).isDirectory();
|
|
49
|
+
}
|
|
50
|
+
catch (_err) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { logger } from '@monkeyplus/flow-kit';
|
|
2
|
+
import type { ViteDevServer } from 'vite';
|
|
3
|
+
|
|
4
|
+
export async function warmupViteServer(
|
|
5
|
+
server: ViteDevServer,
|
|
6
|
+
entries: string[],
|
|
7
|
+
) {
|
|
8
|
+
const warmedUrls = new Set<String>();
|
|
9
|
+
|
|
10
|
+
const warmup = async(url: string) => {
|
|
11
|
+
if (warmedUrls.has(url))
|
|
12
|
+
return;
|
|
13
|
+
|
|
14
|
+
warmedUrls.add(url);
|
|
15
|
+
try {
|
|
16
|
+
await server.transformRequest(url);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
logger.debug('Warmup for %s failed with: %s', url, e);
|
|
20
|
+
}
|
|
21
|
+
const mod = await server.moduleGraph.getModuleByUrl(url);
|
|
22
|
+
const deps = Array.from(mod?.importedModules || []);
|
|
23
|
+
await Promise.all(deps.map((m) => warmup(m.url.replace('/@id/__x00__', '\0'))));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
await Promise.all(entries.map((entry) => warmup(entry)));
|
|
27
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// import { createApp, createError, defineEventHandler, defineLazyEventHandler } from 'h3';
|
|
2
|
+
// import { ViteNodeServer } from 'vite-node/server';
|
|
3
|
+
import fse from 'fs-extra';
|
|
4
|
+
import { resolve } from 'pathe';
|
|
5
|
+
import { distDir } from '../../../dirs';
|
|
6
|
+
import type { ViteBuildContext } from './types';
|
|
7
|
+
// import { addServerMiddleware } from '@nuxt/kit';
|
|
8
|
+
// import type { ViteDevServer, Plugin as VitePlugin } from 'vite';
|
|
9
|
+
// import { distDir } from './dirs';
|
|
10
|
+
// import type { ViteBuildContext } from './vite';
|
|
11
|
+
// import { isCSS } from './utils';
|
|
12
|
+
|
|
13
|
+
// // TODO: Remove this in favor of registerViteNodeMiddleware
|
|
14
|
+
// // after Nitropack or h3 fixed for adding middlewares after setup
|
|
15
|
+
// export function viteNodePlugin(ctx: ViteBuildContext): VitePlugin {
|
|
16
|
+
// return {
|
|
17
|
+
// name: 'nuxt:vite-node-server',
|
|
18
|
+
// enforce: 'pre',
|
|
19
|
+
// configureServer(server) {
|
|
20
|
+
// server.middlewares.use('/__nuxt_vite_node__', createViteNodeMiddleware(ctx));
|
|
21
|
+
// },
|
|
22
|
+
// };
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
// export function registerViteNodeMiddleware(ctx: ViteBuildContext) {
|
|
26
|
+
// addServerMiddleware({
|
|
27
|
+
// route: '/__nuxt_vite_node__/',
|
|
28
|
+
// handler: createViteNodeMiddleware(ctx),
|
|
29
|
+
// });
|
|
30
|
+
// }
|
|
31
|
+
|
|
32
|
+
// function getManifest(server: ViteDevServer) {
|
|
33
|
+
// const ids = Array.from(server.moduleGraph.urlToModuleMap.keys())
|
|
34
|
+
// .filter((i) => isCSS(i));
|
|
35
|
+
|
|
36
|
+
// const entries = [
|
|
37
|
+
// '@vite/client',
|
|
38
|
+
// 'entry.mjs',
|
|
39
|
+
// ...ids.map((i) => i.slice(1)),
|
|
40
|
+
// ];
|
|
41
|
+
|
|
42
|
+
// return {
|
|
43
|
+
// publicPath: '',
|
|
44
|
+
// all: entries,
|
|
45
|
+
// initial: entries,
|
|
46
|
+
// async: [],
|
|
47
|
+
// modules: {},
|
|
48
|
+
// };
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
// function createViteNodeMiddleware(ctx: ViteBuildContext) {
|
|
52
|
+
// const app = createApp();
|
|
53
|
+
|
|
54
|
+
// app.use('/manifest', defineEventHandler(async() => {
|
|
55
|
+
// const manifest = await getManifest(ctx.ssrServer);
|
|
56
|
+
// return manifest;
|
|
57
|
+
// }));
|
|
58
|
+
|
|
59
|
+
// app.use('/module', defineLazyEventHandler(() => {
|
|
60
|
+
// const node: ViteNodeServer = new ViteNodeServer(ctx.ssrServer, {
|
|
61
|
+
// deps: {
|
|
62
|
+
// inline: [
|
|
63
|
+
// /\/(nuxt|nuxt3)\//,
|
|
64
|
+
// /^#/,
|
|
65
|
+
// ...ctx.nuxt.options.build.transpile as string[],
|
|
66
|
+
// ],
|
|
67
|
+
// },
|
|
68
|
+
// });
|
|
69
|
+
// return async(event) => {
|
|
70
|
+
// const moduleId = decodeURI(event.req.url).substring(1);
|
|
71
|
+
// if (moduleId === '/')
|
|
72
|
+
// throw createError({ statusCode: 400 });
|
|
73
|
+
|
|
74
|
+
// const module = await node.fetchModule(moduleId) as any;
|
|
75
|
+
// return module;
|
|
76
|
+
// };
|
|
77
|
+
// }));
|
|
78
|
+
|
|
79
|
+
// return app.nodeHandler;
|
|
80
|
+
// }
|
|
81
|
+
|
|
82
|
+
export async function prepareDevServerEntry(ctx: ViteBuildContext) {
|
|
83
|
+
let entryPath = resolve(ctx.flow.options.appDir, 'entry.async.mjs');
|
|
84
|
+
if (!fse.existsSync(entryPath))
|
|
85
|
+
entryPath = resolve(ctx.flow.options.appDir, 'entry.async');
|
|
86
|
+
|
|
87
|
+
// TODO: Update me
|
|
88
|
+
const host = ctx.flow.options.server.host || 'localhost';
|
|
89
|
+
const port = ctx.flow.options.server.port || '3000';
|
|
90
|
+
const protocol = ctx.flow.options.server.https ? 'https' : 'http';
|
|
91
|
+
|
|
92
|
+
// Serialize and pass vite-node runtime options
|
|
93
|
+
const viteNodeServerOptions = {
|
|
94
|
+
baseURL: `${protocol}://${host}:${port}/__flow_vite_node__`,
|
|
95
|
+
rootDir: ctx.flow.options.rootDir,
|
|
96
|
+
entryPath,
|
|
97
|
+
base: '/_flow/',
|
|
98
|
+
// base: ctx.ssrServer.config.base || '/_nuxt/',
|
|
99
|
+
};
|
|
100
|
+
process.env.FLOW_VITE_NODE_OPTIONS = JSON.stringify(viteNodeServerOptions);
|
|
101
|
+
|
|
102
|
+
await fse.writeFile(
|
|
103
|
+
resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'),
|
|
104
|
+
`export { default } from ${JSON.stringify(resolve(distDir, 'runtime/vite-node.mjs'))}`,
|
|
105
|
+
);
|
|
106
|
+
await fse.writeFile(
|
|
107
|
+
resolve(ctx.flow.options.buildDir, 'dist/server/client.manifest.mjs'),
|
|
108
|
+
`export { default } from ${JSON.stringify(resolve(distDir, 'runtime/client.manifest.mjs'))}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolve } from 'pathe';
|
|
2
|
+
import type { Flow } from '@monkeyplus/flow-schema';
|
|
3
|
+
import type { ViteDevServer } from 'vite';
|
|
4
|
+
import { build, createServer } from 'vite';
|
|
5
|
+
import { debounce } from 'perfect-debounce';
|
|
6
|
+
|
|
7
|
+
export const createClient = async(flow: Flow) => {
|
|
8
|
+
let vite: ViteDevServer;
|
|
9
|
+
if (globalThis.viteClient) {
|
|
10
|
+
vite = globalThis.viteClient as ViteDevServer;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
vite = await createServer({
|
|
14
|
+
root: resolve(flow.options.rootDir),
|
|
15
|
+
base: '/_vite/',
|
|
16
|
+
build: {
|
|
17
|
+
manifest: true,
|
|
18
|
+
},
|
|
19
|
+
server: {
|
|
20
|
+
watch: {
|
|
21
|
+
ignored: ['**/.env/**', '**/.env*'],
|
|
22
|
+
},
|
|
23
|
+
middlewareMode: 'ssr',
|
|
24
|
+
//
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
globalThis.viteClient = vite;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const _doReload = () => {
|
|
31
|
+
if (vite)
|
|
32
|
+
vite?.ws?.send({ type: 'full-reload' });
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const doReload = debounce(_doReload, 60);
|
|
36
|
+
|
|
37
|
+
// Use this to refresh page
|
|
38
|
+
flow.hook('bundler:change', () => {
|
|
39
|
+
doReload();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
flow.hook('close', async() => {
|
|
43
|
+
vite.restart();
|
|
44
|
+
// await vite.close();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return vite;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const builClient = async(flow: Flow) => {
|
|
51
|
+
return await build({
|
|
52
|
+
root: flow.options.rootDir,
|
|
53
|
+
mode: 'production',
|
|
54
|
+
build: {
|
|
55
|
+
assetsDir: 'scripts',
|
|
56
|
+
target: 'es2017',
|
|
57
|
+
outDir: '.vite',
|
|
58
|
+
manifest: true,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// export default await runVite();
|
package/src/dirs.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { dirname, resolve } from 'pathe';
|
|
3
|
+
|
|
4
|
+
let _distDir = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
if (_distDir.endsWith('chunks')) _distDir = dirname(_distDir);
|
|
6
|
+
export const distDir = _distDir;
|
|
7
|
+
export const pkgDir = resolve(distDir, '..');
|
|
8
|
+
export const runtimeDir = resolve(distDir, 'runtime');
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { addPlugin, defineFlowModule } from '@monkeyplus/flow-kit';
|
|
2
|
+
import { resolve } from 'pathe';
|
|
3
|
+
import type { FlowModule } from '@monkeyplus/flow-schema';
|
|
4
|
+
|
|
5
|
+
import { distDir } from '../dirs';
|
|
6
|
+
|
|
7
|
+
export default defineFlowModule({
|
|
8
|
+
meta: {
|
|
9
|
+
name: 'meta',
|
|
10
|
+
},
|
|
11
|
+
defaults: {
|
|
12
|
+
charset: 'utf-8',
|
|
13
|
+
viewport: 'width=device-width, initial-scale=1',
|
|
14
|
+
},
|
|
15
|
+
setup(options, flow) {
|
|
16
|
+
const runtimeDir = flow.options.alias['#head'] || resolve(distDir, 'head/runtime');
|
|
17
|
+
// Transpile @nuxt/meta and @vueuse/head
|
|
18
|
+
// flow.options.build.transpile.push('@vueuse/head');
|
|
19
|
+
|
|
20
|
+
flow.options.alias['#head'] = runtimeDir;
|
|
21
|
+
|
|
22
|
+
// Global meta -for Bridge, this is necessary to repeat here
|
|
23
|
+
// and in packages/schema/src/config/_app.ts
|
|
24
|
+
// const globalMeta: any = defu(flow.options.app.head, {
|
|
25
|
+
// charset: options.charset,
|
|
26
|
+
// viewport: options.viewport,
|
|
27
|
+
// });
|
|
28
|
+
|
|
29
|
+
// // Add global meta configuration
|
|
30
|
+
// addTemplate({
|
|
31
|
+
// filename: 'meta.config.mjs',
|
|
32
|
+
// getContents: () => `export default ${JSON.stringify({ globalMeta })}`,
|
|
33
|
+
// });
|
|
34
|
+
// Add generic plugin
|
|
35
|
+
addPlugin({ src: resolve(runtimeDir, 'plugin') });
|
|
36
|
+
},
|
|
37
|
+
}) as FlowModule<any>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import type { MetaObject } from '@monkeyplus/flow-schema';
|
|
3
|
+
/**
|
|
4
|
+
* You can pass in a meta object, which has keys corresponding to meta tags:
|
|
5
|
+
* `title`, `base`, `script`, `style`, `meta` and `link`, as well as `htmlAttrs` and `bodyAttrs`.
|
|
6
|
+
*
|
|
7
|
+
* Alternatively, for reactive meta state, you can pass in a function
|
|
8
|
+
* that returns a meta object.
|
|
9
|
+
*/
|
|
10
|
+
// TODO: fake use Head
|
|
11
|
+
export function useHead(meta: MetaObject) {
|
|
12
|
+
// console.log('meta', meta);
|
|
13
|
+
|
|
14
|
+
// const resolvedMeta = isFunction(meta) ? computed(meta) : meta;
|
|
15
|
+
// useFlowApp()._useHead(resolvedMeta);
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './composables';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
import { defineFlowPlugin } from '#app';
|
|
3
|
+
|
|
4
|
+
export default defineFlowPlugin((flow) => {
|
|
5
|
+
// console.log('Pages plugin');
|
|
6
|
+
// flow.hook('page:scripts', (scripts) => {
|
|
7
|
+
// scripts.head.push('');
|
|
8
|
+
// });
|
|
9
|
+
flow._useHead = (_meta: any) => {
|
|
10
|
+
console.log(_meta);
|
|
11
|
+
};
|
|
12
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { addPlugin, addTemplate, defineNuxtModule } from '@monkeyplus/flow-kit';
|
|
2
|
+
import { resolve } from 'pathe';
|
|
3
|
+
import escapeRE from 'escape-string-regexp';
|
|
4
|
+
import type { FlowModule } from '@monkeyplus/flow-schema';
|
|
5
|
+
import { distDir } from '../dirs';
|
|
6
|
+
import type{ Pages } from './utils';
|
|
7
|
+
import { normalizePages, resolvePagesRoutes } from './utils';
|
|
8
|
+
import { pagesTypeTemplate } from './templates';
|
|
9
|
+
export default defineNuxtModule({
|
|
10
|
+
meta: {
|
|
11
|
+
name: 'pages',
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
async setup(_options, flow) {
|
|
15
|
+
const runtimeDir = resolve(distDir, 'pages/runtime');
|
|
16
|
+
// flow.options.alias['#pages'] = runtimeDir;
|
|
17
|
+
const pages: Pages[] = [];
|
|
18
|
+
// Regenerate templates when adding or removing pages
|
|
19
|
+
flow.hook('builder:watch', async(event, path) => {
|
|
20
|
+
const dirs = [
|
|
21
|
+
flow.options.dir.pages,
|
|
22
|
+
flow.options.dir.layouts,
|
|
23
|
+
flow.options.dir.middleware,
|
|
24
|
+
].filter(Boolean);
|
|
25
|
+
|
|
26
|
+
const pathPattern = new RegExp(`^(${dirs.map(escapeRE).join('|')})/`);
|
|
27
|
+
if (event !== 'change' && path.match(pathPattern))
|
|
28
|
+
await flow.callHook('builder:generateApp');
|
|
29
|
+
});
|
|
30
|
+
const options = { pages, buildDir: flow.options.buildDir };
|
|
31
|
+
addTemplate({
|
|
32
|
+
...pagesTypeTemplate,
|
|
33
|
+
options,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
flow.options.alias['#pages'] = resolve(flow.options.buildDir, 'pages.mjs');
|
|
37
|
+
addTemplate({
|
|
38
|
+
filename: 'pages.mjs',
|
|
39
|
+
async getContents({ options }) {
|
|
40
|
+
const { exports, imports } = normalizePages(options.pages);
|
|
41
|
+
return [imports, `export default {${exports}}`].join('\n');
|
|
42
|
+
},
|
|
43
|
+
options,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
flow.hook('app:templates', async() => {
|
|
47
|
+
options.pages = await resolvePagesRoutes();
|
|
48
|
+
});
|
|
49
|
+
flow.hook('prepare:types', ({ references }) => {
|
|
50
|
+
references.push({ path: resolve(flow.options.buildDir, 'pages.d.ts') });
|
|
51
|
+
});
|
|
52
|
+
// Add generic plugin
|
|
53
|
+
addPlugin({ src: resolve(runtimeDir, 'plugin') });
|
|
54
|
+
},
|
|
55
|
+
}) as FlowModule<any>;
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { GetPages, PageDefinition } from '@monkeyplus/flow-schema';
|
|
2
|
+
import { joinURL, withTrailingSlash } from 'ufo';
|
|
3
|
+
|
|
4
|
+
const buildPages = (page: PageDefinition): GetPages => (location: string, language: string) => {
|
|
5
|
+
const locales = Object.entries(page.locales);
|
|
6
|
+
return locales.map(([locale, localePage]) => {
|
|
7
|
+
const [_language, _location] = locale.split('-');
|
|
8
|
+
const name = joinURL('/', _location, _language, page.name);
|
|
9
|
+
const defLocation = _location === location ? '' : _location;
|
|
10
|
+
const defLanguage = _language === language ? '' : _language;
|
|
11
|
+
const url = joinURL('/', defLocation, defLanguage, localePage.url);
|
|
12
|
+
const _locale = {
|
|
13
|
+
lang: _language,
|
|
14
|
+
loc: _location,
|
|
15
|
+
code: locale,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const path = localePage.url.endsWith('/') ? withTrailingSlash(url) : url;
|
|
19
|
+
return {
|
|
20
|
+
name,
|
|
21
|
+
url: path,
|
|
22
|
+
context: { page: localePage, locale: _locale, path, view: page.view, name: page.name },
|
|
23
|
+
// locale: _locale,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function definePage(page: PageDefinition) {
|
|
29
|
+
return {
|
|
30
|
+
pages: [],
|
|
31
|
+
getPages: buildPages(page),
|
|
32
|
+
};
|
|
33
|
+
}
|