@depup/nuxt 4.3.0-depup.0 → 4.4.2-depup.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/README.md +24 -107
- package/dist/app/components/nuxt-announcer.d.ts +26 -0
- package/dist/app/components/nuxt-announcer.js +59 -0
- package/dist/app/components/nuxt-island.js +7 -1
- package/dist/app/components/nuxt-layout.js +44 -21
- package/dist/app/components/nuxt-link.js +29 -15
- package/dist/app/components/nuxt-root.vue +1 -1
- package/dist/app/components/nuxt-route-announcer.js +11 -2
- package/dist/app/components/nuxt-time.vue +13 -2
- package/dist/app/components/test-component-wrapper.js +10 -2
- package/dist/app/components/utils.d.ts +7 -1
- package/dist/app/components/utils.js +18 -0
- package/dist/app/components/welcome.vue +1 -1
- package/dist/app/composables/announcer.d.ts +23 -0
- package/dist/app/composables/announcer.js +47 -0
- package/dist/app/composables/asyncData.d.ts +18 -36
- package/dist/app/composables/asyncData.js +214 -186
- package/dist/app/composables/chunk.js +1 -2
- package/dist/app/composables/cookie.d.ts +14 -0
- package/dist/app/composables/cookie.js +66 -17
- package/dist/app/composables/error.d.ts +2 -2
- package/dist/app/composables/error.js +11 -1
- package/dist/app/composables/fetch.d.ts +11 -16
- package/dist/app/composables/fetch.js +79 -76
- package/dist/app/composables/index.d.ts +2 -0
- package/dist/app/composables/index.js +1 -0
- package/dist/app/composables/manifest.d.ts +1 -1
- package/dist/app/composables/manifest.js +1 -4
- package/dist/app/composables/pages.d.ts +2 -0
- package/dist/app/composables/pages.js +1 -0
- package/dist/app/composables/payload.js +14 -5
- package/dist/app/composables/preload.js +1 -1
- package/dist/app/composables/route-announcer.d.ts +2 -2
- package/dist/app/composables/route-announcer.js +6 -6
- package/dist/app/composables/router.d.ts +7 -0
- package/dist/app/composables/router.js +8 -3
- package/dist/app/composables/ssr.d.ts +1 -1
- package/dist/app/composables/ssr.js +1 -1
- package/dist/app/composables/state.d.ts +11 -1
- package/dist/app/composables/state.js +11 -2
- package/dist/app/composables/url.d.ts +1 -1
- package/dist/app/composables/url.js +1 -1
- package/dist/app/config.d.ts +1 -2
- package/dist/app/index.d.ts +2 -2
- package/dist/app/index.js +1 -1
- package/dist/app/nuxt.d.ts +46 -31
- package/dist/app/nuxt.js +6 -2
- package/dist/app/plugins/restore-state.client.js +1 -2
- package/dist/app/plugins/revive-payload.client.js +9 -3
- package/dist/app/plugins/router.js +2 -2
- package/dist/app/plugins/view-transitions.client.js +39 -4
- package/dist/compiler/runtime/index.d.ts +14 -0
- package/dist/compiler/runtime/index.js +14 -0
- package/dist/index.mjs +2592 -1365
- package/dist/pages/runtime/page.js +11 -21
- package/dist/pages/runtime/plugins/router.js +20 -8
- package/dist/pages/runtime/router.options.js +12 -6
- package/meta.js +2 -1
- package/package.json +77 -37
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import fs, { statSync, promises, existsSync, readdirSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { mkdir, readFile, readdir, writeFile,
|
|
3
|
+
import { mkdir, readFile, readdir, writeFile, stat, unlink, open, rm } from 'node:fs/promises';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
5
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
6
|
-
import { dirname, resolve, normalize, basename, extname, relative,
|
|
6
|
+
import { dirname, resolve, normalize, basename, extname, relative, join, isAbsolute, parse as parse$1 } from 'pathe';
|
|
7
7
|
import { createHooks, createDebugger } from 'hookable';
|
|
8
8
|
import ignore from 'ignore';
|
|
9
|
-
import { useLogger, tryUseNuxt, useNuxt, directoryToURL, getLayerDirectories, resolveFiles, resolvePath, defineNuxtModule, findPath, addPlugin, addTemplate, addTypeTemplate, addComponent, useNitro, addBuildPlugin,
|
|
9
|
+
import { useLogger, tryUseNuxt, useNuxt, directoryToURL, getLayerDirectories, resolveFiles, resolvePath, defineNuxtModule, findPath, addPlugin, addTemplate, addTypeTemplate, addComponent, isIgnored, useNitro, addBuildPlugin, resolveAlias as resolveAlias$1, addPluginTemplate, addImportsSources, addVitePlugin, createIsIgnored, updateTemplates, tryResolveModule, normalizeModuleTranspilePath, importModule, createResolver, runWithNuxtContext, nuxtCtx, loadNuxtConfig, installModules, resolveIgnorePatterns, addRouteMiddleware, resolveModuleWithOptions, normalizeTemplate, normalizePlugin } from '@nuxt/kit';
|
|
10
10
|
import { resolvePackageJSON, readPackage, readPackageJSON } from 'pkg-types';
|
|
11
11
|
import { hash, isEqual, serialize } from 'ohash';
|
|
12
12
|
import { consola } from 'consola';
|
|
@@ -14,24 +14,25 @@ import onChange from 'on-change';
|
|
|
14
14
|
import { colors } from 'consola/utils';
|
|
15
15
|
import { resolveCompatibilityDatesFromEnv, formatDate } from 'compatx';
|
|
16
16
|
import escapeRE from 'escape-string-regexp';
|
|
17
|
-
import { withTrailingSlash as withTrailingSlash$1,
|
|
17
|
+
import { withTrailingSlash as withTrailingSlash$1, joinURL, withoutLeadingSlash } from 'ufo';
|
|
18
18
|
import { ImpoundPlugin } from 'impound';
|
|
19
19
|
import { defu } from 'defu';
|
|
20
20
|
import { satisfies, coerce } from 'semver';
|
|
21
21
|
import { isCI, provider, hasTTY } from 'std-env';
|
|
22
|
-
import { genArrayFromRaw, genSafeVariableName, genImport, genDynamicImport, genObjectFromRawEntries, genString, genDynamicTypeImport, genExport } from 'knitwork';
|
|
22
|
+
import { genArrayFromRaw, genSafeVariableName, genImport, genDynamicImport, genObjectFromRawEntries, genString, genObjectKey, genInlineTypeImport, genDynamicTypeImport, genExport } from 'knitwork';
|
|
23
23
|
import { resolveModulePath } from 'exsolve';
|
|
24
24
|
import { addDependency } from 'nypm';
|
|
25
25
|
import { reverseResolveAlias, filename, resolveAlias } from 'pathe/utils';
|
|
26
|
-
import { createRoutesContext } from '
|
|
27
|
-
import { resolveOptions } from 'unplugin-vue-router/options';
|
|
26
|
+
import { createRoutesContext, resolveOptions } from 'vue-router/unplugin';
|
|
28
27
|
import { createRouter, addRoute, findAllRoutes } from 'rou3';
|
|
29
|
-
import { fileURLToPath
|
|
28
|
+
import { fileURLToPath } from 'node:url';
|
|
29
|
+
import picomatch from 'picomatch';
|
|
30
30
|
import { runInNewContext } from 'node:vm';
|
|
31
31
|
import { klona } from 'klona';
|
|
32
32
|
import { parseAndWalk, ScopeTracker, walk, isBindingIdentifier, getUndeclaredIdentifiersInFunction } from 'oxc-walker';
|
|
33
33
|
import { parseSync } from 'oxc-parser';
|
|
34
34
|
import { transformSync } from 'oxc-transform';
|
|
35
|
+
import { compileParsePath, buildTree, removeFile, addFile, toVueRouter4 } from 'unrouting';
|
|
35
36
|
import { splitByCase, kebabCase, pascalCase, camelCase } from 'scule';
|
|
36
37
|
import { createUnplugin } from 'unplugin';
|
|
37
38
|
import { findStaticImports, findExports, parseStaticImport, parseNodeModulePath, lookupNodeModuleSubpath } from 'mlly';
|
|
@@ -41,17 +42,16 @@ import { defineUnimportPreset, createUnimport, toExports, toTypeDeclarationFile,
|
|
|
41
42
|
import { glob } from 'tinyglobby';
|
|
42
43
|
import { parse, walk as walk$1, ELEMENT_NODE } from 'ultrahtml';
|
|
43
44
|
import { isObject } from '@vue/shared';
|
|
44
|
-
import {
|
|
45
|
+
import { resolve as resolve$1 } from 'node:path';
|
|
46
|
+
import { parseTar, createTar } from 'nanotar';
|
|
45
47
|
import { createTransformer } from 'unctx/transform';
|
|
48
|
+
import { performance } from 'node:perf_hooks';
|
|
46
49
|
import { watch as watch$1 } from 'chokidar';
|
|
47
50
|
import { debounce } from 'perfect-debounce';
|
|
48
51
|
import { resolveSchema, generateTypes } from 'untyped';
|
|
49
52
|
import untypedPlugin from 'untyped/babel-plugin';
|
|
50
53
|
import { createJiti } from 'jiti';
|
|
51
54
|
import { minifySync } from 'oxc-minify';
|
|
52
|
-
import { performance } from 'node:perf_hooks';
|
|
53
|
-
import { resolve as resolve$1 } from 'node:path';
|
|
54
|
-
import { parseTar, createTar } from 'nanotar';
|
|
55
55
|
|
|
56
56
|
function toArray(value) {
|
|
57
57
|
return Array.isArray(value) ? value : [value];
|
|
@@ -66,6 +66,10 @@ function isDirectorySync(path) {
|
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
const LEADING_DOT_RE = /^\.+/g;
|
|
70
|
+
function normalizeExtension(input) {
|
|
71
|
+
return input.replace(LEADING_DOT_RE, "");
|
|
72
|
+
}
|
|
69
73
|
function stripExtension(path) {
|
|
70
74
|
return path.replace(/\.[^./\\]+$/, "");
|
|
71
75
|
}
|
|
@@ -73,6 +77,10 @@ function isWhitespace(char) {
|
|
|
73
77
|
const c = typeof char === "string" ? char.charCodeAt(0) : char;
|
|
74
78
|
return c === 32 || c === 9 || c === 10 || c === 13 || c === 12;
|
|
75
79
|
}
|
|
80
|
+
const JS_EXT_RE = /^[^?]*\.(?:[jt]sx?|[cm][jt]s)(?:$|\?)/;
|
|
81
|
+
const NUXT_LIB_RE = /^[^?]*node_modules\/(?:nuxt|nuxt3|nuxt-nightly|@nuxt)\//;
|
|
82
|
+
const STYLE_QUERY_RE$1 = /[?&]type=style/;
|
|
83
|
+
const MACRO_QUERY_RE$2 = /[?&]macro(?:=|&|$)/;
|
|
76
84
|
const DECLARATION_EXTENSIONS = ["d.ts", "d.mts", "d.cts", "d.vue.ts", "d.vue.mts", "d.vue.cts"];
|
|
77
85
|
const logger = useLogger("nuxt");
|
|
78
86
|
function resolveToAlias(path, nuxt = tryUseNuxt()) {
|
|
@@ -192,34 +200,51 @@ function resolveComponentNameSegments(fileName, prefixParts) {
|
|
|
192
200
|
return [...componentNameParts, ...fileNameParts];
|
|
193
201
|
}
|
|
194
202
|
|
|
203
|
+
function parseModuleId(id) {
|
|
204
|
+
const qIndex = id.indexOf("?");
|
|
205
|
+
if (qIndex === -1) {
|
|
206
|
+
return { pathname: id, search: "" };
|
|
207
|
+
}
|
|
208
|
+
return { pathname: id.slice(0, qIndex), search: id.slice(qIndex) };
|
|
209
|
+
}
|
|
210
|
+
const NUXT_COMPONENT_RE = /[?&]nuxt_component=/;
|
|
211
|
+
const MACRO_RE$1 = /[?&]macro=/;
|
|
212
|
+
const VUE_QUERY_RE = /[?&]vue(?:&|$)/;
|
|
213
|
+
const SETUP_QUERY_RE = /[?&]setup(?:=|&|$)/;
|
|
214
|
+
const TYPE_QUERY_RE = /[?&]type=([^&]*)/;
|
|
195
215
|
function isVue(id, opts = {}) {
|
|
196
|
-
const { search } =
|
|
216
|
+
const { search } = parseModuleId(id);
|
|
197
217
|
if (id.endsWith(".vue") && !search) {
|
|
198
218
|
return true;
|
|
199
219
|
}
|
|
200
220
|
if (!search) {
|
|
201
221
|
return false;
|
|
202
222
|
}
|
|
203
|
-
|
|
204
|
-
if (query.nuxt_component) {
|
|
223
|
+
if (NUXT_COMPONENT_RE.test(search)) {
|
|
205
224
|
return false;
|
|
206
225
|
}
|
|
207
|
-
if (
|
|
226
|
+
if (MACRO_RE$1.test(search) && (search === "?macro=true" || !opts.type || opts.type.includes("script"))) {
|
|
208
227
|
return true;
|
|
209
228
|
}
|
|
210
|
-
|
|
211
|
-
if (!("vue" in query) || opts.type && !opts.type.includes(type)) {
|
|
229
|
+
if (!VUE_QUERY_RE.test(search)) {
|
|
212
230
|
return false;
|
|
213
231
|
}
|
|
232
|
+
if (opts.type) {
|
|
233
|
+
const type = SETUP_QUERY_RE.test(search) ? "script" : TYPE_QUERY_RE.exec(search)?.[1];
|
|
234
|
+
if (!type || !opts.type.includes(type)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
214
238
|
return true;
|
|
215
239
|
}
|
|
216
240
|
const JS_RE$1 = /\.(?:[cm]?j|t)sx?$/;
|
|
241
|
+
const VUE_ID_RE = /\.vue(?:\?|$)/;
|
|
217
242
|
function isJS(id) {
|
|
218
|
-
const { pathname } =
|
|
243
|
+
const { pathname } = parseModuleId(id);
|
|
219
244
|
return JS_RE$1.test(pathname);
|
|
220
245
|
}
|
|
221
246
|
function getLoader(id) {
|
|
222
|
-
const { pathname } =
|
|
247
|
+
const { pathname } = parseModuleId(id);
|
|
223
248
|
const ext = extname(pathname);
|
|
224
249
|
if (ext === ".vue") {
|
|
225
250
|
return "vue";
|
|
@@ -249,30 +274,69 @@ const QUOTE_RE = /["']/g;
|
|
|
249
274
|
const EXTENSION_RE = /\b\.\w+$/g;
|
|
250
275
|
const SX_RE = /\.[tj]sx$/;
|
|
251
276
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
};
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
277
|
+
function createPagesContext(options = {}) {
|
|
278
|
+
const modes = options.shouldUseServerComponents ? ["server", "client"] : ["client"];
|
|
279
|
+
const treeOptions = {
|
|
280
|
+
roots: options.roots,
|
|
281
|
+
modes,
|
|
282
|
+
warn: (msg) => logger.warn(msg)
|
|
283
|
+
};
|
|
284
|
+
const emitOptions = {
|
|
285
|
+
onDuplicateRouteName: (_name, file, existingFile) => {
|
|
286
|
+
logger.warn(`Route name generated for \`${file}\` is the same as \`${existingFile}\`. You may wish to set a custom name using \`definePageMeta\` within the page file.`);
|
|
287
|
+
},
|
|
288
|
+
attrs: { mode: modes }
|
|
289
|
+
};
|
|
290
|
+
const compiledParse = compileParsePath(treeOptions);
|
|
291
|
+
let tree = buildTree([], treeOptions);
|
|
292
|
+
const trackedFiles = /* @__PURE__ */ new Set();
|
|
293
|
+
return {
|
|
294
|
+
emit() {
|
|
295
|
+
return toVueRouter4(tree, emitOptions);
|
|
296
|
+
},
|
|
297
|
+
addFile(filePath, priority = 0) {
|
|
298
|
+
addFile(tree, { path: filePath, priority }, compiledParse);
|
|
299
|
+
trackedFiles.add(filePath);
|
|
300
|
+
},
|
|
301
|
+
removeFile(filePath) {
|
|
302
|
+
const removed = removeFile(tree, filePath);
|
|
303
|
+
if (removed) {
|
|
304
|
+
trackedFiles.delete(filePath);
|
|
305
|
+
}
|
|
306
|
+
return removed;
|
|
307
|
+
},
|
|
308
|
+
rebuild(files) {
|
|
309
|
+
tree = buildTree(files, treeOptions);
|
|
310
|
+
trackedFiles.clear();
|
|
311
|
+
for (const f of files) {
|
|
312
|
+
trackedFiles.add(f.path);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
trackedFiles
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
async function resolvePagesRoutes(pattern, nuxt = useNuxt(), ctx) {
|
|
265
319
|
const pagesDirs = getLayerDirectories(nuxt).map((d) => d.appPages);
|
|
266
|
-
const
|
|
267
|
-
for (
|
|
320
|
+
const inputFiles = [];
|
|
321
|
+
for (let priority = 0; priority < pagesDirs.length; priority++) {
|
|
322
|
+
const dir = pagesDirs[priority];
|
|
268
323
|
const files = await resolveFiles(dir, pattern);
|
|
269
|
-
|
|
324
|
+
for (const file of files) {
|
|
325
|
+
inputFiles.push({ path: file, priority });
|
|
326
|
+
}
|
|
270
327
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
328
|
+
let pages;
|
|
329
|
+
if (ctx) {
|
|
330
|
+
ctx.rebuild(inputFiles);
|
|
331
|
+
pages = ctx.emit();
|
|
332
|
+
} else {
|
|
333
|
+
const oneShot = createPagesContext({ roots: pagesDirs, shouldUseServerComponents: !!nuxt.options.experimental.componentIslands });
|
|
334
|
+
oneShot.rebuild(inputFiles);
|
|
335
|
+
pages = oneShot.emit();
|
|
336
|
+
}
|
|
337
|
+
return augmentAndResolve(pages, ctx?.trackedFiles ?? new Set(inputFiles.map((f) => f.path)), nuxt);
|
|
338
|
+
}
|
|
339
|
+
async function augmentAndResolve(pages, trackedFiles, nuxt = useNuxt()) {
|
|
276
340
|
const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages;
|
|
277
341
|
if (shouldAugment === false) {
|
|
278
342
|
await nuxt.callHook("pages:extend", pages);
|
|
@@ -284,7 +348,7 @@ async function resolvePagesRoutes(pattern, nuxt = useNuxt()) {
|
|
|
284
348
|
"middleware",
|
|
285
349
|
...extraPageMetaExtractionKeys
|
|
286
350
|
]),
|
|
287
|
-
fullyResolvedPaths:
|
|
351
|
+
fullyResolvedPaths: trackedFiles
|
|
288
352
|
};
|
|
289
353
|
if (shouldAugment === "after-resolve") {
|
|
290
354
|
await nuxt.callHook("pages:extend", pages);
|
|
@@ -298,68 +362,11 @@ async function resolvePagesRoutes(pattern, nuxt = useNuxt()) {
|
|
|
298
362
|
await nuxt.callHook("pages:resolved", pages);
|
|
299
363
|
return pages;
|
|
300
364
|
}
|
|
301
|
-
const INDEX_PAGE_RE = /\/index$/;
|
|
302
|
-
function generateRoutesFromFiles(files, options = {}) {
|
|
303
|
-
if (!files.length) {
|
|
304
|
-
return [];
|
|
305
|
-
}
|
|
306
|
-
const routes = [];
|
|
307
|
-
const sortedFiles = [...files].sort((a, b) => a.relativePath.length - b.relativePath.length);
|
|
308
|
-
for (const file of sortedFiles) {
|
|
309
|
-
const segments = file.relativePath.replace(new RegExp(`${escapeRE(extname(file.relativePath))}$`), "").split("/");
|
|
310
|
-
const route = {
|
|
311
|
-
name: "",
|
|
312
|
-
path: "",
|
|
313
|
-
file: file.absolutePath,
|
|
314
|
-
children: []
|
|
315
|
-
};
|
|
316
|
-
let parent = routes;
|
|
317
|
-
const routeGroups = [];
|
|
318
|
-
const lastSegment = segments[segments.length - 1];
|
|
319
|
-
if (lastSegment.endsWith(".server")) {
|
|
320
|
-
segments[segments.length - 1] = lastSegment.replace(".server", "");
|
|
321
|
-
if (options.shouldUseServerComponents) {
|
|
322
|
-
route.mode = "server";
|
|
323
|
-
}
|
|
324
|
-
} else if (lastSegment.endsWith(".client")) {
|
|
325
|
-
segments[segments.length - 1] = lastSegment.replace(".client", "");
|
|
326
|
-
route.mode = "client";
|
|
327
|
-
}
|
|
328
|
-
for (let i = 0; i < segments.length; i++) {
|
|
329
|
-
const segment = segments[i];
|
|
330
|
-
const tokens = parseSegment(segment, file.absolutePath);
|
|
331
|
-
if (tokens.every((token) => token.type === SegmentTokenType.group)) {
|
|
332
|
-
const groupNames = tokens.map((t) => t.value);
|
|
333
|
-
routeGroups.push(...groupNames);
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
const segmentName = tokens.map(({ value, type }) => type === SegmentTokenType.group ? "" : value).join("");
|
|
337
|
-
route.name += (route.name && "/") + segmentName;
|
|
338
|
-
const routePath = getRoutePath(tokens, segments[i + 1] !== void 0 && segments[i + 1] !== "index");
|
|
339
|
-
const path = withLeadingSlash(joinURL(route.path, routePath.replace(INDEX_PAGE_RE, "/")));
|
|
340
|
-
const child = parent.find((parentRoute) => parentRoute.name === route.name && parentRoute.path === path.replace("([^/]*)*", "(.*)*"));
|
|
341
|
-
if (child && child.children) {
|
|
342
|
-
parent = child.children;
|
|
343
|
-
route.path = "";
|
|
344
|
-
} else if (segmentName === "index" && !route.path) {
|
|
345
|
-
route.path += "/";
|
|
346
|
-
} else if (segmentName !== "index") {
|
|
347
|
-
route.path += routePath;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
if (routeGroups.length > 0) {
|
|
351
|
-
route.meta ||= {};
|
|
352
|
-
route.meta.groups = routeGroups;
|
|
353
|
-
}
|
|
354
|
-
parent.push(route);
|
|
355
|
-
}
|
|
356
|
-
return prepareRoutes(routes);
|
|
357
|
-
}
|
|
358
365
|
async function augmentPages(routes, vfs, ctx = {}) {
|
|
359
366
|
ctx.augmentedPages ??= /* @__PURE__ */ new Set();
|
|
360
367
|
for (const route of routes) {
|
|
361
368
|
if (route.file && !ctx.pagesToSkip?.has(route.file)) {
|
|
362
|
-
const fileContent =
|
|
369
|
+
const fileContent = vfs[route.file] ?? fs.readFileSync(ctx.fullyResolvedPaths?.has(route.file) ? route.file : await resolvePath(route.file), "utf-8");
|
|
363
370
|
const routeMeta = getRouteMeta(fileContent, route.file, ctx.extraExtractionKeys);
|
|
364
371
|
if (route.meta) {
|
|
365
372
|
routeMeta.meta = defu({}, routeMeta.meta, route.meta);
|
|
@@ -376,7 +383,7 @@ async function augmentPages(routes, vfs, ctx = {}) {
|
|
|
376
383
|
}
|
|
377
384
|
return ctx.augmentedPages;
|
|
378
385
|
}
|
|
379
|
-
const SFC_SCRIPT_RE = /<script(?<attrs>[^>]*)>(?<content>[\s\S]*?)<\/script
|
|
386
|
+
const SFC_SCRIPT_RE = /<script(?=\s|>)(?<attrs>[^>]*)>(?<content>[\s\S]*?)<\/script\s*>/gi;
|
|
380
387
|
function extractScriptContent(sfc) {
|
|
381
388
|
const contents = [];
|
|
382
389
|
for (const match of sfc.matchAll(SFC_SCRIPT_RE)) {
|
|
@@ -497,153 +504,35 @@ function getRouteMeta(contents, absolutePath, extraExtractionKeys = /* @__PURE__
|
|
|
497
504
|
extractCache[absolutePath] = extractedData;
|
|
498
505
|
return klona(extractedData);
|
|
499
506
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
switch (token.type) {
|
|
504
|
-
case SegmentTokenType.optional:
|
|
505
|
-
return path + `:${token.value}?`;
|
|
506
|
-
case SegmentTokenType.dynamic:
|
|
507
|
-
return path + `:${token.value}()`;
|
|
508
|
-
case SegmentTokenType.catchall:
|
|
509
|
-
return path + (hasSucceedingSegment ? `:${token.value}([^/]*)*` : `:${token.value}(.*)*`);
|
|
510
|
-
case SegmentTokenType.group:
|
|
511
|
-
return path;
|
|
512
|
-
case SegmentTokenType.static:
|
|
513
|
-
default:
|
|
514
|
-
return path + token.value.replace(ESCAPE_CHARS_RE, "\\$&");
|
|
515
|
-
}
|
|
516
|
-
}, "/");
|
|
517
|
-
}
|
|
518
|
-
const PARAM_CHAR_RE = /[\w.]/;
|
|
519
|
-
function parseSegment(segment, absolutePath) {
|
|
520
|
-
let state = SegmentParserState.initial;
|
|
521
|
-
let i = 0;
|
|
522
|
-
let buffer = "";
|
|
523
|
-
const tokens = [];
|
|
524
|
-
function consumeBuffer() {
|
|
525
|
-
if (!buffer) {
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
if (state === SegmentParserState.initial) {
|
|
529
|
-
throw new Error("wrong state");
|
|
530
|
-
}
|
|
531
|
-
tokens.push({ type: state, value: buffer });
|
|
532
|
-
buffer = "";
|
|
533
|
-
}
|
|
534
|
-
while (i < segment.length) {
|
|
535
|
-
const c = segment[i];
|
|
536
|
-
switch (state) {
|
|
537
|
-
case SegmentParserState.initial:
|
|
538
|
-
buffer = "";
|
|
539
|
-
if (c === "[") {
|
|
540
|
-
state = SegmentParserState.dynamic;
|
|
541
|
-
} else if (c === "(") {
|
|
542
|
-
state = SegmentParserState.group;
|
|
543
|
-
} else {
|
|
544
|
-
i--;
|
|
545
|
-
state = SegmentParserState.static;
|
|
546
|
-
}
|
|
547
|
-
break;
|
|
548
|
-
case SegmentParserState.static:
|
|
549
|
-
if (c === "[") {
|
|
550
|
-
consumeBuffer();
|
|
551
|
-
state = SegmentParserState.dynamic;
|
|
552
|
-
} else if (c === "(") {
|
|
553
|
-
consumeBuffer();
|
|
554
|
-
state = SegmentParserState.group;
|
|
555
|
-
} else {
|
|
556
|
-
buffer += c;
|
|
557
|
-
}
|
|
558
|
-
break;
|
|
559
|
-
case SegmentParserState.catchall:
|
|
560
|
-
case SegmentParserState.dynamic:
|
|
561
|
-
case SegmentParserState.optional:
|
|
562
|
-
case SegmentParserState.group:
|
|
563
|
-
if (buffer === "...") {
|
|
564
|
-
buffer = "";
|
|
565
|
-
state = SegmentParserState.catchall;
|
|
566
|
-
}
|
|
567
|
-
if (c === "[" && state === SegmentParserState.dynamic) {
|
|
568
|
-
state = SegmentParserState.optional;
|
|
569
|
-
}
|
|
570
|
-
if (c === "]" && (state !== SegmentParserState.optional || segment[i - 1] === "]")) {
|
|
571
|
-
if (!buffer) {
|
|
572
|
-
throw new Error("Empty param");
|
|
573
|
-
} else {
|
|
574
|
-
consumeBuffer();
|
|
575
|
-
}
|
|
576
|
-
state = SegmentParserState.initial;
|
|
577
|
-
} else if (c === ")" && state === SegmentParserState.group) {
|
|
578
|
-
if (!buffer) {
|
|
579
|
-
throw new Error("Empty group");
|
|
580
|
-
} else {
|
|
581
|
-
consumeBuffer();
|
|
582
|
-
}
|
|
583
|
-
state = SegmentParserState.initial;
|
|
584
|
-
} else if (c && PARAM_CHAR_RE.test(c)) {
|
|
585
|
-
buffer += c;
|
|
586
|
-
} else if (state === SegmentParserState.dynamic || state === SegmentParserState.optional) {
|
|
587
|
-
if (c !== "[" && c !== "]") {
|
|
588
|
-
logger.warn(`'\`${c}\`' is not allowed in a dynamic route parameter and has been ignored. Consider renaming \`${absolutePath}\`.`);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
break;
|
|
592
|
-
}
|
|
593
|
-
i++;
|
|
594
|
-
}
|
|
595
|
-
if (state === SegmentParserState.dynamic) {
|
|
596
|
-
throw new Error(`Unfinished param "${buffer}"`);
|
|
507
|
+
function serializeRouteValue(value, skipSerialisation = false) {
|
|
508
|
+
if (skipSerialisation || value === void 0) {
|
|
509
|
+
return void 0;
|
|
597
510
|
}
|
|
598
|
-
|
|
599
|
-
return tokens;
|
|
511
|
+
return JSON.stringify(value);
|
|
600
512
|
}
|
|
601
|
-
function
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
return route;
|
|
605
|
-
}
|
|
606
|
-
if (route.children && route.children.length > 0) {
|
|
607
|
-
const child = findRouteByName(name, route.children);
|
|
608
|
-
if (child) {
|
|
609
|
-
return child;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
513
|
+
function normalizeComponent(page, pageImport, routeName) {
|
|
514
|
+
if (page.mode === "server") {
|
|
515
|
+
return `() => createIslandPage(${routeName})`;
|
|
612
516
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
function prepareRoutes(routes, parent, names = /* @__PURE__ */ new Set()) {
|
|
616
|
-
for (const route of routes) {
|
|
617
|
-
if (route.name) {
|
|
618
|
-
route.name = route.name.replace(INDEX_PAGE_RE, "").replace(NESTED_PAGE_RE, "-");
|
|
619
|
-
if (names.has(route.name)) {
|
|
620
|
-
const existingRoute = findRouteByName(route.name, routes);
|
|
621
|
-
const extra = existingRoute?.name ? `is the same as \`${existingRoute.file}\`` : "is a duplicate";
|
|
622
|
-
logger.warn(`Route name generated for \`${route.file}\` ${extra}. You may wish to set a custom name using \`definePageMeta\` within the page file.`);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
if (parent && route.path[0] === "/") {
|
|
626
|
-
route.path = route.path.slice(1);
|
|
627
|
-
}
|
|
628
|
-
if (route.children?.length) {
|
|
629
|
-
route.children = prepareRoutes(route.children, route, names);
|
|
630
|
-
}
|
|
631
|
-
if (route.children?.find((childRoute) => childRoute.path === "")) {
|
|
632
|
-
delete route.name;
|
|
633
|
-
}
|
|
634
|
-
if (route.name) {
|
|
635
|
-
names.add(route.name);
|
|
636
|
-
}
|
|
517
|
+
if (page.mode === "client") {
|
|
518
|
+
return `() => createClientPage(${pageImport})`;
|
|
637
519
|
}
|
|
638
|
-
return
|
|
520
|
+
return pageImport;
|
|
639
521
|
}
|
|
640
|
-
function
|
|
641
|
-
if (
|
|
642
|
-
return
|
|
522
|
+
function normalizeComponentWithName(page, isSyncImport, pageImportName, pageImport, routeName, metaRouteName) {
|
|
523
|
+
if (isSyncImport) {
|
|
524
|
+
return `Object.assign(${pageImportName}, { __name: ${metaRouteName} })`;
|
|
643
525
|
}
|
|
644
|
-
|
|
526
|
+
if (page.mode === "server") {
|
|
527
|
+
return `() => createIslandPage(${routeName})`;
|
|
528
|
+
}
|
|
529
|
+
if (page.mode === "client") {
|
|
530
|
+
return `() => createClientPage(${pageImport}).then((c) => Object.assign(c, { __name: ${metaRouteName} }))`;
|
|
531
|
+
}
|
|
532
|
+
return `${pageImport}.then((m) => Object.assign(m.default, { __name: ${metaRouteName} }))`;
|
|
645
533
|
}
|
|
646
534
|
function normalizeRoutes(routes, metaImports = /* @__PURE__ */ new Set(), options) {
|
|
535
|
+
const nuxt = useNuxt();
|
|
647
536
|
return {
|
|
648
537
|
imports: metaImports,
|
|
649
538
|
routes: genArrayFromRaw(routes.map((page) => {
|
|
@@ -683,15 +572,18 @@ function normalizeRoutes(routes, metaImports = /* @__PURE__ */ new Set(), option
|
|
|
683
572
|
if (page._sync) {
|
|
684
573
|
metaImports.add(genImport(file, [{ name: "default", as: pageImportName }]));
|
|
685
574
|
}
|
|
686
|
-
const
|
|
575
|
+
const isSyncImport = page._sync && page.mode !== "client";
|
|
576
|
+
const pageImport = isSyncImport ? pageImportName : genDynamicImport(file);
|
|
577
|
+
const metaRouteName = `${metaImportName}?.name ?? ${route.name}`;
|
|
578
|
+
const component = nuxt.options.experimental.normalizePageNames ? normalizeComponentWithName(page, isSyncImport, pageImportName, pageImport, route.name, metaRouteName) : normalizeComponent(page, pageImport, route.name);
|
|
687
579
|
const metaRoute = {
|
|
688
|
-
name:
|
|
580
|
+
name: metaRouteName,
|
|
689
581
|
path: `${metaImportName}?.path ?? ${route.path}`,
|
|
690
582
|
props: `${metaImportName}?.props ?? ${route.props ?? false}`,
|
|
691
583
|
meta: `${metaImportName} || {}`,
|
|
692
584
|
alias: `${metaImportName}?.alias || []`,
|
|
693
585
|
redirect: `${metaImportName}?.redirect`,
|
|
694
|
-
component
|
|
586
|
+
component
|
|
695
587
|
};
|
|
696
588
|
if (page.mode === "server") {
|
|
697
589
|
metaImports.add(`
|
|
@@ -866,12 +758,10 @@ const PageMetaPlugin = (options = {}) => createUnplugin(() => {
|
|
|
866
758
|
return {
|
|
867
759
|
name: "nuxt:pages-macros-transform",
|
|
868
760
|
enforce: "post",
|
|
869
|
-
transformInclude(id) {
|
|
870
|
-
return !!parseMacroQuery(id).macro;
|
|
871
|
-
},
|
|
872
761
|
transform: {
|
|
873
762
|
filter: {
|
|
874
763
|
id: {
|
|
764
|
+
include: /[?&]macro=true\b/,
|
|
875
765
|
exclude: [/(?:\?|%3F).*type=(?:style|template)/]
|
|
876
766
|
},
|
|
877
767
|
code: {
|
|
@@ -919,7 +809,7 @@ const PageMetaPlugin = (options = {}) => createUnplugin(() => {
|
|
|
919
809
|
if (!hasMacro && !code.includes("export { default }") && !code.includes("__nuxt_page_meta")) {
|
|
920
810
|
if (!code) {
|
|
921
811
|
s.append(options.dev ? CODE_DEV_EMPTY + CODE_HMR : CODE_EMPTY);
|
|
922
|
-
const { pathname } =
|
|
812
|
+
const { pathname } = parseModuleId(id);
|
|
923
813
|
logger.error(`The file \`${pathname}\` is not a valid page as it has no content.`);
|
|
924
814
|
} else {
|
|
925
815
|
s.overwrite(0, code.length, options.dev ? CODE_DEV_EMPTY + CODE_HMR : CODE_EMPTY);
|
|
@@ -1033,21 +923,46 @@ const PageMetaPlugin = (options = {}) => createUnplugin(() => {
|
|
|
1033
923
|
const metaCode = code.slice(meta.start, meta.end);
|
|
1034
924
|
const m = new MagicString(metaCode);
|
|
1035
925
|
if (meta.type === "ObjectExpression") {
|
|
926
|
+
const omitProp = (prop, i) => {
|
|
927
|
+
const nextProperty = meta.properties[i + 1];
|
|
928
|
+
if (nextProperty) {
|
|
929
|
+
m.overwrite(prop.start - meta.start, nextProperty.start - meta.start, "");
|
|
930
|
+
} else if (code[prop.end] === ",") {
|
|
931
|
+
m.overwrite(prop.start - meta.start, prop.end - meta.start + 1, "");
|
|
932
|
+
} else {
|
|
933
|
+
m.overwrite(prop.start - meta.start, prop.end - meta.start, "");
|
|
934
|
+
}
|
|
935
|
+
};
|
|
1036
936
|
for (let i = 0; i < meta.properties.length; i++) {
|
|
1037
937
|
const prop = meta.properties[i];
|
|
1038
|
-
if (prop.type
|
|
938
|
+
if (prop.type !== "Property" || prop.key.type !== "Identifier") {
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
if (options.extractedKeys?.includes(prop.key.name)) {
|
|
1039
942
|
const { serializable } = isSerializable(metaCode, prop.value);
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
943
|
+
if (serializable) {
|
|
944
|
+
omitProp(prop, i);
|
|
1042
945
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
946
|
+
} else if (prop.key.name === "layout" && prop.value.type === "ObjectExpression") {
|
|
947
|
+
for (const layoutProp of prop.value.properties) {
|
|
948
|
+
if (layoutProp.type !== "Property" || layoutProp.key.type !== "Identifier") {
|
|
949
|
+
continue;
|
|
950
|
+
}
|
|
951
|
+
if (layoutProp.key.name === "name") {
|
|
952
|
+
m.appendLeft(
|
|
953
|
+
prop.start - meta.start,
|
|
954
|
+
`layout: ${code.slice(layoutProp.value.start, layoutProp.value.end)},
|
|
955
|
+
`
|
|
956
|
+
);
|
|
957
|
+
} else if (layoutProp.key.name === "props") {
|
|
958
|
+
m.appendLeft(
|
|
959
|
+
prop.start - meta.start,
|
|
960
|
+
`layoutProps: ${code.slice(layoutProp.value.start, layoutProp.value.end)},
|
|
961
|
+
`
|
|
962
|
+
);
|
|
963
|
+
}
|
|
1050
964
|
}
|
|
965
|
+
omitProp(prop, i);
|
|
1051
966
|
}
|
|
1052
967
|
}
|
|
1053
968
|
}
|
|
@@ -1114,11 +1029,17 @@ const MACRO_RE = /¯o=true/;
|
|
|
1114
1029
|
function rewriteQuery(id) {
|
|
1115
1030
|
return id.replace(/\?.+$/, (r) => "?macro=true&" + r.replace(QUERY_START_RE, "").replace(MACRO_RE, ""));
|
|
1116
1031
|
}
|
|
1032
|
+
const MACRO_QUERY_RE$1 = /[?&]macro=true(?:&|$)/;
|
|
1033
|
+
const TYPE_PARAM_RE = /[?&]type=([^?&]+)/;
|
|
1034
|
+
const LANG_PARAM_RE = /[?&]lang=([^?&]+)/;
|
|
1117
1035
|
function parseMacroQuery(id) {
|
|
1118
|
-
const { search } =
|
|
1119
|
-
const query =
|
|
1120
|
-
|
|
1121
|
-
|
|
1036
|
+
const { search } = parseModuleId(id);
|
|
1037
|
+
const query = {
|
|
1038
|
+
type: TYPE_PARAM_RE.exec(search)?.[1],
|
|
1039
|
+
lang: LANG_PARAM_RE.exec(search)?.[1] ?? void 0
|
|
1040
|
+
};
|
|
1041
|
+
if (MACRO_QUERY_RE$1.test(search)) {
|
|
1042
|
+
query.macro = "true";
|
|
1122
1043
|
}
|
|
1123
1044
|
return query;
|
|
1124
1045
|
}
|
|
@@ -1178,13 +1099,13 @@ const RouteInjectionPlugin = (nuxt) => createUnplugin(() => {
|
|
|
1178
1099
|
});
|
|
1179
1100
|
|
|
1180
1101
|
const OPTIONAL_PARAM_RE = /^\/?:.*(?:\?|\(\.\*\)\*)$/;
|
|
1181
|
-
const runtimeDir = resolve(distDir, "pages/runtime");
|
|
1182
1102
|
const pagesImportPresets = [
|
|
1183
|
-
{ imports: ["definePageMeta"], from:
|
|
1103
|
+
{ imports: ["definePageMeta"], from: "#app/composables/pages" },
|
|
1104
|
+
{ imports: ["PageMeta"], from: "#app/composables/pages", type: true },
|
|
1184
1105
|
{ imports: ["useLink"], from: "vue-router" }
|
|
1185
1106
|
];
|
|
1186
1107
|
const routeRulesPresets = [
|
|
1187
|
-
{ imports: ["defineRouteRules"], from:
|
|
1108
|
+
{ imports: ["defineRouteRules"], from: "#app/composables/pages" }
|
|
1188
1109
|
];
|
|
1189
1110
|
async function resolveRouterOptions(nuxt, builtInRouterOptions) {
|
|
1190
1111
|
const context = {
|
|
@@ -1210,6 +1131,7 @@ const pagesModule = defineNuxtModule({
|
|
|
1210
1131
|
pattern: `**/*{${nuxt.options.extensions.join(",")}}`
|
|
1211
1132
|
}),
|
|
1212
1133
|
async setup(_options, nuxt) {
|
|
1134
|
+
const runtimeDir = resolve(distDir, "pages/runtime");
|
|
1213
1135
|
const options = typeof _options === "boolean" ? { enabled: _options ?? nuxt.options.pages, pattern: `**/*{${nuxt.options.extensions.join(",")}}` } : { ..._options };
|
|
1214
1136
|
options.pattern = Array.isArray(options.pattern) ? [...new Set(options.pattern)] : options.pattern;
|
|
1215
1137
|
let inlineRulesCache = {};
|
|
@@ -1224,19 +1146,34 @@ const pagesModule = defineNuxtModule({
|
|
|
1224
1146
|
};
|
|
1225
1147
|
});
|
|
1226
1148
|
}
|
|
1227
|
-
const
|
|
1228
|
-
|
|
1229
|
-
|
|
1149
|
+
const useExperimentalTypedPages = nuxt.options.experimental.typedPages;
|
|
1150
|
+
const builtInRouterOptions = await findPath(resolve(runtimeDir, "router.options")) || resolve(runtimeDir, "router.options");
|
|
1151
|
+
const pagesDirs = getLayerDirectories(nuxt).map((dirs) => dirs.appPages);
|
|
1152
|
+
const pagesCtx = nuxt.options.dev ? createPagesContext({
|
|
1153
|
+
roots: pagesDirs,
|
|
1154
|
+
shouldUseServerComponents: !!nuxt.options.experimental.componentIslands
|
|
1155
|
+
}) : void 0;
|
|
1156
|
+
const isPagePattern = picomatch(
|
|
1157
|
+
Array.isArray(options.pattern) ? options.pattern : [options.pattern]
|
|
1158
|
+
);
|
|
1159
|
+
const handleRouteRules = async (pages) => {
|
|
1160
|
+
if (nuxt.options.experimental.inlineRouteRules) {
|
|
1230
1161
|
const routeRules = globRouteRulesFromPages(pages);
|
|
1231
1162
|
await updateRouteConfig?.(routeRules);
|
|
1232
1163
|
} else {
|
|
1233
1164
|
removePagesRules(pages);
|
|
1234
1165
|
}
|
|
1166
|
+
};
|
|
1167
|
+
const resolvePagesRoutes$1 = async (pattern, nuxt2) => {
|
|
1168
|
+
const pages = await resolvePagesRoutes(pattern, nuxt2, pagesCtx);
|
|
1169
|
+
await handleRouteRules(pages);
|
|
1235
1170
|
return pages;
|
|
1236
1171
|
};
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1172
|
+
const augmentAndResolvePages = async (pages, trackedFiles, nuxt2) => {
|
|
1173
|
+
const resolved = await augmentAndResolve(pages, trackedFiles, nuxt2);
|
|
1174
|
+
await handleRouteRules(resolved);
|
|
1175
|
+
return resolved;
|
|
1176
|
+
};
|
|
1240
1177
|
nuxt.options.alias["#vue-router"] = "vue-router";
|
|
1241
1178
|
const routerPath = await resolveTypePath("vue-router", "", nuxt.options.modulesDir) || "vue-router";
|
|
1242
1179
|
nuxt.hook("prepare:types", ({ tsConfig }) => {
|
|
@@ -1369,7 +1306,7 @@ const pagesModule = defineNuxtModule({
|
|
|
1369
1306
|
route.addToMeta(page.meta);
|
|
1370
1307
|
}
|
|
1371
1308
|
if (page.alias) {
|
|
1372
|
-
route.addAlias(page.alias);
|
|
1309
|
+
route.addAlias(Array.isArray(page.alias) ? page.alias : [page.alias]);
|
|
1373
1310
|
}
|
|
1374
1311
|
if (page.name) {
|
|
1375
1312
|
route.name = page.name;
|
|
@@ -1387,7 +1324,6 @@ const pagesModule = defineNuxtModule({
|
|
|
1387
1324
|
};
|
|
1388
1325
|
nuxt.hook("prepare:types", ({ references }) => {
|
|
1389
1326
|
references.push({ path: declarationFile });
|
|
1390
|
-
references.push({ types: "unplugin-vue-router/client" });
|
|
1391
1327
|
});
|
|
1392
1328
|
const context = createRoutesContext(resolveOptions(typedRouterOptions));
|
|
1393
1329
|
await mkdir(dirname(declarationFile), { recursive: true });
|
|
@@ -1405,8 +1341,17 @@ const pagesModule = defineNuxtModule({
|
|
|
1405
1341
|
}
|
|
1406
1342
|
});
|
|
1407
1343
|
}
|
|
1408
|
-
nuxt.hook("prepare:types", ({ references }) => {
|
|
1344
|
+
nuxt.hook("prepare:types", ({ references, tsConfig }) => {
|
|
1409
1345
|
references.push({ types: useExperimentalTypedPages ? "vue-router/auto-routes" : "vue-router" });
|
|
1346
|
+
tsConfig.vueCompilerOptions ||= {};
|
|
1347
|
+
tsConfig.vueCompilerOptions.plugins ||= [];
|
|
1348
|
+
tsConfig.vueCompilerOptions.plugins.push("vue-router/volar/sfc-route-blocks");
|
|
1349
|
+
if (useExperimentalTypedPages) {
|
|
1350
|
+
tsConfig.vueCompilerOptions.plugins.push({
|
|
1351
|
+
name: "vue-router/volar/sfc-typed-router",
|
|
1352
|
+
options: { rootDir: nuxt.options.rootDir }
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1410
1355
|
});
|
|
1411
1356
|
nuxt.hook("imports:sources", (sources) => {
|
|
1412
1357
|
const routerImports = sources.find((s) => s.from === "#app/composables/router" && s.imports.includes("onBeforeRouteLeave"));
|
|
@@ -1434,7 +1379,28 @@ const pagesModule = defineNuxtModule({
|
|
|
1434
1379
|
if (event === "change" && !shouldAlwaysRegenerate) {
|
|
1435
1380
|
return;
|
|
1436
1381
|
}
|
|
1437
|
-
|
|
1382
|
+
const layerIndex = pagesDirs.findIndex((dir) => path.startsWith(dir));
|
|
1383
|
+
const isInPagesDir = layerIndex !== -1;
|
|
1384
|
+
if (pagesCtx && isInPagesDir && !shouldAlwaysRegenerate) {
|
|
1385
|
+
try {
|
|
1386
|
+
if (event === "add") {
|
|
1387
|
+
const relativeToDir = relative(pagesDirs[layerIndex], path);
|
|
1388
|
+
if (!isPagePattern(relativeToDir) || isIgnored(path)) {
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
pagesCtx.addFile(path, layerIndex);
|
|
1392
|
+
} else if (event === "unlink") {
|
|
1393
|
+
if (!pagesCtx.removeFile(path)) {
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
const pages = pagesCtx.emit();
|
|
1398
|
+
nuxt.apps.default.pages = await augmentAndResolvePages(pages, pagesCtx.trackedFiles, nuxt);
|
|
1399
|
+
} catch (err) {
|
|
1400
|
+
logger.warn("Incremental route update failed, performing full rebuild", err);
|
|
1401
|
+
nuxt.apps.default.pages = await resolvePagesRoutes$1(options.pattern, nuxt);
|
|
1402
|
+
}
|
|
1403
|
+
} else if (shouldAlwaysRegenerate || updateTemplatePaths.some((dir) => path.startsWith(dir))) {
|
|
1438
1404
|
nuxt.apps.default.pages = await resolvePagesRoutes$1(options.pattern, nuxt);
|
|
1439
1405
|
}
|
|
1440
1406
|
});
|
|
@@ -1491,7 +1457,7 @@ const pagesModule = defineNuxtModule({
|
|
|
1491
1457
|
...nitro.options.ssrRoutes || [],
|
|
1492
1458
|
...toRou3Patterns(nuxt.apps.default?.pages || [])
|
|
1493
1459
|
];
|
|
1494
|
-
if (!nitro.options.static
|
|
1460
|
+
if (!nitro.options.static) {
|
|
1495
1461
|
const routeRulesRouter = createRouter();
|
|
1496
1462
|
for (const [route, rules] of Object.entries(nitro.options.routeRules)) {
|
|
1497
1463
|
addRoute(routeRulesRouter, void 0, route, rules);
|
|
@@ -1673,23 +1639,25 @@ const pagesModule = defineNuxtModule({
|
|
|
1673
1639
|
addTypeTemplate({
|
|
1674
1640
|
filename: "types/layouts.d.ts",
|
|
1675
1641
|
getContents: ({ app }) => {
|
|
1676
|
-
const imports = /* @__PURE__ */ new Set();
|
|
1677
|
-
const interfaceKeyValues = /* @__PURE__ */ new Map();
|
|
1678
|
-
for (const layout of Object.values(app.layouts)) {
|
|
1679
|
-
const varName = genSafeVariableName(layout.name);
|
|
1680
|
-
imports.add(genImport(layout.file, varName));
|
|
1681
|
-
interfaceKeyValues.set(layout.name, varName);
|
|
1682
|
-
}
|
|
1683
1642
|
return [
|
|
1684
|
-
...Array.from(imports),
|
|
1685
1643
|
"import type { ComputedRef, MaybeRef } from 'vue'",
|
|
1644
|
+
"",
|
|
1645
|
+
"type ComponentProps<T> = T extends new(...args: any) => { $props: infer P } ? NonNullable<P>",
|
|
1646
|
+
" : T extends (props: infer P, ...args: any) => any ? P",
|
|
1647
|
+
" : {}",
|
|
1648
|
+
"",
|
|
1686
1649
|
"declare module 'nuxt/app' {",
|
|
1687
1650
|
" interface NuxtLayouts {",
|
|
1688
|
-
...
|
|
1689
|
-
"}",
|
|
1651
|
+
...Object.values(app.layouts).map((layout) => ` ${genObjectKey(layout.name)}: ComponentProps<${genInlineTypeImport(layout.file)}>`),
|
|
1652
|
+
" }",
|
|
1690
1653
|
" export type LayoutKey = keyof NuxtLayouts extends never ? string : keyof NuxtLayouts",
|
|
1691
1654
|
" interface PageMeta {",
|
|
1692
|
-
" layout?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false>",
|
|
1655
|
+
" layout?: MaybeRef<LayoutKey | false> | ComputedRef<LayoutKey | false> | {",
|
|
1656
|
+
" [K in LayoutKey]: {",
|
|
1657
|
+
" name?: MaybeRef<K | false> | ComputedRef<K | false>",
|
|
1658
|
+
" props?: NuxtLayouts[K]",
|
|
1659
|
+
" }",
|
|
1660
|
+
" }[LayoutKey]",
|
|
1693
1661
|
" }",
|
|
1694
1662
|
"}"
|
|
1695
1663
|
].join("\n");
|
|
@@ -1700,9 +1668,10 @@ const pagesModule = defineNuxtModule({
|
|
|
1700
1668
|
filename: "types/view-transitions.d.ts",
|
|
1701
1669
|
getContents: () => {
|
|
1702
1670
|
return [
|
|
1671
|
+
"import type { ViewTransitionPageOptions } from '../types/config'",
|
|
1703
1672
|
"declare module 'nuxt/app' {",
|
|
1704
1673
|
" interface PageMeta {",
|
|
1705
|
-
" viewTransition?:
|
|
1674
|
+
" viewTransition?: ViewTransitionPageOptions['enabled'] | ViewTransitionPageOptions",
|
|
1706
1675
|
" }",
|
|
1707
1676
|
"}",
|
|
1708
1677
|
"export {}"
|
|
@@ -1729,12 +1698,19 @@ if (import.meta.hot) {
|
|
|
1729
1698
|
import.meta.hot.invalidate('[nuxt] Cannot replace routes because there is no active router. Reloading.')
|
|
1730
1699
|
return
|
|
1731
1700
|
}
|
|
1701
|
+
const addedRoutes = router.getRoutes().filter(r => !r._initial)
|
|
1732
1702
|
router.clearRoutes()
|
|
1733
1703
|
const routes = generateRoutes(mod.default || mod)
|
|
1734
1704
|
function addRoutes (routes) {
|
|
1735
1705
|
for (const route of routes) {
|
|
1736
1706
|
router.addRoute(route)
|
|
1737
1707
|
}
|
|
1708
|
+
for (const route of router.getRoutes()) {
|
|
1709
|
+
route._initial = true
|
|
1710
|
+
}
|
|
1711
|
+
for (const route of addedRoutes) {
|
|
1712
|
+
router.addRoute(route)
|
|
1713
|
+
}
|
|
1738
1714
|
router.isReady().then(() => {
|
|
1739
1715
|
// Resolve the current path against the new routes to get updated meta
|
|
1740
1716
|
const newRoute = router.resolve(router.currentRoute.value.fullPath)
|
|
@@ -1758,12 +1734,16 @@ export function handleHotUpdate(_router, _generateRoutes) {
|
|
|
1758
1734
|
import.meta.hot.data ||= {}
|
|
1759
1735
|
import.meta.hot.data.router = _router
|
|
1760
1736
|
import.meta.hot.data.generateRoutes = _generateRoutes
|
|
1737
|
+
for (const route of _router.getRoutes()) {
|
|
1738
|
+
route._initial = true
|
|
1739
|
+
}
|
|
1761
1740
|
}
|
|
1762
1741
|
}
|
|
1763
1742
|
`
|
|
1764
1743
|
);
|
|
1765
1744
|
|
|
1766
1745
|
const UNHEAD_LIB_RE = /node_modules[/\\](?:@unhead[/\\][^/\\]+|unhead)[/\\]/;
|
|
1746
|
+
const NUXT_HEAD_RE = /node_modules[/\\]nuxt[/\\]dist[/\\]head[/\\]runtime[/\\]/;
|
|
1767
1747
|
function toImports(specifiers) {
|
|
1768
1748
|
return specifiers.map((specifier) => {
|
|
1769
1749
|
const imported = specifier.imported;
|
|
@@ -1779,7 +1759,7 @@ const UnheadImportsPlugin = (options) => createUnplugin(() => {
|
|
|
1779
1759
|
enforce: "post",
|
|
1780
1760
|
transformInclude(id) {
|
|
1781
1761
|
id = normalize(id);
|
|
1782
|
-
return (isJS(id) || isVue(id, { type: ["script"] })) && !id.startsWith("virtual:") && !id.startsWith(normalize(distDir)) && !UNHEAD_LIB_RE.test(id);
|
|
1762
|
+
return (isJS(id) || isVue(id, { type: ["script"] })) && !id.startsWith("virtual:") && !id.startsWith(normalize(distDir)) && !UNHEAD_LIB_RE.test(id) && !NUXT_HEAD_RE.test(id);
|
|
1783
1763
|
},
|
|
1784
1764
|
transform: {
|
|
1785
1765
|
filter: {
|
|
@@ -1916,7 +1896,7 @@ const granularAppPresets = [
|
|
|
1916
1896
|
from: "#app/composables/component"
|
|
1917
1897
|
},
|
|
1918
1898
|
{
|
|
1919
|
-
imports: ["useAsyncData", "useLazyAsyncData", "useNuxtData", "refreshNuxtData", "clearNuxtData"],
|
|
1899
|
+
imports: ["useAsyncData", "useLazyAsyncData", "useNuxtData", "refreshNuxtData", "clearNuxtData", "createUseAsyncData"],
|
|
1920
1900
|
from: "#app/composables/asyncData"
|
|
1921
1901
|
},
|
|
1922
1902
|
{
|
|
@@ -1936,7 +1916,7 @@ const granularAppPresets = [
|
|
|
1936
1916
|
from: "#app/composables/error"
|
|
1937
1917
|
},
|
|
1938
1918
|
{
|
|
1939
|
-
imports: ["useFetch", "useLazyFetch"],
|
|
1919
|
+
imports: ["useFetch", "useLazyFetch", "createUseFetch"],
|
|
1940
1920
|
from: "#app/composables/fetch"
|
|
1941
1921
|
},
|
|
1942
1922
|
{
|
|
@@ -1987,6 +1967,10 @@ const granularAppPresets = [
|
|
|
1987
1967
|
imports: ["useRouteAnnouncer"],
|
|
1988
1968
|
from: "#app/composables/route-announcer"
|
|
1989
1969
|
},
|
|
1970
|
+
{
|
|
1971
|
+
imports: ["useAnnouncer"],
|
|
1972
|
+
from: "#app/composables/announcer"
|
|
1973
|
+
},
|
|
1990
1974
|
{
|
|
1991
1975
|
imports: ["useRuntimeHook"],
|
|
1992
1976
|
from: "#app/composables/runtime-hook"
|
|
@@ -2249,7 +2233,7 @@ const componentsIslandsTemplate = {
|
|
|
2249
2233
|
}
|
|
2250
2234
|
};
|
|
2251
2235
|
const NON_VUE_RE = /\b\.(?!vue)\w+$/g;
|
|
2252
|
-
function resolveComponentTypes(app, baseDir) {
|
|
2236
|
+
function resolveComponentTypes(app, baseDir, dynamic) {
|
|
2253
2237
|
const serverPlaceholderPath = resolve(distDir, "app/components/server-placeholder");
|
|
2254
2238
|
const componentTypes = [];
|
|
2255
2239
|
for (const c of app.components) {
|
|
@@ -2257,7 +2241,7 @@ function resolveComponentTypes(app, baseDir) {
|
|
|
2257
2241
|
continue;
|
|
2258
2242
|
}
|
|
2259
2243
|
const filePath = c.declarationPath || c.filePath;
|
|
2260
|
-
let type =
|
|
2244
|
+
let type = dynamic ? renderDynamicTypeImport(baseDir, filePath, c.export) : renderLegacyTypeImport(baseDir, filePath, c.export);
|
|
2261
2245
|
if (c.mode === "server") {
|
|
2262
2246
|
if (app.components.some((other) => other.pascalName === c.pascalName && other.mode === "client")) {
|
|
2263
2247
|
if (c.filePath.startsWith(serverPlaceholderPath)) {
|
|
@@ -2271,6 +2255,12 @@ function resolveComponentTypes(app, baseDir) {
|
|
|
2271
2255
|
}
|
|
2272
2256
|
return componentTypes;
|
|
2273
2257
|
}
|
|
2258
|
+
function renderDynamicTypeImport(baseDir, filePath, exportName) {
|
|
2259
|
+
return genDynamicTypeImport(isAbsolute(filePath) ? relative(baseDir, filePath).replace(NON_VUE_RE, "") : filePath.replace(NON_VUE_RE, ""), exportName);
|
|
2260
|
+
}
|
|
2261
|
+
function renderLegacyTypeImport(baseDir, filePath, exportName) {
|
|
2262
|
+
return `typeof ${genDynamicImport(isAbsolute(filePath) ? relative(baseDir, filePath).replace(NON_VUE_RE, "") : filePath.replace(NON_VUE_RE, ""), { wrapper: false })}['${exportName}']`;
|
|
2263
|
+
}
|
|
2274
2264
|
const islandType = "type IslandComponent<T> = DefineComponent<{}, {refresh: () => Promise<void>}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, SlotsType<{ fallback: { error: unknown } }>> & T";
|
|
2275
2265
|
const hydrationTypes = `
|
|
2276
2266
|
type HydrationStrategies = {
|
|
@@ -2288,7 +2278,7 @@ const componentsDeclarationTemplate = {
|
|
|
2288
2278
|
filename: "components.d.ts",
|
|
2289
2279
|
write: true,
|
|
2290
2280
|
getContents: ({ app, nuxt }) => {
|
|
2291
|
-
const componentTypes = resolveComponentTypes(app, nuxt.options.buildDir);
|
|
2281
|
+
const componentTypes = resolveComponentTypes(app, nuxt.options.buildDir, nuxt.options.experimental.typescriptPlugin);
|
|
2292
2282
|
return `
|
|
2293
2283
|
import type { DefineComponent, SlotsType } from 'vue'
|
|
2294
2284
|
${nuxt.options.experimental.componentIslands ? islandType : ""}
|
|
@@ -2304,14 +2294,14 @@ export const componentNames: string[]
|
|
|
2304
2294
|
const componentsTypeTemplate = {
|
|
2305
2295
|
filename: "types/components.d.ts",
|
|
2306
2296
|
getContents: ({ app, nuxt }) => {
|
|
2307
|
-
const componentTypes = resolveComponentTypes(app, join(nuxt.options.buildDir, "types"));
|
|
2297
|
+
const componentTypes = resolveComponentTypes(app, join(nuxt.options.buildDir, "types"), nuxt.options.experimental.typescriptPlugin);
|
|
2308
2298
|
return `
|
|
2309
2299
|
import type { DefineComponent, SlotsType } from 'vue'
|
|
2310
2300
|
${nuxt.options.experimental.componentIslands ? islandType : ""}
|
|
2311
2301
|
${hydrationTypes}
|
|
2312
2302
|
interface _GlobalComponents {
|
|
2313
|
-
${componentTypes.map(([pascalName, type]) => `
|
|
2314
|
-
${componentTypes.map(([pascalName, type]) => `
|
|
2303
|
+
${componentTypes.map(([pascalName, type]) => ` ${genObjectKey(pascalName)}: ${type}`).join("\n")}
|
|
2304
|
+
${componentTypes.map(([pascalName, type]) => ` ${genObjectKey(`Lazy${pascalName}`)}: LazyComponent<${type}>`).join("\n")}
|
|
2315
2305
|
}
|
|
2316
2306
|
|
|
2317
2307
|
declare module 'vue' {
|
|
@@ -2618,7 +2608,7 @@ const IslandsTransformPlugin = (options) => createUnplugin((_options, meta) => {
|
|
|
2618
2608
|
const islands = components.filter(
|
|
2619
2609
|
(component) => component.island || component.mode === "server" && !components.some((c) => c.pascalName === component.pascalName && c.mode === "client")
|
|
2620
2610
|
);
|
|
2621
|
-
const { pathname } =
|
|
2611
|
+
const { pathname } = parseModuleId(normalize(id));
|
|
2622
2612
|
return islands.some((c) => c.filePath === pathname);
|
|
2623
2613
|
},
|
|
2624
2614
|
transform: {
|
|
@@ -2819,6 +2809,7 @@ function TransformPlugin$1(nuxt, options) {
|
|
|
2819
2809
|
virtualImports: ["#components"],
|
|
2820
2810
|
injectAtEnd: true
|
|
2821
2811
|
});
|
|
2812
|
+
const rootDirWithSlash = nuxt.options.rootDir.replace(/\/?$/, "/");
|
|
2822
2813
|
function getComponentsImports() {
|
|
2823
2814
|
const components = options.getComponents(options.mode);
|
|
2824
2815
|
const clientOrServerModes = /* @__PURE__ */ new Set(["client", "server"]);
|
|
@@ -2852,11 +2843,11 @@ function TransformPlugin$1(nuxt, options) {
|
|
|
2852
2843
|
id: COMPONENT_QUERY_RE
|
|
2853
2844
|
},
|
|
2854
2845
|
handler(_code, id) {
|
|
2855
|
-
const { search } =
|
|
2856
|
-
const
|
|
2857
|
-
const mode =
|
|
2846
|
+
const { search } = parseModuleId(id);
|
|
2847
|
+
const params = new URLSearchParams(search);
|
|
2848
|
+
const mode = params.get("nuxt_component");
|
|
2858
2849
|
const bare = id.replace(/\?.*/, "");
|
|
2859
|
-
const componentExport =
|
|
2850
|
+
const componentExport = params.get("nuxt_component_export") || "default";
|
|
2860
2851
|
const exportWording = componentExport === "default" ? "export default" : `export const ${componentExport} =`;
|
|
2861
2852
|
if (mode === "async") {
|
|
2862
2853
|
return {
|
|
@@ -2885,7 +2876,7 @@ function TransformPlugin$1(nuxt, options) {
|
|
|
2885
2876
|
map: null
|
|
2886
2877
|
};
|
|
2887
2878
|
} else if (mode === "server" || mode === "server,async") {
|
|
2888
|
-
const name =
|
|
2879
|
+
const name = params.get("nuxt_component_name");
|
|
2889
2880
|
return {
|
|
2890
2881
|
code: [
|
|
2891
2882
|
`import { createServerComponent } from ${JSON.stringify(options.serverComponentRuntime)}`,
|
|
@@ -2911,9 +2902,15 @@ function TransformPlugin$1(nuxt, options) {
|
|
|
2911
2902
|
code: /#components/
|
|
2912
2903
|
},
|
|
2913
2904
|
async handler(code, id) {
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2905
|
+
if (isAbsolute(id) && (/node_modules[\\/](?!\.virtual)/.test(id) || !id.includes(rootDirWithSlash))) {
|
|
2906
|
+
let pkg;
|
|
2907
|
+
try {
|
|
2908
|
+
pkg = await readPackage(id);
|
|
2909
|
+
} catch {
|
|
2910
|
+
}
|
|
2911
|
+
if (isObject(pkg) && isObject(pkg.imports) && Object.keys(pkg.imports).some((k) => k.includes("#components"))) {
|
|
2912
|
+
return;
|
|
2913
|
+
}
|
|
2917
2914
|
}
|
|
2918
2915
|
componentUnimport.modifyDynamicImports((imports) => {
|
|
2919
2916
|
imports.length = 0;
|
|
@@ -2942,70 +2939,71 @@ const TreeShakeTemplatePlugin = (options) => createUnplugin(() => {
|
|
|
2942
2939
|
return {
|
|
2943
2940
|
name: "nuxt:tree-shake-template",
|
|
2944
2941
|
enforce: "post",
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
}
|
|
2956
|
-
const s = new MagicString(code);
|
|
2957
|
-
const [COMPONENTS_RE, COMPONENTS_IDENTIFIERS_RE] = regexpMap.get(components);
|
|
2958
|
-
if (!COMPONENTS_RE.test(code)) {
|
|
2959
|
-
return;
|
|
2960
|
-
}
|
|
2961
|
-
const componentsToRemoveSet = /* @__PURE__ */ new Set();
|
|
2962
|
-
const { program: ast } = parseAndWalk(code, id, (node) => {
|
|
2963
|
-
if (!isSsrRender(node)) {
|
|
2964
|
-
return;
|
|
2942
|
+
transform: {
|
|
2943
|
+
filter: {
|
|
2944
|
+
id: { include: VUE_ID_RE }
|
|
2945
|
+
},
|
|
2946
|
+
handler(code, id) {
|
|
2947
|
+
const components = options.getComponents();
|
|
2948
|
+
if (!regexpMap.has(components)) {
|
|
2949
|
+
const serverPlaceholderPath = resolve(distDir, "app/components/server-placeholder");
|
|
2950
|
+
const clientOnlyComponents = components.filter((c) => c.mode === "client" && !components.some((other) => other.mode !== "client" && other.pascalName === c.pascalName && !other.filePath.startsWith(serverPlaceholderPath))).flatMap((c) => [c.pascalName, c.kebabName.replaceAll("-", "_")]).concat(["ClientOnly", "client_only"]);
|
|
2951
|
+
regexpMap.set(components, [new RegExp(`(${clientOnlyComponents.join("|")})`), new RegExp(`^(${clientOnlyComponents.map((c) => `(?:(?:_unref\\()?(?:_component_)?(?:Lazy|lazy_)?${c}\\)?)`).join("|")})$`), clientOnlyComponents]);
|
|
2965
2952
|
}
|
|
2966
|
-
const
|
|
2967
|
-
|
|
2953
|
+
const s = new MagicString(code);
|
|
2954
|
+
const [COMPONENTS_RE, COMPONENTS_IDENTIFIERS_RE] = regexpMap.get(components);
|
|
2955
|
+
if (!COMPONENTS_RE.test(code)) {
|
|
2968
2956
|
return;
|
|
2969
2957
|
}
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
if (!
|
|
2958
|
+
const componentsToRemoveSet = /* @__PURE__ */ new Set();
|
|
2959
|
+
const { program: ast } = parseAndWalk(code, id, (node) => {
|
|
2960
|
+
if (!isSsrRender(node)) {
|
|
2973
2961
|
return;
|
|
2974
2962
|
}
|
|
2975
|
-
const
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
const
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
}
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2963
|
+
const [componentCall, _, children] = node.arguments;
|
|
2964
|
+
if (!componentCall) {
|
|
2965
|
+
return;
|
|
2966
|
+
}
|
|
2967
|
+
if (componentCall.type === "Identifier" || componentCall.type === "MemberExpression" || componentCall.type === "CallExpression") {
|
|
2968
|
+
const componentName = getComponentName(node);
|
|
2969
|
+
if (!componentName || !COMPONENTS_IDENTIFIERS_RE.test(componentName) || children?.type !== "ObjectExpression") {
|
|
2970
|
+
return;
|
|
2971
|
+
}
|
|
2972
|
+
const isClientOnlyComponent = CLIENT_ONLY_NAME_RE.test(componentName);
|
|
2973
|
+
const slotsToRemove = isClientOnlyComponent ? children.properties.filter((prop) => prop.type === "Property" && prop.key.type === "Identifier" && !PLACEHOLDER_EXACT_RE.test(prop.key.name)) : children.properties;
|
|
2974
|
+
for (const slot of slotsToRemove) {
|
|
2975
|
+
s.remove(slot.start, slot.end + 1);
|
|
2976
|
+
const removedCode = `({${code.slice(slot.start, slot.end + 1)}})`;
|
|
2977
|
+
const currentState = s.toString();
|
|
2978
|
+
parseAndWalk(removedCode, id, (node2) => {
|
|
2979
|
+
if (!isSsrRender(node2)) {
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2982
|
+
const name = getComponentName(node2);
|
|
2983
|
+
if (!name) {
|
|
2984
|
+
return;
|
|
2985
|
+
}
|
|
2986
|
+
const nameToRemove = isComponentNotCalledInSetup(currentState, id, name);
|
|
2987
|
+
if (nameToRemove) {
|
|
2988
|
+
componentsToRemoveSet.add(nameToRemove);
|
|
2989
|
+
}
|
|
2990
|
+
});
|
|
2991
|
+
}
|
|
2994
2992
|
}
|
|
2993
|
+
});
|
|
2994
|
+
const componentsToRemove = [...componentsToRemoveSet];
|
|
2995
|
+
const removedNodes = /* @__PURE__ */ new WeakSet();
|
|
2996
|
+
for (const componentName of componentsToRemove) {
|
|
2997
|
+
removeImportDeclaration(ast, componentName, s);
|
|
2998
|
+
removeVariableDeclarator(ast, componentName, s, removedNodes);
|
|
2999
|
+
removeFromSetupReturn(ast, componentName, s);
|
|
3000
|
+
}
|
|
3001
|
+
if (s.hasChanged()) {
|
|
3002
|
+
return {
|
|
3003
|
+
code: s.toString(),
|
|
3004
|
+
map: options.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
3005
|
+
};
|
|
2995
3006
|
}
|
|
2996
|
-
});
|
|
2997
|
-
const componentsToRemove = [...componentsToRemoveSet];
|
|
2998
|
-
const removedNodes = /* @__PURE__ */ new WeakSet();
|
|
2999
|
-
for (const componentName of componentsToRemove) {
|
|
3000
|
-
removeImportDeclaration(ast, componentName, s);
|
|
3001
|
-
removeVariableDeclarator(ast, componentName, s, removedNodes);
|
|
3002
|
-
removeFromSetupReturn(ast, componentName, s);
|
|
3003
|
-
}
|
|
3004
|
-
if (s.hasChanged()) {
|
|
3005
|
-
return {
|
|
3006
|
-
code: s.toString(),
|
|
3007
|
-
map: options.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
3008
|
-
};
|
|
3009
3007
|
}
|
|
3010
3008
|
}
|
|
3011
3009
|
};
|
|
@@ -3916,102 +3914,1392 @@ function addDeclarationTemplates(ctx, options) {
|
|
|
3916
3914
|
if (!nitroImport || i.dtsDisabled || nitroImport.dtsDisabled) {
|
|
3917
3915
|
continue;
|
|
3918
3916
|
}
|
|
3917
|
+
if (i.from !== nitroImport.from) {
|
|
3918
|
+
continue;
|
|
3919
|
+
}
|
|
3919
3920
|
sharedImports.push(i);
|
|
3920
3921
|
}
|
|
3921
3922
|
await cacheImportPaths(sharedImports);
|
|
3922
|
-
|
|
3923
|
+
const handCraftedDeclarations = `
|
|
3924
|
+
const useRuntimeConfig: (event?: import('h3').H3Event) => import('nuxt/schema').RuntimeConfig
|
|
3925
|
+
const useAppConfig: () => import('nuxt/schema').AppConfig
|
|
3926
|
+
const defineAppConfig: <C extends import('nuxt/schema').AppConfigInput>(config: C) => C
|
|
3927
|
+
const createError: typeof import('h3')['createError']
|
|
3928
|
+
const setResponseStatus: typeof import('h3')['setResponseStatus']`;
|
|
3929
|
+
return GENERATED_BY_COMMENT + toTypeDeclarationFile(sharedImports, { resolvePath: r }).replace(
|
|
3930
|
+
/^declare global \{$/m,
|
|
3931
|
+
`declare global {${handCraftedDeclarations}`
|
|
3932
|
+
);
|
|
3923
3933
|
}
|
|
3924
3934
|
});
|
|
3925
3935
|
}
|
|
3926
3936
|
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
const pkg = {
|
|
3948
|
-
version: version};
|
|
3949
|
-
|
|
3950
|
-
function createImportProtectionPatterns(nuxt, options) {
|
|
3951
|
-
const patterns = [];
|
|
3952
|
-
const context = contextFlags[options.context];
|
|
3953
|
-
patterns.push([
|
|
3954
|
-
/^(nuxt|nuxt3|nuxt-nightly)$/,
|
|
3955
|
-
`\`nuxt\`, or \`nuxt-nightly\` cannot be imported directly in ${context}.` + (options.context === "nuxt-app" ? " Instead, import runtime Nuxt composables from `#app` or `#imports`." : "")
|
|
3956
|
-
]);
|
|
3957
|
-
patterns.push([
|
|
3958
|
-
/^((~|~~|@|@@)?\/)?nuxt\.config(\.|$)/,
|
|
3959
|
-
"Importing directly from a `nuxt.config` file is not allowed. Instead, use runtime config or a module."
|
|
3960
|
-
]);
|
|
3961
|
-
patterns.push([/(^|node_modules\/)@vue\/composition-api/]);
|
|
3962
|
-
for (const mod of nuxt.options._installedModules) {
|
|
3963
|
-
if (mod.entryPath) {
|
|
3964
|
-
patterns.push([
|
|
3965
|
-
new RegExp(`^${escapeRE(mod.entryPath)}$`),
|
|
3966
|
-
"Importing directly from module entry-points is not allowed."
|
|
3967
|
-
]);
|
|
3968
|
-
}
|
|
3969
|
-
}
|
|
3970
|
-
for (const i of [/(^|node_modules\/)@nuxt\/(cli|kit|test-utils)/, /(^|node_modules\/)nuxi/, /(^|node_modules\/)nitro(?:pack)?(?:-nightly)?(?:$|\/)(?!(?:dist\/)?(?:node_modules|presets|runtime|types))/, /(^|node_modules\/)nuxt\/(config|kit|schema)/]) {
|
|
3971
|
-
patterns.push([i, `This module cannot be imported in ${context}.`]);
|
|
3972
|
-
}
|
|
3973
|
-
if (options.context === "nitro-app" || options.context === "shared") {
|
|
3974
|
-
for (const i of ["#app", /^#build(\/|$)/]) {
|
|
3975
|
-
patterns.push([i, `Vue app aliases are not allowed in ${context}.`]);
|
|
3937
|
+
function createScanPluginContext(code, filePath) {
|
|
3938
|
+
let parseResult = null;
|
|
3939
|
+
let parsedStaticImports = null;
|
|
3940
|
+
const pluginScanThisContext = {
|
|
3941
|
+
walkParsed: (...args) => {
|
|
3942
|
+
if (parseResult) {
|
|
3943
|
+
const options = typeof args[0] === "function" ? { enter: args[0] } : args[0];
|
|
3944
|
+
walk(parseResult.program, options);
|
|
3945
|
+
return parseResult;
|
|
3946
|
+
}
|
|
3947
|
+
parseResult = parseAndWalk.call(null, code, filePath, args[0]);
|
|
3948
|
+
return parseResult;
|
|
3949
|
+
},
|
|
3950
|
+
getParsedStaticImports: () => {
|
|
3951
|
+
if (parsedStaticImports) {
|
|
3952
|
+
return parsedStaticImports;
|
|
3953
|
+
}
|
|
3954
|
+
const imports = findStaticImports(code);
|
|
3955
|
+
parsedStaticImports = imports.map((i) => parseStaticImport(i));
|
|
3956
|
+
return parsedStaticImports;
|
|
3976
3957
|
}
|
|
3958
|
+
};
|
|
3959
|
+
return pluginScanThisContext;
|
|
3960
|
+
}
|
|
3961
|
+
function matchWithStringOrRegex(value, matcher) {
|
|
3962
|
+
if (typeof matcher === "string") {
|
|
3963
|
+
return value === matcher;
|
|
3964
|
+
} else if (matcher instanceof RegExp) {
|
|
3965
|
+
return matcher.test(value);
|
|
3977
3966
|
}
|
|
3978
|
-
|
|
3979
|
-
patterns.push([
|
|
3980
|
-
new RegExp(escapeRE(relative(nuxt.options.srcDir, resolve(nuxt.options.srcDir, nuxt.options.serverDir || "server"))) + "\\/(api|routes|middleware|plugins)\\/"),
|
|
3981
|
-
`Importing from server is not allowed in ${context}.`
|
|
3982
|
-
]);
|
|
3983
|
-
patterns.push([
|
|
3984
|
-
/^#server(\/|$)/,
|
|
3985
|
-
`Server aliases are not allowed in ${context}.`
|
|
3986
|
-
]);
|
|
3987
|
-
}
|
|
3988
|
-
return patterns;
|
|
3967
|
+
return false;
|
|
3989
3968
|
}
|
|
3990
|
-
const contextFlags = {
|
|
3991
|
-
"nitro-app": "server runtime",
|
|
3992
|
-
"nuxt-app": "the Vue part of your app",
|
|
3993
|
-
"shared": "the #shared directory"
|
|
3994
|
-
};
|
|
3995
3969
|
|
|
3996
|
-
|
|
3997
|
-
const
|
|
3998
|
-
const
|
|
3999
|
-
const
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
3970
|
+
function processImports(imports, alias) {
|
|
3971
|
+
const directImports = /* @__PURE__ */ new Map();
|
|
3972
|
+
const namespaces = /* @__PURE__ */ new Map();
|
|
3973
|
+
for (const i of imports) {
|
|
3974
|
+
const resolvedSpecifier = stripExtension(resolveAlias$1(i.specifier, alias));
|
|
3975
|
+
const namedImports = i.namedImports ?? {};
|
|
3976
|
+
for (const originalIdentifier in namedImports) {
|
|
3977
|
+
const localIdentifier = namedImports[originalIdentifier] || originalIdentifier;
|
|
3978
|
+
directImports.set(localIdentifier, {
|
|
3979
|
+
originalName: originalIdentifier,
|
|
3980
|
+
source: resolvedSpecifier
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
if (i.namespacedImport || i.defaultImport) {
|
|
3984
|
+
if (!namespaces.has(resolvedSpecifier)) {
|
|
3985
|
+
namespaces.set(resolvedSpecifier, {
|
|
3986
|
+
namespaces: /* @__PURE__ */ new Set()
|
|
3987
|
+
});
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
if (i.defaultImport) {
|
|
3991
|
+
const namespace = i.defaultImport;
|
|
3992
|
+
const entry = namespaces.get(resolvedSpecifier);
|
|
3993
|
+
entry.namespaces.add(namespace);
|
|
3994
|
+
directImports.set(i.defaultImport, {
|
|
3995
|
+
originalName: "default",
|
|
3996
|
+
source: resolvedSpecifier
|
|
3997
|
+
});
|
|
3998
|
+
} else if (i.namespacedImport) {
|
|
3999
|
+
const namespace = i.namespacedImport;
|
|
4000
|
+
const entry = namespaces.get(resolvedSpecifier);
|
|
4001
|
+
entry.namespaces.add(namespace);
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
return {
|
|
4005
|
+
directImports,
|
|
4006
|
+
namespaces
|
|
4007
|
+
};
|
|
4008
|
+
}
|
|
4009
|
+
function parseStaticFunctionCall(node, filter) {
|
|
4010
|
+
const callExpression = node.type === "CallExpression" ? node : node.type === "ChainExpression" && node.expression.type === "CallExpression" ? node.expression : null;
|
|
4011
|
+
if (!callExpression) {
|
|
4012
|
+
return null;
|
|
4013
|
+
}
|
|
4014
|
+
let functionName;
|
|
4015
|
+
let identifierNode;
|
|
4016
|
+
if (callExpression.callee.type === "Identifier") {
|
|
4017
|
+
functionName = callExpression.callee.name;
|
|
4018
|
+
identifierNode = callExpression.callee;
|
|
4019
|
+
} else if (callExpression.callee.type === "ParenthesizedExpression") {
|
|
4020
|
+
if (callExpression.callee.expression.type === "Identifier") {
|
|
4021
|
+
functionName = callExpression.callee.expression.name;
|
|
4022
|
+
identifierNode = callExpression.callee;
|
|
4023
|
+
} else if ((callExpression.callee.expression.type === "TSAsExpression" || callExpression.callee.expression.type === "TSTypeAssertion" || callExpression.callee.expression.type === "TSNonNullExpression") && callExpression.callee.expression.expression.type === "Identifier") {
|
|
4024
|
+
functionName = callExpression.callee.expression.expression.name;
|
|
4025
|
+
identifierNode = callExpression.callee;
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
if (functionName && identifierNode && filter.test(functionName)) {
|
|
4029
|
+
return {
|
|
4030
|
+
name: functionName,
|
|
4031
|
+
namespace: null,
|
|
4032
|
+
node: identifierNode,
|
|
4033
|
+
callExpression
|
|
4034
|
+
};
|
|
4035
|
+
}
|
|
4036
|
+
function getParsedMemberExpression(memberExpression) {
|
|
4037
|
+
let memberObjectName;
|
|
4038
|
+
if (memberExpression.object.type === "Identifier") {
|
|
4039
|
+
memberObjectName = memberExpression.object.name;
|
|
4040
|
+
} else if (memberExpression.object.type === "ParenthesizedExpression") {
|
|
4041
|
+
if (memberExpression.object.expression.type === "Identifier") {
|
|
4042
|
+
memberObjectName = memberExpression.object.expression.name;
|
|
4043
|
+
} else if ((memberExpression.object.expression.type === "TSAsExpression" || memberExpression.object.expression.type === "TSTypeAssertion" || memberExpression.object.expression.type === "TSNonNullExpression") && memberExpression.object.expression.expression.type === "Identifier") {
|
|
4044
|
+
memberObjectName = memberExpression.object.expression.expression.name;
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
if (memberObjectName) {
|
|
4048
|
+
if (memberExpression.property.type === "Identifier" && filter.test(memberExpression.property.name)) {
|
|
4049
|
+
return {
|
|
4050
|
+
name: memberExpression.property.name,
|
|
4051
|
+
namespace: memberObjectName,
|
|
4052
|
+
node: memberExpression.property
|
|
4053
|
+
};
|
|
4054
|
+
}
|
|
4055
|
+
if (memberExpression.property.type === "Literal" && typeof memberExpression.property.value === "string" && filter.test(memberExpression.property.value)) {
|
|
4056
|
+
return {
|
|
4057
|
+
name: memberExpression.property.value,
|
|
4058
|
+
namespace: memberObjectName,
|
|
4059
|
+
node: memberExpression
|
|
4060
|
+
};
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
return null;
|
|
4064
|
+
}
|
|
4065
|
+
if (callExpression.callee.type === "MemberExpression") {
|
|
4066
|
+
const val = getParsedMemberExpression(callExpression.callee);
|
|
4067
|
+
if (val) {
|
|
4068
|
+
return {
|
|
4069
|
+
...val,
|
|
4070
|
+
callExpression
|
|
4071
|
+
};
|
|
4072
|
+
}
|
|
4073
|
+
} else if (callExpression.callee.type === "ParenthesizedExpression" && callExpression.callee.expression.type === "MemberExpression") {
|
|
4074
|
+
const val = getParsedMemberExpression(callExpression.callee.expression);
|
|
4075
|
+
if (val) {
|
|
4076
|
+
return {
|
|
4077
|
+
...val,
|
|
4078
|
+
node: callExpression.callee,
|
|
4079
|
+
callExpression
|
|
4080
|
+
};
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
return null;
|
|
4084
|
+
}
|
|
4085
|
+
function parseStaticExportIdentifiers(node, filter) {
|
|
4086
|
+
if (node.type === "ExportNamedDeclaration" && node.exportKind !== "type") {
|
|
4087
|
+
if (node.declaration?.type === "VariableDeclaration") {
|
|
4088
|
+
return node.declaration.declarations.map((d) => {
|
|
4089
|
+
if (d.id.type === "Identifier" && (true)) {
|
|
4090
|
+
return {
|
|
4091
|
+
localName: d.id.name,
|
|
4092
|
+
exportedName: d.id.name
|
|
4093
|
+
};
|
|
4094
|
+
}
|
|
4095
|
+
return null;
|
|
4096
|
+
}).filter((v) => !!v);
|
|
4097
|
+
}
|
|
4098
|
+
if (node.declaration?.type === "FunctionDeclaration") {
|
|
4099
|
+
if (node.declaration.id?.type === "Identifier" && (true)) {
|
|
4100
|
+
return [{
|
|
4101
|
+
localName: node.declaration.id.name,
|
|
4102
|
+
exportedName: node.declaration.id.name
|
|
4103
|
+
}];
|
|
4104
|
+
}
|
|
4105
|
+
return [];
|
|
4106
|
+
}
|
|
4107
|
+
if (node.declaration?.type === "ClassDeclaration") {
|
|
4108
|
+
if (node.declaration.id?.type === "Identifier" && (true)) {
|
|
4109
|
+
return [{
|
|
4110
|
+
localName: node.declaration.id.name,
|
|
4111
|
+
exportedName: node.declaration.id.name
|
|
4112
|
+
}];
|
|
4113
|
+
}
|
|
4114
|
+
return [];
|
|
4115
|
+
}
|
|
4116
|
+
if (node.specifiers && node.specifiers.length) {
|
|
4117
|
+
return node.specifiers.map((s) => {
|
|
4118
|
+
if (s.exported.type === "Identifier" && s.exportKind !== "type" && s.local.type === "Identifier" && (true)) {
|
|
4119
|
+
return {
|
|
4120
|
+
localName: s.local.name,
|
|
4121
|
+
exportedName: s.exported.name
|
|
4122
|
+
};
|
|
4123
|
+
}
|
|
4124
|
+
return null;
|
|
4125
|
+
}).filter((v) => !!v);
|
|
4126
|
+
}
|
|
4127
|
+
return [];
|
|
4128
|
+
}
|
|
4129
|
+
if (node.type === "ExportDefaultDeclaration" && (!node.exportKind || node.exportKind === "value")) {
|
|
4130
|
+
if (node.declaration.type === "Identifier") {
|
|
4131
|
+
return [{
|
|
4132
|
+
localName: node.declaration.name,
|
|
4133
|
+
exportedName: "default"
|
|
4134
|
+
}];
|
|
4135
|
+
}
|
|
4136
|
+
if (node.declaration.type === "FunctionDeclaration") {
|
|
4137
|
+
if (node.declaration.id?.type === "Identifier") {
|
|
4138
|
+
return [{
|
|
4139
|
+
localName: node.declaration.id.name,
|
|
4140
|
+
exportedName: "default"
|
|
4141
|
+
}];
|
|
4142
|
+
}
|
|
4143
|
+
return [];
|
|
4144
|
+
}
|
|
4145
|
+
if (node.declaration.type === "ClassDeclaration") {
|
|
4146
|
+
if (node.declaration.id?.type === "Identifier") {
|
|
4147
|
+
return [{
|
|
4148
|
+
localName: node.declaration.id.name,
|
|
4149
|
+
exportedName: "default"
|
|
4150
|
+
}];
|
|
4151
|
+
}
|
|
4152
|
+
return [];
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
if (node.type === "TSExportAssignment") {
|
|
4156
|
+
if (node.expression.type === "Identifier") {
|
|
4157
|
+
{
|
|
4158
|
+
return [{
|
|
4159
|
+
localName: node.expression.name,
|
|
4160
|
+
exportedName: "default"
|
|
4161
|
+
}];
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
}
|
|
4165
|
+
return [];
|
|
4166
|
+
}
|
|
4167
|
+
|
|
4168
|
+
function parseKeyedFunctionFactory(node, filter, scopeTracker) {
|
|
4169
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
4170
|
+
let processVariableDeclarator = function(node2) {
|
|
4171
|
+
if (node2.init?.type !== "CallExpression" && node2.init?.type !== "ChainExpression") {
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
const functionCallMeta = parseStaticFunctionCall(node2.init, filter);
|
|
4175
|
+
if (functionCallMeta && node2?.id.type === "Identifier") {
|
|
4176
|
+
parsed.push({
|
|
4177
|
+
factoryName: functionCallMeta.name,
|
|
4178
|
+
factoryNode: functionCallMeta.node,
|
|
4179
|
+
functionName: node2.id.name,
|
|
4180
|
+
namespace: functionCallMeta.namespace
|
|
4181
|
+
});
|
|
4182
|
+
}
|
|
4183
|
+
};
|
|
4184
|
+
const parsed = [];
|
|
4185
|
+
if (node.declaration?.type === "VariableDeclaration") {
|
|
4186
|
+
for (const d of node.declaration.declarations) {
|
|
4187
|
+
processVariableDeclarator(d);
|
|
4188
|
+
}
|
|
4189
|
+
} else if (node.specifiers.length) {
|
|
4190
|
+
for (const specifier of node.specifiers) {
|
|
4191
|
+
if (specifier.type !== "ExportSpecifier" || specifier.exported.type !== "Identifier" || specifier.local.type !== "Identifier") {
|
|
4192
|
+
continue;
|
|
4193
|
+
}
|
|
4194
|
+
const declaration = scopeTracker.getDeclaration(specifier.local.name);
|
|
4195
|
+
if (declaration?.type !== "Variable") {
|
|
4196
|
+
continue;
|
|
4197
|
+
}
|
|
4198
|
+
for (const d of declaration.variableNode.declarations) {
|
|
4199
|
+
processVariableDeclarator(d);
|
|
4200
|
+
}
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
return parsed;
|
|
4204
|
+
}
|
|
4205
|
+
if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "CallExpression") {
|
|
4206
|
+
const functionCallMeta = parseStaticFunctionCall(node.declaration, filter);
|
|
4207
|
+
if (functionCallMeta) {
|
|
4208
|
+
return [{
|
|
4209
|
+
factoryName: functionCallMeta.name,
|
|
4210
|
+
factoryNode: functionCallMeta.node,
|
|
4211
|
+
functionName: "default",
|
|
4212
|
+
namespace: functionCallMeta.namespace
|
|
4213
|
+
}];
|
|
4214
|
+
}
|
|
4215
|
+
return [];
|
|
4216
|
+
}
|
|
4217
|
+
return [];
|
|
4218
|
+
}
|
|
4219
|
+
function createFactoryProcessor(filePath, scopeTracker, namesToFactoryMeta, imports, autoImportsToSources, alias) {
|
|
4220
|
+
const { directImports, namespaces } = processImports(imports, alias);
|
|
4221
|
+
const localFactoryNames = new Set(namesToFactoryMeta.keys());
|
|
4222
|
+
for (const [localName, directImport] of directImports) {
|
|
4223
|
+
if (namesToFactoryMeta.has(directImport.originalName)) {
|
|
4224
|
+
localFactoryNames.add(localName);
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
const LOCAL_FACTORY_NAMES_RE = new RegExp(`\\b(${[...localFactoryNames].map((f) => escapeRE(f)).join("|")})\\b`);
|
|
4228
|
+
function _resolvePath(path) {
|
|
4229
|
+
let p = path;
|
|
4230
|
+
if (isAbsolute(p)) {
|
|
4231
|
+
return p;
|
|
4232
|
+
}
|
|
4233
|
+
p = resolveAlias$1(p, alias);
|
|
4234
|
+
if (isAbsolute(p)) {
|
|
4235
|
+
return p;
|
|
4236
|
+
}
|
|
4237
|
+
return join(parse$1(filePath).dir, p);
|
|
4238
|
+
}
|
|
4239
|
+
function getFactoryByLocalName(localName) {
|
|
4240
|
+
if (!localName) {
|
|
4241
|
+
return void 0;
|
|
4242
|
+
}
|
|
4243
|
+
const directImport = directImports.get(localName);
|
|
4244
|
+
if (directImport) {
|
|
4245
|
+
return namesToFactoryMeta.get(directImport.originalName);
|
|
4246
|
+
}
|
|
4247
|
+
return namesToFactoryMeta.get(localName);
|
|
4248
|
+
}
|
|
4249
|
+
function processFactory(walkContext, node, handler) {
|
|
4250
|
+
const parsedFactoryCalls = parseKeyedFunctionFactory(node, LOCAL_FACTORY_NAMES_RE, scopeTracker);
|
|
4251
|
+
if (!parsedFactoryCalls.length) {
|
|
4252
|
+
return;
|
|
4253
|
+
}
|
|
4254
|
+
for (const parsedFactoryCall of parsedFactoryCalls) {
|
|
4255
|
+
let isFactoryImport = function(node2) {
|
|
4256
|
+
return node2?.type === "Import" && node2.importNode.importKind !== "type";
|
|
4257
|
+
};
|
|
4258
|
+
const factoryMeta = getFactoryByLocalName(parsedFactoryCall.factoryName);
|
|
4259
|
+
if (!factoryMeta) {
|
|
4260
|
+
logger.error(`[nuxt:compiler] No factory function found for \`${parsedFactoryCall.functionName}\` in file \`${filePath}\`. This is a Nuxt bug.`);
|
|
4261
|
+
continue;
|
|
4262
|
+
}
|
|
4263
|
+
const scopeTrackerNode = scopeTracker.getDeclaration(!parsedFactoryCall.namespace ? parsedFactoryCall.factoryName : parsedFactoryCall.namespace);
|
|
4264
|
+
let importSourceResolved;
|
|
4265
|
+
if (isFactoryImport(scopeTrackerNode)) {
|
|
4266
|
+
importSourceResolved = stripExtension(_resolvePath(scopeTrackerNode.importNode.source.value));
|
|
4267
|
+
} else if (!scopeTrackerNode) {
|
|
4268
|
+
const autoImportedSource = autoImportsToSources?.get(factoryMeta.name);
|
|
4269
|
+
if (autoImportedSource) {
|
|
4270
|
+
importSourceResolved = stripExtension(_resolvePath(autoImportedSource));
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
if (!importSourceResolved) {
|
|
4274
|
+
continue;
|
|
4275
|
+
}
|
|
4276
|
+
const resolvedFactorySource = factoryMeta.source;
|
|
4277
|
+
if (!parsedFactoryCall.namespace && // and the factory is imported directly
|
|
4278
|
+
(isFactoryImport(scopeTrackerNode) && // import { createUseFetch } from '...'
|
|
4279
|
+
(scopeTrackerNode.node.type === "ImportSpecifier" && scopeTrackerNode.node.importKind !== "type" || scopeTrackerNode.node.type === "ImportDefaultSpecifier" && factoryMeta.name === "default") && importSourceResolved === resolvedFactorySource || !scopeTrackerNode && importSourceResolved === resolvedFactorySource)) {
|
|
4280
|
+
handler({ parseFactoryResult: parsedFactoryCall, factory: factoryMeta });
|
|
4281
|
+
walkContext.skip();
|
|
4282
|
+
continue;
|
|
4283
|
+
}
|
|
4284
|
+
if (parsedFactoryCall.namespace) {
|
|
4285
|
+
const namespacedImportMeta = namespaces.get(resolvedFactorySource);
|
|
4286
|
+
const namespaceScopeTrackerNode = scopeTracker.getDeclaration(parsedFactoryCall.namespace);
|
|
4287
|
+
if (namespacedImportMeta && namespacedImportMeta.namespaces.has(parsedFactoryCall.namespace) && namespaceScopeTrackerNode?.type === "Import" && namespaceScopeTrackerNode.node.type === "ImportNamespaceSpecifier") {
|
|
4288
|
+
handler({ parseFactoryResult: parsedFactoryCall, factory: factoryMeta });
|
|
4289
|
+
}
|
|
4290
|
+
walkContext.skip();
|
|
4291
|
+
continue;
|
|
4292
|
+
}
|
|
4293
|
+
logger.debug(`[nuxt:compiler] The factory function \`${factoryMeta.name}\` used to create \`${parsedFactoryCall.functionName}\` in file \`${filePath}\` is not imported and is not in auto-imports. Skipping processing.`);
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
return {
|
|
4297
|
+
processFactory
|
|
4298
|
+
};
|
|
4299
|
+
}
|
|
4300
|
+
function scanFileForFactories(id, code, namesToFactoryMeta, autoImportsToSources, alias) {
|
|
4301
|
+
const results = [];
|
|
4302
|
+
const context = createScanPluginContext(code, id);
|
|
4303
|
+
const scopeTracker = new ScopeTracker({
|
|
4304
|
+
preserveExitedScopes: true
|
|
4305
|
+
});
|
|
4306
|
+
const { processFactory } = createFactoryProcessor(id, scopeTracker, namesToFactoryMeta, context.getParsedStaticImports(), autoImportsToSources, alias);
|
|
4307
|
+
context.walkParsed({
|
|
4308
|
+
scopeTracker
|
|
4309
|
+
});
|
|
4310
|
+
scopeTracker.freeze();
|
|
4311
|
+
let isWalkingSupportedSubtree = false;
|
|
4312
|
+
context.walkParsed({
|
|
4313
|
+
scopeTracker,
|
|
4314
|
+
enter(node) {
|
|
4315
|
+
if (node.type !== "Program" && !isWalkingSupportedSubtree && node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration" && node.type !== "ImportDeclaration") {
|
|
4316
|
+
this.skip();
|
|
4317
|
+
}
|
|
4318
|
+
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") {
|
|
4319
|
+
return;
|
|
4320
|
+
}
|
|
4321
|
+
isWalkingSupportedSubtree = true;
|
|
4322
|
+
processFactory(this, node, ({ parseFactoryResult, factory }) => {
|
|
4323
|
+
results.push({
|
|
4324
|
+
name: parseFactoryResult.functionName,
|
|
4325
|
+
source: id,
|
|
4326
|
+
argumentLength: factory.argumentLength
|
|
4327
|
+
});
|
|
4328
|
+
});
|
|
4329
|
+
},
|
|
4330
|
+
leave(node) {
|
|
4331
|
+
if (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ImportDeclaration") {
|
|
4332
|
+
isWalkingSupportedSubtree = false;
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
});
|
|
4336
|
+
return results;
|
|
4337
|
+
}
|
|
4338
|
+
const KeyedFunctionFactoriesScanPlugin = (options) => {
|
|
4339
|
+
const fileResults = /* @__PURE__ */ new Map();
|
|
4340
|
+
const namesToFactoryMeta = new Map(options.factories.map((f) => [f.name, {
|
|
4341
|
+
...f,
|
|
4342
|
+
source: stripExtension(resolveAlias$1(f.source, options.alias))
|
|
4343
|
+
}]));
|
|
4344
|
+
const KEYED_FUNCTION_FACTORY_NAMES_RE = new RegExp(`\\b(${options.factories.map((f) => escapeRE(f.name)).join("|")})\\b`);
|
|
4345
|
+
const result = {
|
|
4346
|
+
fileResults,
|
|
4347
|
+
factoryNamesRegex: KEYED_FUNCTION_FACTORY_NAMES_RE,
|
|
4348
|
+
namesToFactoryMeta
|
|
4349
|
+
};
|
|
4350
|
+
return {
|
|
4351
|
+
result,
|
|
4352
|
+
name: "nuxt:keyed-function-factories",
|
|
4353
|
+
filter: {
|
|
4354
|
+
id: { include: JS_EXT_RE },
|
|
4355
|
+
code: { include: KEYED_FUNCTION_FACTORY_NAMES_RE }
|
|
4356
|
+
},
|
|
4357
|
+
scan({ id, autoImportsToSources }) {
|
|
4358
|
+
const results = [];
|
|
4359
|
+
const scopeTracker = new ScopeTracker({
|
|
4360
|
+
preserveExitedScopes: true
|
|
4361
|
+
});
|
|
4362
|
+
const { processFactory } = createFactoryProcessor(id, scopeTracker, namesToFactoryMeta, this.getParsedStaticImports(), autoImportsToSources, options.alias);
|
|
4363
|
+
this.walkParsed({
|
|
4364
|
+
scopeTracker
|
|
4365
|
+
});
|
|
4366
|
+
scopeTracker.freeze();
|
|
4367
|
+
let isWalkingSupportedSubtree = false;
|
|
4368
|
+
this.walkParsed({
|
|
4369
|
+
scopeTracker,
|
|
4370
|
+
enter(node) {
|
|
4371
|
+
if (node.type !== "Program" && !isWalkingSupportedSubtree && node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration" && node.type !== "ImportDeclaration") {
|
|
4372
|
+
this.skip();
|
|
4373
|
+
}
|
|
4374
|
+
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") {
|
|
4375
|
+
return;
|
|
4376
|
+
}
|
|
4377
|
+
isWalkingSupportedSubtree = true;
|
|
4378
|
+
processFactory(this, node, ({ parseFactoryResult, factory }) => {
|
|
4379
|
+
results.push({
|
|
4380
|
+
name: parseFactoryResult.functionName,
|
|
4381
|
+
source: id,
|
|
4382
|
+
argumentLength: factory.argumentLength
|
|
4383
|
+
});
|
|
4384
|
+
});
|
|
4385
|
+
},
|
|
4386
|
+
leave(node) {
|
|
4387
|
+
if (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ImportDeclaration") {
|
|
4388
|
+
isWalkingSupportedSubtree = false;
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
});
|
|
4392
|
+
fileResults.set(id, results);
|
|
4393
|
+
},
|
|
4394
|
+
afterScan: (nuxt) => {
|
|
4395
|
+
for (const functions of fileResults.values()) {
|
|
4396
|
+
nuxt.options.optimization.keyedComposables.push(...functions);
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
};
|
|
4400
|
+
};
|
|
4401
|
+
const KeyedFunctionFactoriesPlugin = (options) => createUnplugin(() => {
|
|
4402
|
+
const namesToFactoryMeta = new Map(options.factories.map((f) => [f.name, {
|
|
4403
|
+
...f,
|
|
4404
|
+
source: stripExtension(resolveAlias$1(f.source, options.alias))
|
|
4405
|
+
}]));
|
|
4406
|
+
const KEYED_FUNCTION_FACTORY_NAMES_RE = new RegExp(`\\b(${options.factories.map((f) => escapeRE(f.name)).join("|")})\\b`);
|
|
4407
|
+
return {
|
|
4408
|
+
name: "nuxt:compiler:keyed-function-factories",
|
|
4409
|
+
enforce: "post",
|
|
4410
|
+
transform: {
|
|
4411
|
+
filter: {
|
|
4412
|
+
id: {
|
|
4413
|
+
include: JS_EXT_RE,
|
|
4414
|
+
exclude: [NUXT_LIB_RE, STYLE_QUERY_RE$1, MACRO_QUERY_RE$2]
|
|
4415
|
+
},
|
|
4416
|
+
code: { include: KEYED_FUNCTION_FACTORY_NAMES_RE }
|
|
4417
|
+
},
|
|
4418
|
+
async handler(code, id) {
|
|
4419
|
+
const s = new MagicString(code);
|
|
4420
|
+
const scopeTracker = new ScopeTracker({
|
|
4421
|
+
preserveExitedScopes: true
|
|
4422
|
+
});
|
|
4423
|
+
const autoImports = await options.getAutoImports();
|
|
4424
|
+
const autoImportsToSources = new Map(autoImports.map((i) => [i.as || i.name, i.from]));
|
|
4425
|
+
const { processFactory } = createFactoryProcessor(
|
|
4426
|
+
id,
|
|
4427
|
+
scopeTracker,
|
|
4428
|
+
namesToFactoryMeta,
|
|
4429
|
+
findStaticImports(code).map((i) => parseStaticImport(i)),
|
|
4430
|
+
autoImportsToSources,
|
|
4431
|
+
options.alias
|
|
4432
|
+
);
|
|
4433
|
+
function rewriteFactoryMacro(node) {
|
|
4434
|
+
if (node.type === "Identifier") {
|
|
4435
|
+
if (code[node.end] === "?" && code[node.end + 1] === ".") {
|
|
4436
|
+
s.overwrite(
|
|
4437
|
+
node.start,
|
|
4438
|
+
node.end + 2,
|
|
4439
|
+
`${node.name}?.__nuxt_factory`
|
|
4440
|
+
);
|
|
4441
|
+
} else {
|
|
4442
|
+
s.overwrite(
|
|
4443
|
+
node.start,
|
|
4444
|
+
node.end,
|
|
4445
|
+
`${node.name}.__nuxt_factory`
|
|
4446
|
+
);
|
|
4447
|
+
}
|
|
4448
|
+
} else if (code[node.end] === "?" && code[node.end + 1] === ".") {
|
|
4449
|
+
s.appendLeft(node.end + 2, "__nuxt_factory");
|
|
4450
|
+
} else {
|
|
4451
|
+
s.appendLeft(node.end, ".__nuxt_factory");
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
const { program } = parseAndWalk(code, id, {
|
|
4455
|
+
scopeTracker
|
|
4456
|
+
});
|
|
4457
|
+
scopeTracker.freeze();
|
|
4458
|
+
walk(program, {
|
|
4459
|
+
// no need for a scope tracker pre-pass, since we only care about imports
|
|
4460
|
+
// and we only consider the root scope (because that's where an export would be - so no shadowing)
|
|
4461
|
+
scopeTracker,
|
|
4462
|
+
enter(node) {
|
|
4463
|
+
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") {
|
|
4464
|
+
return;
|
|
4465
|
+
}
|
|
4466
|
+
processFactory(this, node, ({ parseFactoryResult }) => {
|
|
4467
|
+
rewriteFactoryMacro(parseFactoryResult.factoryNode);
|
|
4468
|
+
});
|
|
4469
|
+
}
|
|
4470
|
+
});
|
|
4471
|
+
if (s.hasChanged()) {
|
|
4472
|
+
return {
|
|
4473
|
+
code: s.toString(),
|
|
4474
|
+
map: options.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
4475
|
+
};
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
};
|
|
4480
|
+
});
|
|
4481
|
+
|
|
4482
|
+
const stringTypes = ["Literal", "TemplateLiteral"];
|
|
4483
|
+
const SUPPORTED_EXT_RE$1 = /^[^?]*\.(?:m?[jt]sx?|vue)(?:$|\?)/;
|
|
4484
|
+
const SCRIPT_RE$1 = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i;
|
|
4485
|
+
const NUXT_INJECTED_MARKER = "/* nuxt-injected */";
|
|
4486
|
+
function buildKeyedFunctionsState(keyedFunctions) {
|
|
4487
|
+
const namesToSourcesToFunctionMeta = /* @__PURE__ */ new Map();
|
|
4488
|
+
const defaultExportSources = /* @__PURE__ */ new Set();
|
|
4489
|
+
for (const f of keyedFunctions) {
|
|
4490
|
+
let functionName = f.name;
|
|
4491
|
+
const fnSource = typeof f.source === "string" ? stripExtension(f.source) : "";
|
|
4492
|
+
if (f.name === "default") {
|
|
4493
|
+
const parsedSource = parse$1(f.source);
|
|
4494
|
+
defaultExportSources.add(parsedSource.name);
|
|
4495
|
+
functionName = camelCase(parsedSource.name);
|
|
4496
|
+
}
|
|
4497
|
+
if (import.meta.dev) {
|
|
4498
|
+
const sourcesToFunctionMeta2 = namesToSourcesToFunctionMeta.get(functionName);
|
|
4499
|
+
const existingEntry = sourcesToFunctionMeta2?.get(fnSource);
|
|
4500
|
+
if (existingEntry?.source && existingEntry.source === fnSource) {
|
|
4501
|
+
logger.warn(`[nuxt:compiler] [keyed-functions] Duplicate function name \`${functionName}\`${functionName !== f.name ? ` defined as \`${f.name}\`` : ""} with ${f.source ? `the same source \`${f.source}\`` : "no source"} found. Overwriting the existing entry.`);
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
let sourcesToFunctionMeta = namesToSourcesToFunctionMeta.get(functionName);
|
|
4505
|
+
if (!sourcesToFunctionMeta) {
|
|
4506
|
+
sourcesToFunctionMeta = /* @__PURE__ */ new Map();
|
|
4507
|
+
namesToSourcesToFunctionMeta.set(functionName, sourcesToFunctionMeta);
|
|
4508
|
+
}
|
|
4509
|
+
sourcesToFunctionMeta.set(fnSource, {
|
|
4510
|
+
...f,
|
|
4511
|
+
// TODO: use only `fnSource` in Nuxt 5
|
|
4512
|
+
source: typeof f.source === "string" ? fnSource : f.source
|
|
4513
|
+
});
|
|
4514
|
+
}
|
|
4515
|
+
const sources = /* @__PURE__ */ new Set();
|
|
4516
|
+
for (const sourcesToFunctionMeta of namesToSourcesToFunctionMeta.values()) {
|
|
4517
|
+
for (const f of sourcesToFunctionMeta.values()) {
|
|
4518
|
+
if (f.source && typeof f.source === "string") {
|
|
4519
|
+
sources.add(f.source);
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
const codeIncludeRE = new RegExp(`\\b(${[...namesToSourcesToFunctionMeta.keys(), ...defaultExportSources].map((f) => escapeRE(f)).join("|")})\\b`);
|
|
4524
|
+
return { namesToSourcesToFunctionMeta, defaultExportSources, sources, codeIncludeRE };
|
|
4525
|
+
}
|
|
4526
|
+
const KeyedFunctionsPlugin = (options) => createUnplugin(() => {
|
|
4527
|
+
let state = buildKeyedFunctionsState(options.keyedFunctions);
|
|
4528
|
+
let lastKeyedFunctionsLength = options.keyedFunctions.length;
|
|
4529
|
+
function getState() {
|
|
4530
|
+
if (options.dev && options.getKeyedFunctions) {
|
|
4531
|
+
const current = options.getKeyedFunctions();
|
|
4532
|
+
if (current.length !== lastKeyedFunctionsLength) {
|
|
4533
|
+
state = buildKeyedFunctionsState(current);
|
|
4534
|
+
lastKeyedFunctionsLength = current.length;
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
return state;
|
|
4538
|
+
}
|
|
4539
|
+
return {
|
|
4540
|
+
name: "nuxt:compiler:keyed-functions",
|
|
4541
|
+
enforce: "post",
|
|
4542
|
+
transform: {
|
|
4543
|
+
filter: {
|
|
4544
|
+
id: {
|
|
4545
|
+
include: SUPPORTED_EXT_RE$1,
|
|
4546
|
+
exclude: [NUXT_LIB_RE, STYLE_QUERY_RE$1, MACRO_QUERY_RE$2]
|
|
4547
|
+
},
|
|
4548
|
+
// In dev mode, skip the static code filter to allow HMR-added composables to be processed.
|
|
4549
|
+
// In production, use the static regex for performance.
|
|
4550
|
+
...!options.dev && { code: { include: state.codeIncludeRE } }
|
|
4551
|
+
},
|
|
4552
|
+
async handler(code, _id) {
|
|
4553
|
+
const { namesToSourcesToFunctionMeta, sources } = getState();
|
|
4554
|
+
if (options.dev) {
|
|
4555
|
+
const { codeIncludeRE } = getState();
|
|
4556
|
+
if (!codeIncludeRE.test(code)) {
|
|
4557
|
+
return;
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
const { 0: script = code, index: codeIndex = 0 } = code.match(SCRIPT_RE$1) || { 0: code, index: 0 };
|
|
4561
|
+
const id = stripExtension(_id);
|
|
4562
|
+
const { directImports, namespaces } = processImports(findStaticImports(script).map((i) => parseStaticImport(i)), options.alias);
|
|
4563
|
+
const shouldConsiderExports = sources.has(id);
|
|
4564
|
+
const localNamesToExportedName = /* @__PURE__ */ new Map();
|
|
4565
|
+
const possibleLocalFunctionNames = new Set(namesToSourcesToFunctionMeta.keys());
|
|
4566
|
+
for (const [localName, directImport] of directImports) {
|
|
4567
|
+
const functionName = directImport.originalName === "default" ? camelCase(parse$1(directImport.source).name) : directImport.originalName;
|
|
4568
|
+
if (namesToSourcesToFunctionMeta.has(functionName)) {
|
|
4569
|
+
possibleLocalFunctionNames.add(localName);
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
const autoImports = await options.getAutoImports();
|
|
4573
|
+
const autoImportsToSources = new Map(autoImports.map((i) => [i.as || i.name, i.from]));
|
|
4574
|
+
function getFunctionMetaByLocalName(localName, source) {
|
|
4575
|
+
if (!localName) {
|
|
4576
|
+
return;
|
|
4577
|
+
}
|
|
4578
|
+
const exportedName = localNamesToExportedName.get(localName);
|
|
4579
|
+
if (exportedName) {
|
|
4580
|
+
return namesToSourcesToFunctionMeta.get(exportedName)?.get(source);
|
|
4581
|
+
}
|
|
4582
|
+
const directImport = directImports.get(localName);
|
|
4583
|
+
if (directImport) {
|
|
4584
|
+
const functionName = directImport.originalName === "default" ? camelCase(parse$1(directImport.source).name) : directImport.originalName;
|
|
4585
|
+
const sourcesToMetas = namesToSourcesToFunctionMeta.get(functionName);
|
|
4586
|
+
if (!sourcesToMetas) {
|
|
4587
|
+
return;
|
|
4588
|
+
}
|
|
4589
|
+
const fnMeta = sourcesToMetas.get(source);
|
|
4590
|
+
if (fnMeta) {
|
|
4591
|
+
return fnMeta;
|
|
4592
|
+
}
|
|
4593
|
+
if (source.startsWith(options.appDir)) {
|
|
4594
|
+
for (const [fnSource, meta] of sourcesToMetas) {
|
|
4595
|
+
if (meta.name !== functionName || !fnSource.startsWith(options.appDir)) {
|
|
4596
|
+
continue;
|
|
4597
|
+
}
|
|
4598
|
+
return meta;
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
const backwardsCompatibleFnMeta = sourcesToMetas.get("");
|
|
4602
|
+
if (backwardsCompatibleFnMeta?.source === void 0) {
|
|
4603
|
+
const autoImportResolvedSource = stripExtension(resolveAlias$1(autoImportsToSources.get(localName) ?? ""));
|
|
4604
|
+
if (autoImportResolvedSource === source) {
|
|
4605
|
+
return backwardsCompatibleFnMeta;
|
|
4606
|
+
}
|
|
4607
|
+
} else if (backwardsCompatibleFnMeta.source instanceof RegExp && backwardsCompatibleFnMeta.source.test(source)) {
|
|
4608
|
+
return backwardsCompatibleFnMeta;
|
|
4609
|
+
}
|
|
4610
|
+
return;
|
|
4611
|
+
}
|
|
4612
|
+
return namesToSourcesToFunctionMeta.get(localName)?.get(source);
|
|
4613
|
+
}
|
|
4614
|
+
function _resolvePath(path) {
|
|
4615
|
+
let p = path;
|
|
4616
|
+
if (isAbsolute(p)) {
|
|
4617
|
+
return p;
|
|
4618
|
+
}
|
|
4619
|
+
p = resolveAlias$1(p, options.alias);
|
|
4620
|
+
if (isAbsolute(p)) {
|
|
4621
|
+
return p;
|
|
4622
|
+
}
|
|
4623
|
+
return join(parse$1(id).dir, p);
|
|
4624
|
+
}
|
|
4625
|
+
const s = new MagicString(code);
|
|
4626
|
+
let count = 0;
|
|
4627
|
+
const scopeTracker = new ScopeTracker({
|
|
4628
|
+
preserveExitedScopes: true
|
|
4629
|
+
});
|
|
4630
|
+
const { program } = parseAndWalk(code, _id, {
|
|
4631
|
+
scopeTracker,
|
|
4632
|
+
enter(node) {
|
|
4633
|
+
if (!shouldConsiderExports) {
|
|
4634
|
+
return;
|
|
4635
|
+
}
|
|
4636
|
+
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") {
|
|
4637
|
+
return;
|
|
4638
|
+
}
|
|
4639
|
+
const result = parseStaticExportIdentifiers(node);
|
|
4640
|
+
for (const exportMeta of result) {
|
|
4641
|
+
const { localName, exportedName } = exportMeta;
|
|
4642
|
+
const functionName = exportedName === "default" ? camelCase(parse$1(id).name) : getFunctionMetaByLocalName(exportedName, id)?.name;
|
|
4643
|
+
if (!functionName) {
|
|
4644
|
+
continue;
|
|
4645
|
+
}
|
|
4646
|
+
localNamesToExportedName.set(localName, functionName);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
});
|
|
4650
|
+
scopeTracker.freeze();
|
|
4651
|
+
for (const localName of localNamesToExportedName.keys()) {
|
|
4652
|
+
possibleLocalFunctionNames.add(localName);
|
|
4653
|
+
}
|
|
4654
|
+
const LOCAL_FUNCTION_NAMES_RE = new RegExp(`\\b(${[...possibleLocalFunctionNames].map((f) => escapeRE(f)).join("|")})\\b`);
|
|
4655
|
+
function processKeyedFunction(walkContext, node, handler) {
|
|
4656
|
+
if (node.type !== "CallExpression" && node.type !== "ChainExpression") {
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4659
|
+
const parsedCall = parseStaticFunctionCall(node, LOCAL_FUNCTION_NAMES_RE);
|
|
4660
|
+
if (!parsedCall) {
|
|
4661
|
+
return;
|
|
4662
|
+
}
|
|
4663
|
+
const functionScopeTrackerNode = scopeTracker.getDeclaration(!parsedCall.namespace ? parsedCall.name : parsedCall.namespace);
|
|
4664
|
+
function isKeyedFunctionImport(node2) {
|
|
4665
|
+
return node2?.type === "Import" && node2.importNode.importKind !== "type";
|
|
4666
|
+
}
|
|
4667
|
+
let importSourceResolved;
|
|
4668
|
+
if (localNamesToExportedName.has(parsedCall.name) && functionScopeTrackerNode?.scope === "") {
|
|
4669
|
+
importSourceResolved = id;
|
|
4670
|
+
} else if (isKeyedFunctionImport(functionScopeTrackerNode)) {
|
|
4671
|
+
importSourceResolved = stripExtension(_resolvePath(functionScopeTrackerNode.importNode.source.value));
|
|
4672
|
+
}
|
|
4673
|
+
if (!importSourceResolved) {
|
|
4674
|
+
walkContext.skip();
|
|
4675
|
+
return;
|
|
4676
|
+
}
|
|
4677
|
+
const fnMeta = getFunctionMetaByLocalName(parsedCall.name, importSourceResolved);
|
|
4678
|
+
if (!fnMeta) {
|
|
4679
|
+
walkContext.skip();
|
|
4680
|
+
return;
|
|
4681
|
+
}
|
|
4682
|
+
if (!parsedCall.namespace) {
|
|
4683
|
+
if (parsedCall.callExpression.arguments.length >= fnMeta.argumentLength && !parsedCall.callExpression.arguments.some((a) => a.type === "SpreadElement")) {
|
|
4684
|
+
walkContext.skip();
|
|
4685
|
+
return;
|
|
4686
|
+
}
|
|
4687
|
+
if (
|
|
4688
|
+
// the function is imported
|
|
4689
|
+
isKeyedFunctionImport(functionScopeTrackerNode) && // import { useKeyed } from '...'
|
|
4690
|
+
(functionScopeTrackerNode.node.type === "ImportSpecifier" && functionScopeTrackerNode.node.importKind !== "type" || functionScopeTrackerNode.node.type === "ImportDefaultSpecifier" && fnMeta.name === "default") && // the function is imported from the correct source when `source` is specified
|
|
4691
|
+
(typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === importSourceResolved || !fnMeta.source && stripExtension(_resolvePath(autoImportsToSources.get(parsedCall.name) ?? "")) === importSourceResolved || fnMeta.source instanceof RegExp && fnMeta.source.test(importSourceResolved) || typeof fnMeta.source === "string" && fnMeta.source.startsWith(options.appDir)) || localNamesToExportedName.has(parsedCall.name) && functionScopeTrackerNode?.scope === ""
|
|
4692
|
+
) {
|
|
4693
|
+
handler({ parsedCall, fnMeta });
|
|
4694
|
+
}
|
|
4695
|
+
walkContext.skip();
|
|
4696
|
+
return;
|
|
4697
|
+
}
|
|
4698
|
+
if (parsedCall.namespace) {
|
|
4699
|
+
const namespacedImportMeta = namespaces.get(importSourceResolved);
|
|
4700
|
+
const namespaceScopeTrackerNode = scopeTracker.getDeclaration(parsedCall.namespace);
|
|
4701
|
+
if (namespacedImportMeta && namespacedImportMeta.namespaces.has(parsedCall.namespace) && namespaceScopeTrackerNode?.type === "Import" && namespaceScopeTrackerNode.node.type === "ImportNamespaceSpecifier") {
|
|
4702
|
+
handler({ parsedCall, fnMeta });
|
|
4703
|
+
}
|
|
4704
|
+
walkContext.skip();
|
|
4705
|
+
return;
|
|
4706
|
+
}
|
|
4707
|
+
}
|
|
4708
|
+
walk(program, {
|
|
4709
|
+
scopeTracker,
|
|
4710
|
+
enter(node) {
|
|
4711
|
+
processKeyedFunction(this, node, ({ parsedCall, fnMeta }) => {
|
|
4712
|
+
const lastArgument = parsedCall.callExpression.arguments[parsedCall.callExpression.arguments.length - 1];
|
|
4713
|
+
if (lastArgument?.type === "Literal" && typeof lastArgument.value === "string" && lastArgument.end + NUXT_INJECTED_MARKER.length + 1 < parsedCall.callExpression.end) {
|
|
4714
|
+
let wasKeyInjected = true;
|
|
4715
|
+
for (let i2 = 0; i2 < NUXT_INJECTED_MARKER.length; i2++) {
|
|
4716
|
+
if (code[codeIndex + lastArgument.end + 1 + i2] !== NUXT_INJECTED_MARKER[i2]) {
|
|
4717
|
+
wasKeyInjected = false;
|
|
4718
|
+
break;
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
if (wasKeyInjected) {
|
|
4722
|
+
return;
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
switch (parsedCall.name) {
|
|
4726
|
+
case "useState":
|
|
4727
|
+
if (stringTypes.includes(parsedCall.callExpression.arguments[0]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/state", options.alias))) {
|
|
4728
|
+
return;
|
|
4729
|
+
}
|
|
4730
|
+
break;
|
|
4731
|
+
case "useFetch":
|
|
4732
|
+
case "useLazyFetch":
|
|
4733
|
+
if (stringTypes.includes(parsedCall.callExpression.arguments[1]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/fetch", options.alias))) {
|
|
4734
|
+
return;
|
|
4735
|
+
}
|
|
4736
|
+
break;
|
|
4737
|
+
case "useAsyncData":
|
|
4738
|
+
case "useLazyAsyncData":
|
|
4739
|
+
if (stringTypes.includes(parsedCall.callExpression.arguments[0]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/asyncData", options.alias))) {
|
|
4740
|
+
return;
|
|
4741
|
+
}
|
|
4742
|
+
break;
|
|
4743
|
+
}
|
|
4744
|
+
let i = codeIndex + parsedCall.callExpression.end - 2;
|
|
4745
|
+
while (i >= codeIndex + parsedCall.callExpression.start && isWhitespace(code[i])) {
|
|
4746
|
+
i--;
|
|
4747
|
+
}
|
|
4748
|
+
const endsWithComma = code[i] === ",";
|
|
4749
|
+
s.appendLeft(
|
|
4750
|
+
codeIndex + parsedCall.callExpression.end - 1,
|
|
4751
|
+
(parsedCall.callExpression.arguments.length && !endsWithComma ? ", " : "") + "'$" + hash(`${_id}-${++count}`).slice(0, 10) + `' ${NUXT_INJECTED_MARKER}`
|
|
4752
|
+
);
|
|
4753
|
+
});
|
|
4754
|
+
}
|
|
4755
|
+
});
|
|
4756
|
+
if (s.hasChanged()) {
|
|
4757
|
+
return {
|
|
4758
|
+
code: s.toString(),
|
|
4759
|
+
map: options.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
4760
|
+
};
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
};
|
|
4765
|
+
});
|
|
4766
|
+
|
|
4767
|
+
const compilerModule = defineNuxtModule({
|
|
4768
|
+
meta: {
|
|
4769
|
+
name: "nuxt:compiler",
|
|
4770
|
+
configKey: "compiler"
|
|
4771
|
+
},
|
|
4772
|
+
defaults: {
|
|
4773
|
+
scan: true
|
|
4774
|
+
},
|
|
4775
|
+
setup(_options, nuxt) {
|
|
4776
|
+
let unimport;
|
|
4777
|
+
nuxt.hook("imports:context", (ctx) => {
|
|
4778
|
+
unimport = ctx;
|
|
4779
|
+
});
|
|
4780
|
+
let scanResult;
|
|
4781
|
+
let scanDirPaths = [];
|
|
4782
|
+
let normalizedKeyedFunctions = [];
|
|
4783
|
+
nuxt.hook("build:before", async () => {
|
|
4784
|
+
addBuildPlugin(KeyedFunctionFactoriesPlugin({
|
|
4785
|
+
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client,
|
|
4786
|
+
factories: nuxt.options.optimization.keyedComposableFactories,
|
|
4787
|
+
alias: nuxt.options.alias,
|
|
4788
|
+
getAutoImports: () => unimport?.getImports() || Promise.resolve([])
|
|
4789
|
+
}));
|
|
4790
|
+
if (_options.scan) {
|
|
4791
|
+
const scanPlugin = KeyedFunctionFactoriesScanPlugin({
|
|
4792
|
+
factories: nuxt.options.optimization.keyedComposableFactories,
|
|
4793
|
+
alias: nuxt.options.alias
|
|
4794
|
+
});
|
|
4795
|
+
scanResult = scanPlugin.result;
|
|
4796
|
+
await runScanPlugins([scanPlugin]);
|
|
4797
|
+
}
|
|
4798
|
+
normalizedKeyedFunctions = await Promise.all(nuxt.options.optimization.keyedComposables.map(async ({ source, ...rest }) => ({
|
|
4799
|
+
...rest,
|
|
4800
|
+
source: typeof source === "string" ? await resolvePath(source, { fallbackToOriginal: true }) : source
|
|
4801
|
+
})));
|
|
4802
|
+
addBuildPlugin(KeyedFunctionsPlugin({
|
|
4803
|
+
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client,
|
|
4804
|
+
keyedFunctions: normalizedKeyedFunctions,
|
|
4805
|
+
getKeyedFunctions: () => normalizedKeyedFunctions,
|
|
4806
|
+
alias: nuxt.options.alias,
|
|
4807
|
+
getAutoImports: () => unimport?.getImports() || Promise.resolve([]),
|
|
4808
|
+
appDir: nuxt.options.appDir,
|
|
4809
|
+
dev: nuxt.options.dev
|
|
4810
|
+
}));
|
|
4811
|
+
});
|
|
4812
|
+
async function runScanPlugins(plugins) {
|
|
4813
|
+
const autoImports = await unimport?.getImports() || [];
|
|
4814
|
+
const autoImportsToSources = new Map(autoImports.map((i) => [i.as || i.name, i.from]));
|
|
4815
|
+
const dirPaths = /* @__PURE__ */ new Set();
|
|
4816
|
+
const scanDirs = [];
|
|
4817
|
+
for (const layer of nuxt.options._layers) {
|
|
4818
|
+
if (layer.config?.compiler?.scan === false) {
|
|
4819
|
+
continue;
|
|
4820
|
+
}
|
|
4821
|
+
const composablesDir = resolve(layer.config.srcDir, "composables");
|
|
4822
|
+
if (!isDirectorySync(composablesDir) || dirPaths.has(composablesDir)) {
|
|
4823
|
+
continue;
|
|
4824
|
+
}
|
|
4825
|
+
dirPaths.add(composablesDir);
|
|
4826
|
+
const extensions = nuxt.options.extensions.map((e) => normalizeExtension(e));
|
|
4827
|
+
scanDirs.push({
|
|
4828
|
+
path: composablesDir,
|
|
4829
|
+
extensions,
|
|
4830
|
+
pattern: `**/*.{${extensions.join(",")}}`,
|
|
4831
|
+
ignore: [`**/*.{${DECLARATION_EXTENSIONS.join(",")}}`]
|
|
4832
|
+
});
|
|
4833
|
+
}
|
|
4834
|
+
scanDirPaths = scanDirs.map((d) => d.path);
|
|
4835
|
+
const _filePaths = [];
|
|
4836
|
+
await Promise.all(scanDirs.map(async (dir) => {
|
|
4837
|
+
const files = await resolveFiles(dir.path, dir.pattern, { ignore: dir.ignore });
|
|
4838
|
+
_filePaths.push(...files);
|
|
4839
|
+
}));
|
|
4840
|
+
const filePaths = await Promise.all(_filePaths.map((filePath) => resolvePath(filePath)));
|
|
4841
|
+
for (const filePath of filePaths) {
|
|
4842
|
+
const isFileWantedByPlugin = plugins.some((p) => {
|
|
4843
|
+
if (!p.filter?.id) {
|
|
4844
|
+
return true;
|
|
4845
|
+
}
|
|
4846
|
+
return matchFilter(filePath, p.filter.id);
|
|
4847
|
+
});
|
|
4848
|
+
if (!isFileWantedByPlugin) {
|
|
4849
|
+
continue;
|
|
4850
|
+
}
|
|
4851
|
+
try {
|
|
4852
|
+
const contents = await readFile(filePath, "utf-8");
|
|
4853
|
+
const pluginScanThisContext = createScanPluginContext(contents, filePath);
|
|
4854
|
+
await Promise.all(plugins.map(async (plugin) => {
|
|
4855
|
+
if (plugin.filter?.id && !matchFilter(filePath, plugin.filter.id)) {
|
|
4856
|
+
return;
|
|
4857
|
+
}
|
|
4858
|
+
if (plugin.filter?.code && !matchFilter(contents, plugin.filter.code)) {
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
try {
|
|
4862
|
+
await plugin.scan.call(pluginScanThisContext, { id: filePath, code: contents, nuxt, autoImportsToSources });
|
|
4863
|
+
} catch (e) {
|
|
4864
|
+
logger.error(`[nuxt:compiler] Plugin \`${plugin.name}\` failed to scan file \`${filePath}\``, e);
|
|
4865
|
+
}
|
|
4866
|
+
}));
|
|
4867
|
+
} catch (e) {
|
|
4868
|
+
logger.error(`[nuxt:compiler] Cannot read file \`${filePath}\``, e);
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
await Promise.all(plugins.map(async (plugin) => {
|
|
4872
|
+
if (!plugin.afterScan) {
|
|
4873
|
+
return;
|
|
4874
|
+
}
|
|
4875
|
+
try {
|
|
4876
|
+
await plugin.afterScan(nuxt);
|
|
4877
|
+
} catch (e) {
|
|
4878
|
+
logger.error(`[nuxt:compiler] Error in \`afterScan\` hook of plugin \`${plugin.name}\``, e);
|
|
4879
|
+
}
|
|
4880
|
+
}));
|
|
4881
|
+
}
|
|
4882
|
+
if (nuxt.options.dev && _options.scan) {
|
|
4883
|
+
nuxt.hook("builder:watch", async (event, relativePath) => {
|
|
4884
|
+
if (!scanResult || !["add", "change", "unlink"].includes(event)) {
|
|
4885
|
+
return;
|
|
4886
|
+
}
|
|
4887
|
+
const absolutePath = resolve(nuxt.options.srcDir, relativePath);
|
|
4888
|
+
const isInScanDir = scanDirPaths.some((dir) => absolutePath === dir || absolutePath.startsWith(dir + "/"));
|
|
4889
|
+
if (!isInScanDir) {
|
|
4890
|
+
return;
|
|
4891
|
+
}
|
|
4892
|
+
const { fileResults, factoryNamesRegex, namesToFactoryMeta } = scanResult;
|
|
4893
|
+
const oldEntries = fileResults.get(absolutePath);
|
|
4894
|
+
if (oldEntries?.length) {
|
|
4895
|
+
const resolvedSource = await resolvePath(absolutePath, { fallbackToOriginal: true });
|
|
4896
|
+
for (let i = normalizedKeyedFunctions.length - 1; i >= 0; i--) {
|
|
4897
|
+
if (normalizedKeyedFunctions[i].source === resolvedSource) {
|
|
4898
|
+
normalizedKeyedFunctions.splice(i, 1);
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
fileResults.delete(absolutePath);
|
|
4902
|
+
}
|
|
4903
|
+
if (event === "unlink") {
|
|
4904
|
+
return;
|
|
4905
|
+
}
|
|
4906
|
+
let contents;
|
|
4907
|
+
try {
|
|
4908
|
+
contents = await readFile(absolutePath, "utf-8");
|
|
4909
|
+
} catch {
|
|
4910
|
+
return;
|
|
4911
|
+
}
|
|
4912
|
+
if (!factoryNamesRegex.test(contents)) {
|
|
4913
|
+
return;
|
|
4914
|
+
}
|
|
4915
|
+
const autoImports = await unimport?.getImports() || [];
|
|
4916
|
+
const autoImportsToSources = new Map(autoImports.map((i) => [i.as || i.name, i.from]));
|
|
4917
|
+
const newEntries = scanFileForFactories(
|
|
4918
|
+
absolutePath,
|
|
4919
|
+
contents,
|
|
4920
|
+
namesToFactoryMeta,
|
|
4921
|
+
autoImportsToSources,
|
|
4922
|
+
nuxt.options.alias
|
|
4923
|
+
);
|
|
4924
|
+
if (newEntries.length) {
|
|
4925
|
+
fileResults.set(absolutePath, newEntries);
|
|
4926
|
+
const normalized = await Promise.all(newEntries.map(async ({ source, ...rest }) => ({
|
|
4927
|
+
...rest,
|
|
4928
|
+
source: typeof source === "string" ? await resolvePath(source, { fallbackToOriginal: true }) : source
|
|
4929
|
+
})));
|
|
4930
|
+
normalizedKeyedFunctions.push(...normalized);
|
|
4931
|
+
}
|
|
4932
|
+
});
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
});
|
|
4936
|
+
function matchFilter(input, filter) {
|
|
4937
|
+
if (typeof filter === "function") {
|
|
4938
|
+
return filter(input);
|
|
4939
|
+
}
|
|
4940
|
+
const include = filter.include ? toArray(filter.include).some((v) => matchWithStringOrRegex(input, v)) : true;
|
|
4941
|
+
const exclude = filter.exclude ? toArray(filter.exclude).some((v) => matchWithStringOrRegex(input, v)) : false;
|
|
4942
|
+
return include && !exclude;
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
async function getVueHash(nuxt) {
|
|
4946
|
+
const id = "vue";
|
|
4947
|
+
const { hash: hash2 } = await getHashes(nuxt, {
|
|
4948
|
+
id,
|
|
4949
|
+
cwd: (layer) => layer.config.srcDir || layer.cwd,
|
|
4950
|
+
patterns: (layer) => {
|
|
4951
|
+
const srcDir = layer.config.srcDir || layer.cwd;
|
|
4952
|
+
return [
|
|
4953
|
+
"**",
|
|
4954
|
+
`!${relative(srcDir, layer.config.serverDir || join(layer.cwd, "server"))}/**`,
|
|
4955
|
+
`!${relative(srcDir, resolve$1(layer.cwd, layer.config.dir?.public || "public"))}/**`,
|
|
4956
|
+
"!node_modules/**",
|
|
4957
|
+
"!nuxt.config.*"
|
|
4958
|
+
];
|
|
4959
|
+
},
|
|
4960
|
+
configOverrides: {
|
|
4961
|
+
buildId: void 0,
|
|
4962
|
+
serverDir: void 0,
|
|
4963
|
+
nitro: void 0,
|
|
4964
|
+
devServer: void 0,
|
|
4965
|
+
runtimeConfig: void 0,
|
|
4966
|
+
logLevel: void 0,
|
|
4967
|
+
devServerHandlers: void 0,
|
|
4968
|
+
devtools: void 0
|
|
4969
|
+
}
|
|
4970
|
+
});
|
|
4971
|
+
const cacheFile = join(getCacheDir(nuxt), id, hash2 + ".tar");
|
|
4972
|
+
const buildIdCacheFile = cacheFile.replace(".tar", ".buildid");
|
|
4973
|
+
return {
|
|
4974
|
+
hash: hash2,
|
|
4975
|
+
async collectCache() {
|
|
4976
|
+
const start = Date.now();
|
|
4977
|
+
await writeCache(nuxt.options.buildDir, nuxt.options.buildDir, cacheFile);
|
|
4978
|
+
await mkdir(dirname(buildIdCacheFile), { recursive: true });
|
|
4979
|
+
await writeFile(buildIdCacheFile, nuxt.options.buildId);
|
|
4980
|
+
const elapsed = Date.now() - start;
|
|
4981
|
+
consola.success(`Cached Vue client and server builds in \`${elapsed}ms\`.`);
|
|
4982
|
+
},
|
|
4983
|
+
async restoreCache() {
|
|
4984
|
+
const start = Date.now();
|
|
4985
|
+
const res = await restoreCacheFromFile(nuxt.options.buildDir, cacheFile);
|
|
4986
|
+
const elapsed = Date.now() - start;
|
|
4987
|
+
if (res) {
|
|
4988
|
+
consola.success(`Restored Vue client and server builds from cache in \`${elapsed}ms\`.`);
|
|
4989
|
+
}
|
|
4990
|
+
return res;
|
|
4991
|
+
}
|
|
4992
|
+
};
|
|
4993
|
+
}
|
|
4994
|
+
async function restoreCachedBuildId(nuxt) {
|
|
4995
|
+
const { hash: hash2 } = await getVueHash(nuxt);
|
|
4996
|
+
const cacheDir = getCacheDir(nuxt);
|
|
4997
|
+
const buildIdCacheFile = join(cacheDir, "vue", hash2 + ".buildid");
|
|
4998
|
+
if (!existsSync(buildIdCacheFile)) {
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
const cachedBuildId = (await readFile(buildIdCacheFile, "utf-8")).trim();
|
|
5002
|
+
if (!cachedBuildId || !/^[\w-]+$/.test(cachedBuildId)) {
|
|
5003
|
+
return;
|
|
5004
|
+
}
|
|
5005
|
+
nuxt.options.buildId = cachedBuildId;
|
|
5006
|
+
nuxt.options.runtimeConfig.app.buildId = cachedBuildId;
|
|
5007
|
+
consola.debug(`Restored cached buildId: ${cachedBuildId}`);
|
|
5008
|
+
}
|
|
5009
|
+
async function cleanupCaches(nuxt) {
|
|
5010
|
+
const start = Date.now();
|
|
5011
|
+
const caches = await glob(["*/*.tar", "*/*.buildid"], {
|
|
5012
|
+
cwd: getCacheDir(nuxt),
|
|
5013
|
+
absolute: true
|
|
5014
|
+
});
|
|
5015
|
+
if (caches.length >= 10) {
|
|
5016
|
+
const cachesWithMeta = await Promise.all(caches.map(async (cache) => {
|
|
5017
|
+
return [cache, await stat(cache).then((r) => r.mtime.getTime()).catch(() => 0)];
|
|
5018
|
+
}));
|
|
5019
|
+
cachesWithMeta.sort((a, b) => a[1] - b[1]);
|
|
5020
|
+
for (const [cache] of cachesWithMeta.slice(0, cachesWithMeta.length - 10)) {
|
|
5021
|
+
await unlink(cache);
|
|
5022
|
+
}
|
|
5023
|
+
const elapsed = Date.now() - start;
|
|
5024
|
+
consola.success(`Cleaned up old build caches in \`${elapsed}ms\`.`);
|
|
5025
|
+
}
|
|
5026
|
+
}
|
|
5027
|
+
async function getHashes(nuxt, options) {
|
|
5028
|
+
if (nuxt[`_${options.id}BuildHash`]) {
|
|
5029
|
+
return nuxt[`_${options.id}BuildHash`];
|
|
5030
|
+
}
|
|
5031
|
+
const start = Date.now();
|
|
5032
|
+
const hashSources = [];
|
|
5033
|
+
let layerCtr = 0;
|
|
5034
|
+
for (const layer of nuxt.options._layers) {
|
|
5035
|
+
if (layer.cwd.includes("node_modules")) {
|
|
5036
|
+
continue;
|
|
5037
|
+
}
|
|
5038
|
+
const layerName = `layer#${layerCtr++}`;
|
|
5039
|
+
hashSources.push({
|
|
5040
|
+
name: `${layerName}:config`,
|
|
5041
|
+
data: serialize({
|
|
5042
|
+
...layer.config,
|
|
5043
|
+
...options.configOverrides || {}
|
|
5044
|
+
})
|
|
5045
|
+
});
|
|
5046
|
+
const normalizeFiles = (files) => files.map((f) => ({
|
|
5047
|
+
name: f.name,
|
|
5048
|
+
size: f.attrs?.size,
|
|
5049
|
+
data: hash(f.data)
|
|
5050
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
5051
|
+
const isIgnored = createIsIgnored(nuxt);
|
|
5052
|
+
const sourceFiles = await readFilesRecursive(options.cwd(layer), {
|
|
5053
|
+
shouldIgnore: isIgnored,
|
|
5054
|
+
// TODO: Validate if works with absolute paths
|
|
5055
|
+
cwd: nuxt.options.rootDir,
|
|
5056
|
+
patterns: options.patterns(layer)
|
|
5057
|
+
});
|
|
5058
|
+
hashSources.push({
|
|
5059
|
+
name: `${layerName}:src`,
|
|
5060
|
+
data: normalizeFiles(sourceFiles)
|
|
5061
|
+
});
|
|
5062
|
+
const rootFiles = await readFilesRecursive(layer.config?.rootDir || layer.cwd, {
|
|
5063
|
+
shouldIgnore: isIgnored,
|
|
5064
|
+
// TODO: Validate if works with absolute paths
|
|
5065
|
+
cwd: nuxt.options.rootDir,
|
|
5066
|
+
patterns: [
|
|
5067
|
+
".nuxtrc",
|
|
5068
|
+
".npmrc",
|
|
5069
|
+
"package.json",
|
|
5070
|
+
"package-lock.json",
|
|
5071
|
+
"yarn.lock",
|
|
5072
|
+
"pnpm-lock.yaml",
|
|
5073
|
+
"tsconfig.json",
|
|
5074
|
+
"bun.lock",
|
|
5075
|
+
"bun.lockb"
|
|
5076
|
+
]
|
|
5077
|
+
});
|
|
5078
|
+
hashSources.push({
|
|
5079
|
+
name: `${layerName}:root`,
|
|
5080
|
+
data: normalizeFiles(rootFiles)
|
|
5081
|
+
});
|
|
5082
|
+
}
|
|
5083
|
+
hashSources.sort((a, b) => a.name.localeCompare(b.name));
|
|
5084
|
+
const res = nuxt[`_${options.id}BuildHash`] = {
|
|
5085
|
+
hash: hash(hashSources),
|
|
5086
|
+
sources: hashSources
|
|
5087
|
+
};
|
|
5088
|
+
const elapsed = Date.now() - start;
|
|
5089
|
+
consola.debug(`Computed \`${options.id}\` build hash in \`${elapsed}ms\`.`);
|
|
5090
|
+
return res;
|
|
5091
|
+
}
|
|
5092
|
+
async function readFilesRecursive(dir, opts) {
|
|
5093
|
+
if (Array.isArray(dir)) {
|
|
5094
|
+
return (await Promise.all(dir.map((d) => readFilesRecursive(d, opts)))).flat();
|
|
5095
|
+
}
|
|
5096
|
+
const files = await glob(opts.patterns, { cwd: dir });
|
|
5097
|
+
const fileEntries = await Promise.all(files.map(async (fileName) => {
|
|
5098
|
+
if (!opts.shouldIgnore?.(fileName)) {
|
|
5099
|
+
const file = await readFileWithMeta(dir, fileName);
|
|
5100
|
+
if (!file) {
|
|
5101
|
+
return;
|
|
5102
|
+
}
|
|
5103
|
+
return {
|
|
5104
|
+
...file,
|
|
5105
|
+
name: relative(opts.cwd, join(dir, file.name))
|
|
5106
|
+
};
|
|
5107
|
+
}
|
|
5108
|
+
}));
|
|
5109
|
+
return fileEntries.filter(Boolean);
|
|
5110
|
+
}
|
|
5111
|
+
async function readFileWithMeta(dir, fileName, count = 0) {
|
|
5112
|
+
let fd = void 0;
|
|
5113
|
+
try {
|
|
5114
|
+
fd = await open(resolve$1(dir, fileName));
|
|
5115
|
+
const stats = await fd.stat();
|
|
5116
|
+
if (!stats?.isFile()) {
|
|
5117
|
+
return;
|
|
5118
|
+
}
|
|
5119
|
+
const mtime = stats.mtime.getTime();
|
|
5120
|
+
const data = await fd.readFile();
|
|
5121
|
+
if ((await fd.stat()).mtime.getTime() !== mtime) {
|
|
5122
|
+
await fd.close();
|
|
5123
|
+
fd = void 0;
|
|
5124
|
+
if (count < 5) {
|
|
5125
|
+
return await readFileWithMeta(dir, fileName, count + 1);
|
|
5126
|
+
}
|
|
5127
|
+
console.warn(`Failed to read file \`${fileName}\` as it changed during read.`);
|
|
5128
|
+
return;
|
|
5129
|
+
}
|
|
5130
|
+
return {
|
|
5131
|
+
name: fileName,
|
|
5132
|
+
data,
|
|
5133
|
+
attrs: {
|
|
5134
|
+
mtime,
|
|
5135
|
+
size: stats.size
|
|
5136
|
+
}
|
|
5137
|
+
};
|
|
5138
|
+
} catch (err) {
|
|
5139
|
+
console.warn(`Failed to read file \`${fileName}\`:`, err);
|
|
5140
|
+
} finally {
|
|
5141
|
+
await fd?.close();
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
async function restoreCacheFromFile(cwd, cacheFile) {
|
|
5145
|
+
if (!existsSync(cacheFile)) {
|
|
5146
|
+
return false;
|
|
5147
|
+
}
|
|
5148
|
+
const resolvedCwd = resolve$1(cwd) + "/";
|
|
5149
|
+
const files = parseTar(await readFile(cacheFile));
|
|
5150
|
+
for (const file of files) {
|
|
5151
|
+
let fd = void 0;
|
|
5152
|
+
try {
|
|
5153
|
+
const filePath = resolve$1(cwd, file.name);
|
|
5154
|
+
if (!filePath.startsWith(resolvedCwd)) {
|
|
5155
|
+
consola.warn(`Skipping unsafe cache path: ${file.name}`);
|
|
5156
|
+
continue;
|
|
5157
|
+
}
|
|
5158
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
5159
|
+
const existingStats = await stat(filePath).catch(() => null);
|
|
5160
|
+
const cachedSize = file.data?.byteLength ?? 0;
|
|
5161
|
+
if (existingStats?.isFile() && existingStats.size === cachedSize) {
|
|
5162
|
+
const lastModified = Number.parseInt(file.attrs?.mtime?.toString().padEnd(13, "0") || "0");
|
|
5163
|
+
if (existingStats.mtime.getTime() >= lastModified) {
|
|
5164
|
+
consola.debug(`Skipping \`${file.name}\` (up to date or newer than cache)`);
|
|
5165
|
+
continue;
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
5168
|
+
fd = await open(filePath, "w");
|
|
5169
|
+
await fd.writeFile(file.data);
|
|
5170
|
+
} catch (err) {
|
|
5171
|
+
console.error(err);
|
|
5172
|
+
} finally {
|
|
5173
|
+
await fd?.close();
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
return true;
|
|
5177
|
+
}
|
|
5178
|
+
async function writeCache(cwd, sources, cacheFile) {
|
|
5179
|
+
const fileEntries = await readFilesRecursive(sources, {
|
|
5180
|
+
patterns: ["**/*", "!analyze/**"],
|
|
5181
|
+
cwd
|
|
5182
|
+
});
|
|
5183
|
+
const tarData = createTar(fileEntries);
|
|
5184
|
+
await mkdir(dirname(cacheFile), { recursive: true });
|
|
5185
|
+
await writeFile(cacheFile, tarData);
|
|
5186
|
+
}
|
|
5187
|
+
function getCacheDir(nuxt) {
|
|
5188
|
+
let cacheDir = join(nuxt.options.workspaceDir, "node_modules");
|
|
5189
|
+
if (!existsSync(cacheDir)) {
|
|
5190
|
+
for (const dir of [...nuxt.options.modulesDir].sort((a, b) => a.length - b.length)) {
|
|
5191
|
+
if (existsSync(dir)) {
|
|
5192
|
+
cacheDir = dir;
|
|
5193
|
+
break;
|
|
5194
|
+
}
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
return join(cacheDir, ".cache/nuxt/builds");
|
|
5198
|
+
}
|
|
5199
|
+
|
|
5200
|
+
const runtimeDependencies = [
|
|
5201
|
+
// other deps
|
|
5202
|
+
"devalue",
|
|
5203
|
+
"klona",
|
|
5204
|
+
// deliberate exports from nitro builder
|
|
5205
|
+
"@nuxt/nitro-server/h3",
|
|
5206
|
+
// unjs ecosystem
|
|
5207
|
+
"defu",
|
|
5208
|
+
"ufo",
|
|
5209
|
+
"destr",
|
|
5210
|
+
"consola",
|
|
5211
|
+
"hookable",
|
|
5212
|
+
"unctx",
|
|
5213
|
+
"cookie-es",
|
|
5214
|
+
"perfect-debounce",
|
|
5215
|
+
"ohash",
|
|
5216
|
+
"pathe",
|
|
5217
|
+
"uncrypto"
|
|
5218
|
+
];
|
|
5219
|
+
|
|
5220
|
+
const version = "4.4.2";
|
|
5221
|
+
const pkg = {
|
|
5222
|
+
version: version};
|
|
5223
|
+
|
|
5224
|
+
function createImportProtectionPatterns(nuxt, options) {
|
|
5225
|
+
const patterns = [];
|
|
5226
|
+
const context = contextFlags[options.context];
|
|
5227
|
+
patterns.push([
|
|
5228
|
+
/^(nuxt|nuxt3|nuxt-nightly)$/,
|
|
5229
|
+
`\`nuxt\` or \`nuxt-nightly\` cannot be imported directly in ${context}.`,
|
|
5230
|
+
options.context === "nuxt-app" ? ["Import runtime Nuxt composables from `#app` or `#imports` instead."] : ["Use `#app` or `#imports` for runtime composables in your Vue app code."]
|
|
5231
|
+
]);
|
|
5232
|
+
patterns.push([
|
|
5233
|
+
/^((~|~~|@|@@)?\/)?nuxt\.config(\.|$)/,
|
|
5234
|
+
"Importing directly from a `nuxt.config` file is not allowed.",
|
|
5235
|
+
["Use `useRuntimeConfig()` to access runtime config in your app.", "Use `useAppConfig()` to access config that doesn't need to be changed at runtime.", "Use a Nuxt module to access build-time configuration."]
|
|
5236
|
+
]);
|
|
5237
|
+
patterns.push([/(^|node_modules\/)@vue\/composition-api/]);
|
|
5238
|
+
for (const mod of nuxt.options._installedModules) {
|
|
5239
|
+
if (mod.entryPath) {
|
|
5240
|
+
patterns.push([
|
|
5241
|
+
new RegExp(`^${escapeRE(mod.entryPath)}$`),
|
|
5242
|
+
"Importing directly from module entry-points is not allowed.",
|
|
5243
|
+
["Import from the module's runtime directory instead (e.g. `my-module/runtime/...`)."]
|
|
5244
|
+
]);
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
for (const i of [/(^|node_modules\/)@nuxt\/(cli|kit|test-utils)/, /(^|node_modules\/)nuxi/, /(^|node_modules\/)nitro(?:pack)?(?:-nightly)?(?:$|\/)(?!(?:dist\/)?(?:node_modules|presets|runtime|types))/, /(^|node_modules\/)nuxt\/(config|kit|schema)/]) {
|
|
5248
|
+
patterns.push([
|
|
5249
|
+
i,
|
|
5250
|
+
`This module cannot be imported in ${context}.`,
|
|
5251
|
+
["These are build-time only packages and cannot be used at runtime."]
|
|
5252
|
+
]);
|
|
5253
|
+
}
|
|
5254
|
+
if (options.context === "nitro-app" || options.context === "shared") {
|
|
5255
|
+
for (const i of ["#app", /^#build(\/|$)/]) {
|
|
5256
|
+
patterns.push([
|
|
5257
|
+
i,
|
|
5258
|
+
`Vue app aliases are not allowed in ${context}.`,
|
|
5259
|
+
["Move this code to your Vue app directory or use a shared utility."]
|
|
5260
|
+
]);
|
|
5261
|
+
}
|
|
5262
|
+
}
|
|
5263
|
+
if (options.context === "nuxt-app" || options.context === "shared") {
|
|
5264
|
+
const serverRelative = escapeRE(relative(nuxt.options.rootDir, resolve(nuxt.options.srcDir, nuxt.options.serverDir || "server")));
|
|
5265
|
+
patterns.push([
|
|
5266
|
+
new RegExp("^" + serverRelative + "\\/(api|routes|middleware|plugins)\\/"),
|
|
5267
|
+
`Importing from server is not allowed in ${context}.`,
|
|
5268
|
+
["Use `$fetch()` or `useFetch()` to fetch data from server routes.", "Move shared logic to the `shared/` directory."]
|
|
5269
|
+
]);
|
|
5270
|
+
patterns.push([
|
|
5271
|
+
/^#server(\/|$)/,
|
|
5272
|
+
`Server aliases are not allowed in ${context}.`,
|
|
5273
|
+
["Use `$fetch()` or `useFetch()` to call server endpoints.", "Move shared logic to the `shared/` directory."]
|
|
5274
|
+
]);
|
|
5275
|
+
}
|
|
5276
|
+
return patterns;
|
|
5277
|
+
}
|
|
5278
|
+
const contextFlags = {
|
|
5279
|
+
"nitro-app": "server runtime",
|
|
5280
|
+
"nuxt-app": "the Vue part of your app",
|
|
5281
|
+
"shared": "the #shared directory"
|
|
5282
|
+
};
|
|
5283
|
+
|
|
5284
|
+
const TRANSFORM_MARKER = "/* _processed_nuxt_unctx_transform */\n";
|
|
5285
|
+
const TRANSFORM_MARKER_RE = /^\/\* _processed_nuxt_unctx_transform \*\/\n/;
|
|
5286
|
+
const UnctxTransformPlugin = (options) => createUnplugin(() => {
|
|
5287
|
+
const transformer = createTransformer(options.transformerOptions);
|
|
5288
|
+
return {
|
|
5289
|
+
name: "unctx:transform",
|
|
5290
|
+
enforce: "post",
|
|
5291
|
+
transformInclude(id) {
|
|
5292
|
+
return isVue(id, { type: ["template", "script"] }) || isJS(id);
|
|
5293
|
+
},
|
|
5294
|
+
transform: {
|
|
5295
|
+
filter: {
|
|
5296
|
+
...transformer.filter,
|
|
5297
|
+
code: {
|
|
5298
|
+
...transformer.filter.code,
|
|
5299
|
+
exclude: TRANSFORM_MARKER_RE
|
|
5300
|
+
}
|
|
5301
|
+
},
|
|
5302
|
+
handler(code) {
|
|
4015
5303
|
if (!transformer.shouldTransform(code)) {
|
|
4016
5304
|
return;
|
|
4017
5305
|
}
|
|
@@ -4176,7 +5464,7 @@ const LayerAliasingPlugin = (options) => createUnplugin((_options, meta) => {
|
|
|
4176
5464
|
filter: {
|
|
4177
5465
|
id: ALIAS_ID_RE
|
|
4178
5466
|
},
|
|
4179
|
-
|
|
5467
|
+
handler(id, importer) {
|
|
4180
5468
|
if (!importer) {
|
|
4181
5469
|
return;
|
|
4182
5470
|
}
|
|
@@ -4186,7 +5474,7 @@ const LayerAliasingPlugin = (options) => createUnplugin((_options, meta) => {
|
|
|
4186
5474
|
}
|
|
4187
5475
|
const resolvedId = resolveAlias$1(id, aliases[layer]);
|
|
4188
5476
|
if (resolvedId !== id) {
|
|
4189
|
-
return
|
|
5477
|
+
return this.resolve(resolvedId, importer, { skipSelf: true });
|
|
4190
5478
|
}
|
|
4191
5479
|
}
|
|
4192
5480
|
}
|
|
@@ -4238,6 +5526,549 @@ async function loadServerBuilder(nuxt, builder = "@nuxt/nitro-server") {
|
|
|
4238
5526
|
}
|
|
4239
5527
|
}
|
|
4240
5528
|
|
|
5529
|
+
function getMemorySnapshot() {
|
|
5530
|
+
const mem = process.memoryUsage();
|
|
5531
|
+
return { rss: mem.rss, heapUsed: mem.heapUsed, heapTotal: mem.heapTotal };
|
|
5532
|
+
}
|
|
5533
|
+
function formatBytes(bytes) {
|
|
5534
|
+
const abs = Math.abs(bytes);
|
|
5535
|
+
if (abs < 1024) {
|
|
5536
|
+
return `${bytes} B`;
|
|
5537
|
+
}
|
|
5538
|
+
if (abs < 1024 * 1024) {
|
|
5539
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
5540
|
+
}
|
|
5541
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
5542
|
+
}
|
|
5543
|
+
function formatDuration(ms) {
|
|
5544
|
+
if (ms < 1) {
|
|
5545
|
+
return `${Math.round(ms * 1e3)}\xB5s`;
|
|
5546
|
+
}
|
|
5547
|
+
if (ms < 1e3) {
|
|
5548
|
+
return `${Math.round(ms)}ms`;
|
|
5549
|
+
}
|
|
5550
|
+
if (ms < 6e4) {
|
|
5551
|
+
return `${(ms / 1e3).toFixed(1)}s`;
|
|
5552
|
+
}
|
|
5553
|
+
return `${(ms / 6e4).toFixed(1)}min`;
|
|
5554
|
+
}
|
|
5555
|
+
const ANSI_RE = /\x1B\[[0-9;]*m/g;
|
|
5556
|
+
function pad(str, width, align = "left") {
|
|
5557
|
+
const stripped = str.replace(ANSI_RE, "");
|
|
5558
|
+
const diff = width - stripped.length;
|
|
5559
|
+
if (diff <= 0) {
|
|
5560
|
+
return str;
|
|
5561
|
+
}
|
|
5562
|
+
const padding = " ".repeat(diff);
|
|
5563
|
+
return align === "right" ? padding + str : str + padding;
|
|
5564
|
+
}
|
|
5565
|
+
function round(n) {
|
|
5566
|
+
return Math.round(n * 100) / 100;
|
|
5567
|
+
}
|
|
5568
|
+
const SLOW_HOOK_THRESHOLD_MS = Number(process.env.NUXT_PERF_SLOW_HOOK_MS) || 50;
|
|
5569
|
+
const HOOK_PHASE_THRESHOLD_MS = 5;
|
|
5570
|
+
class NuxtPerfProfiler {
|
|
5571
|
+
#phases = [];
|
|
5572
|
+
#phaseStack = [];
|
|
5573
|
+
#hookPhases = [];
|
|
5574
|
+
#hookStartStack = [];
|
|
5575
|
+
#modules = [];
|
|
5576
|
+
#bundlerPluginTimings = /* @__PURE__ */ new Map();
|
|
5577
|
+
#bundlerPluginSpans = [];
|
|
5578
|
+
#globalStart;
|
|
5579
|
+
#globalMemoryBefore;
|
|
5580
|
+
#unsubscribe;
|
|
5581
|
+
/** Offset to convert performance.now() (ms) to epoch microseconds for trace events */
|
|
5582
|
+
#baseTs;
|
|
5583
|
+
constructor(options) {
|
|
5584
|
+
if (options?.startTime) {
|
|
5585
|
+
this.#globalStart = performance.now() - (Date.now() - options.startTime);
|
|
5586
|
+
} else {
|
|
5587
|
+
this.#globalStart = performance.now();
|
|
5588
|
+
}
|
|
5589
|
+
this.#globalMemoryBefore = getMemorySnapshot();
|
|
5590
|
+
this.#baseTs = Date.now() * 1e3 - this.#globalStart * 1e3;
|
|
5591
|
+
}
|
|
5592
|
+
installHookInterceptors(hooks) {
|
|
5593
|
+
const unsubBefore = hooks.beforeEach((event) => {
|
|
5594
|
+
this.#hookStartStack.push({
|
|
5595
|
+
name: event.name,
|
|
5596
|
+
time: performance.now(),
|
|
5597
|
+
memory: getMemorySnapshot()
|
|
5598
|
+
});
|
|
5599
|
+
});
|
|
5600
|
+
const unsubAfter = hooks.afterEach((event) => {
|
|
5601
|
+
let startIdx = -1;
|
|
5602
|
+
for (let i = this.#hookStartStack.length - 1; i >= 0; i--) {
|
|
5603
|
+
if (this.#hookStartStack[i].name === event.name) {
|
|
5604
|
+
startIdx = i;
|
|
5605
|
+
break;
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5608
|
+
if (startIdx === -1) {
|
|
5609
|
+
return;
|
|
5610
|
+
}
|
|
5611
|
+
const start = this.#hookStartStack.splice(startIdx, 1)[0];
|
|
5612
|
+
const endTime = performance.now();
|
|
5613
|
+
const memoryAfter = getMemorySnapshot();
|
|
5614
|
+
const duration = round(endTime - start.time);
|
|
5615
|
+
this.#hookPhases.push({
|
|
5616
|
+
name: `hook:${event.name}`,
|
|
5617
|
+
startTime: start.time,
|
|
5618
|
+
endTime,
|
|
5619
|
+
duration,
|
|
5620
|
+
memoryBefore: start.memory,
|
|
5621
|
+
memoryAfter,
|
|
5622
|
+
memoryDelta: {
|
|
5623
|
+
rss: memoryAfter.rss - start.memory.rss,
|
|
5624
|
+
heapUsed: memoryAfter.heapUsed - start.memory.heapUsed
|
|
5625
|
+
}
|
|
5626
|
+
});
|
|
5627
|
+
});
|
|
5628
|
+
this.#unsubscribe = () => {
|
|
5629
|
+
unsubBefore();
|
|
5630
|
+
unsubAfter();
|
|
5631
|
+
};
|
|
5632
|
+
}
|
|
5633
|
+
startPhase(name) {
|
|
5634
|
+
this.#phaseStack.push({
|
|
5635
|
+
name,
|
|
5636
|
+
startTime: performance.now(),
|
|
5637
|
+
memoryBefore: getMemorySnapshot()
|
|
5638
|
+
});
|
|
5639
|
+
}
|
|
5640
|
+
endPhase(name) {
|
|
5641
|
+
let phaseIdx = this.#phaseStack.length - 1;
|
|
5642
|
+
if (name) {
|
|
5643
|
+
phaseIdx = -1;
|
|
5644
|
+
for (let i = this.#phaseStack.length - 1; i >= 0; i--) {
|
|
5645
|
+
if (this.#phaseStack[i].name === name) {
|
|
5646
|
+
phaseIdx = i;
|
|
5647
|
+
break;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
if (phaseIdx === -1) {
|
|
5651
|
+
return;
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5654
|
+
if (phaseIdx < 0) {
|
|
5655
|
+
return;
|
|
5656
|
+
}
|
|
5657
|
+
const open = this.#phaseStack.splice(phaseIdx, 1)[0];
|
|
5658
|
+
const endTime = performance.now();
|
|
5659
|
+
const memoryAfter = getMemorySnapshot();
|
|
5660
|
+
this.#phases.push({
|
|
5661
|
+
name: open.name,
|
|
5662
|
+
startTime: open.startTime,
|
|
5663
|
+
endTime,
|
|
5664
|
+
duration: round(endTime - open.startTime),
|
|
5665
|
+
memoryBefore: open.memoryBefore,
|
|
5666
|
+
memoryAfter,
|
|
5667
|
+
memoryDelta: {
|
|
5668
|
+
rss: memoryAfter.rss - open.memoryBefore.rss,
|
|
5669
|
+
heapUsed: memoryAfter.heapUsed - open.memoryBefore.heapUsed
|
|
5670
|
+
}
|
|
5671
|
+
});
|
|
5672
|
+
}
|
|
5673
|
+
recordBundlerPluginHook(pluginName, hookName, durationMs, startTime) {
|
|
5674
|
+
let plugin = this.#bundlerPluginTimings.get(pluginName);
|
|
5675
|
+
if (!plugin) {
|
|
5676
|
+
plugin = /* @__PURE__ */ new Map();
|
|
5677
|
+
this.#bundlerPluginTimings.set(pluginName, plugin);
|
|
5678
|
+
}
|
|
5679
|
+
const entry = plugin.get(hookName);
|
|
5680
|
+
if (entry) {
|
|
5681
|
+
entry.totalTime += durationMs;
|
|
5682
|
+
entry.count++;
|
|
5683
|
+
if (durationMs > entry.maxTime) {
|
|
5684
|
+
entry.maxTime = durationMs;
|
|
5685
|
+
}
|
|
5686
|
+
} else {
|
|
5687
|
+
plugin.set(hookName, { totalTime: durationMs, count: 1, maxTime: durationMs });
|
|
5688
|
+
}
|
|
5689
|
+
if (startTime != null && durationMs > 0.1) {
|
|
5690
|
+
this.#bundlerPluginSpans.push({ pluginName, hookName, startTime, durationMs });
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5693
|
+
collectModuleTimings(installedModules) {
|
|
5694
|
+
for (const mod of installedModules) {
|
|
5695
|
+
const name = mod.meta?.name || "(anonymous)";
|
|
5696
|
+
const setupTime = mod.timings?.setup;
|
|
5697
|
+
if (setupTime != null) {
|
|
5698
|
+
this.#modules.push({ name, setupTime });
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
}
|
|
5702
|
+
getReport() {
|
|
5703
|
+
const totalDuration = round(performance.now() - this.#globalStart);
|
|
5704
|
+
const globalMemoryAfter = getMemorySnapshot();
|
|
5705
|
+
const allPhases = [...this.#phases];
|
|
5706
|
+
for (const hp of this.#hookPhases) {
|
|
5707
|
+
if (hp.duration < HOOK_PHASE_THRESHOLD_MS) {
|
|
5708
|
+
continue;
|
|
5709
|
+
}
|
|
5710
|
+
const hookName = hp.name.slice(5);
|
|
5711
|
+
const alreadyCovered = this.#phases.some(
|
|
5712
|
+
(p) => p.name === hookName && p.startTime <= hp.startTime && p.endTime >= hp.endTime
|
|
5713
|
+
);
|
|
5714
|
+
if (!alreadyCovered) {
|
|
5715
|
+
allPhases.push({ ...hp, name: hookName });
|
|
5716
|
+
}
|
|
5717
|
+
}
|
|
5718
|
+
allPhases.sort((a, b) => a.startTime - b.startTime);
|
|
5719
|
+
function computeOwn(phase) {
|
|
5720
|
+
const children = allPhases.filter(
|
|
5721
|
+
(other) => other !== phase && other.startTime >= phase.startTime && other.endTime <= phase.endTime
|
|
5722
|
+
);
|
|
5723
|
+
const directChildren = children.filter(
|
|
5724
|
+
(child) => !children.some(
|
|
5725
|
+
(other) => other !== child && child.startTime >= other.startTime && child.endTime <= other.endTime
|
|
5726
|
+
)
|
|
5727
|
+
);
|
|
5728
|
+
let childTime = 0;
|
|
5729
|
+
let childRss = 0;
|
|
5730
|
+
let childHeap = 0;
|
|
5731
|
+
for (const child of directChildren) {
|
|
5732
|
+
childTime += child.duration;
|
|
5733
|
+
childRss += child.memoryDelta.rss;
|
|
5734
|
+
childHeap += child.memoryDelta.heapUsed;
|
|
5735
|
+
}
|
|
5736
|
+
return {
|
|
5737
|
+
ownDuration: round(Math.max(0, phase.duration - childTime)),
|
|
5738
|
+
ownMemoryDelta: {
|
|
5739
|
+
rss: phase.memoryDelta.rss - childRss,
|
|
5740
|
+
heapUsed: phase.memoryDelta.heapUsed - childHeap
|
|
5741
|
+
}
|
|
5742
|
+
};
|
|
5743
|
+
}
|
|
5744
|
+
return {
|
|
5745
|
+
totalDuration,
|
|
5746
|
+
totalMemoryDelta: {
|
|
5747
|
+
rss: globalMemoryAfter.rss - this.#globalMemoryBefore.rss,
|
|
5748
|
+
heapUsed: globalMemoryAfter.heapUsed - this.#globalMemoryBefore.heapUsed
|
|
5749
|
+
},
|
|
5750
|
+
phases: allPhases.map((p) => {
|
|
5751
|
+
const own = computeOwn(p);
|
|
5752
|
+
return {
|
|
5753
|
+
name: p.name,
|
|
5754
|
+
duration: p.duration,
|
|
5755
|
+
ownDuration: own.ownDuration,
|
|
5756
|
+
memoryBefore: p.memoryBefore,
|
|
5757
|
+
memoryAfter: p.memoryAfter,
|
|
5758
|
+
memoryDelta: p.memoryDelta,
|
|
5759
|
+
ownMemoryDelta: own.ownMemoryDelta
|
|
5760
|
+
};
|
|
5761
|
+
}),
|
|
5762
|
+
slowHooks: this.#computeSlowHooks(new Set(allPhases.map((p) => p.name))),
|
|
5763
|
+
modules: [...this.#modules].sort((a, b) => b.setupTime - a.setupTime),
|
|
5764
|
+
bundlerPlugins: [...this.#bundlerPluginTimings.entries()].map(([name, hookMap]) => {
|
|
5765
|
+
const hooks = {};
|
|
5766
|
+
for (const [hookName, t] of hookMap) {
|
|
5767
|
+
hooks[hookName] = {
|
|
5768
|
+
totalTime: round(t.totalTime),
|
|
5769
|
+
count: t.count,
|
|
5770
|
+
maxTime: round(t.maxTime),
|
|
5771
|
+
avgTime: round(t.totalTime / t.count)
|
|
5772
|
+
};
|
|
5773
|
+
}
|
|
5774
|
+
return { name, hooks };
|
|
5775
|
+
}).sort((a, b) => {
|
|
5776
|
+
const aTotal = Object.values(a.hooks).reduce((s, h) => s + h.totalTime, 0);
|
|
5777
|
+
const bTotal = Object.values(b.hooks).reduce((s, h) => s + h.totalTime, 0);
|
|
5778
|
+
return bTotal - aTotal;
|
|
5779
|
+
}),
|
|
5780
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5781
|
+
};
|
|
5782
|
+
}
|
|
5783
|
+
printReport(options) {
|
|
5784
|
+
const report = this.getReport();
|
|
5785
|
+
const isSubPhase = (name) => name.startsWith("module:") || name.startsWith("vite:");
|
|
5786
|
+
const topPhases = report.phases.filter((p) => !isSubPhase(p.name));
|
|
5787
|
+
const subPhases = report.phases.filter((p) => isSubPhase(p.name));
|
|
5788
|
+
consola.log("");
|
|
5789
|
+
consola.log(colors.bold(colors.cyan(` ${options?.title || "Nuxt Performance Report"}`)));
|
|
5790
|
+
consola.log("");
|
|
5791
|
+
const colPhase = 24;
|
|
5792
|
+
const colDuration = 10;
|
|
5793
|
+
const colRss = 14;
|
|
5794
|
+
const colHeap = 14;
|
|
5795
|
+
const maxDuration = Math.max(...topPhases.map((p) => p.ownDuration), 1);
|
|
5796
|
+
const header = [
|
|
5797
|
+
pad(colors.bold("Phase"), colPhase),
|
|
5798
|
+
pad(colors.bold("Duration"), colDuration, "right"),
|
|
5799
|
+
pad(colors.bold("RSS Delta"), colRss, "right"),
|
|
5800
|
+
pad(colors.bold("Heap Delta"), colHeap, "right")
|
|
5801
|
+
].join(" ");
|
|
5802
|
+
consola.log(` ${header}`);
|
|
5803
|
+
const separator = " " + colors.dim("\u2500".repeat(colPhase + colDuration + colRss + colHeap + 6));
|
|
5804
|
+
consola.log(separator);
|
|
5805
|
+
const maxRss = Math.max(...topPhases.map((p) => Math.abs(p.ownMemoryDelta.rss)), 1);
|
|
5806
|
+
const barMax = 20;
|
|
5807
|
+
for (const phase of topPhases) {
|
|
5808
|
+
const dur = phase.ownDuration;
|
|
5809
|
+
const rss = phase.ownMemoryDelta.rss;
|
|
5810
|
+
const heap = phase.ownMemoryDelta.heapUsed;
|
|
5811
|
+
const durBar = dur > 0 ? Math.max(1, Math.round(Math.log(dur + 1) / Math.log(maxDuration + 1) * (barMax / 2))) : 0;
|
|
5812
|
+
const memBar = Math.abs(rss) > 0 ? Math.max(0, Math.round(Math.abs(rss) / maxRss * (barMax / 2))) : 0;
|
|
5813
|
+
const durColor = dur > 1e3 ? colors.red : dur > 200 ? colors.yellow : colors.green;
|
|
5814
|
+
const memColor = Math.abs(rss) > 50 * 1024 * 1024 ? colors.red : Math.abs(rss) > 10 * 1024 * 1024 ? colors.yellow : colors.green;
|
|
5815
|
+
const bar = durColor("\u2588".repeat(durBar)) + memColor("\u2591".repeat(memBar));
|
|
5816
|
+
const row = [
|
|
5817
|
+
pad(phase.name, colPhase),
|
|
5818
|
+
pad(durColor(formatDuration(dur)), colDuration, "right"),
|
|
5819
|
+
pad(memColor((rss >= 0 ? "+" : "") + formatBytes(rss)), colRss, "right"),
|
|
5820
|
+
pad((heap >= 0 ? "+" : "") + formatBytes(heap), colHeap, "right")
|
|
5821
|
+
].join(" ");
|
|
5822
|
+
consola.log(` ${row} ${bar}`);
|
|
5823
|
+
}
|
|
5824
|
+
consola.log(separator);
|
|
5825
|
+
const totalRow = [
|
|
5826
|
+
pad(colors.bold("Total"), colPhase),
|
|
5827
|
+
pad(colors.bold(formatDuration(report.totalDuration)), colDuration, "right"),
|
|
5828
|
+
pad(colors.bold((report.totalMemoryDelta.rss >= 0 ? "+" : "") + formatBytes(report.totalMemoryDelta.rss)), colRss, "right"),
|
|
5829
|
+
pad(colors.bold((report.totalMemoryDelta.heapUsed >= 0 ? "+" : "") + formatBytes(report.totalMemoryDelta.heapUsed)), colHeap, "right")
|
|
5830
|
+
].join(" ");
|
|
5831
|
+
consola.log(` ${totalRow}`);
|
|
5832
|
+
consola.log("");
|
|
5833
|
+
const significantModules = report.modules.filter((m) => m.setupTime > 5);
|
|
5834
|
+
if (significantModules.length > 0) {
|
|
5835
|
+
consola.log(colors.bold(` Modules`));
|
|
5836
|
+
consola.log("");
|
|
5837
|
+
for (const mod of significantModules) {
|
|
5838
|
+
const durColor = mod.setupTime > 500 ? colors.red : mod.setupTime > 100 ? colors.yellow : colors.dim;
|
|
5839
|
+
consola.log(` ${colors.dim("\u2022")} ${mod.name} ${colors.dim("\u2014")} ${durColor(formatDuration(mod.setupTime))}`);
|
|
5840
|
+
}
|
|
5841
|
+
consola.log("");
|
|
5842
|
+
}
|
|
5843
|
+
if (report.bundlerPlugins.length > 0) {
|
|
5844
|
+
const rows = [];
|
|
5845
|
+
for (const plugin of report.bundlerPlugins) {
|
|
5846
|
+
for (const [hook, timing] of Object.entries(plugin.hooks)) {
|
|
5847
|
+
if (timing.avgTime > 0.5) {
|
|
5848
|
+
rows.push({ plugin: plugin.name, hook, timing });
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5852
|
+
rows.sort((a, b) => b.timing.avgTime - a.timing.avgTime);
|
|
5853
|
+
if (rows.length > 0) {
|
|
5854
|
+
consola.log(colors.bold(` Bundler Plugins`));
|
|
5855
|
+
consola.log("");
|
|
5856
|
+
for (const { plugin, hook, timing } of rows.slice(0, 15)) {
|
|
5857
|
+
const durColor = timing.avgTime > 10 ? colors.red : timing.avgTime > 2 ? colors.yellow : colors.dim;
|
|
5858
|
+
const avgLabel = formatDuration(timing.avgTime) + "/file";
|
|
5859
|
+
const maxLabel = timing.maxTime > timing.avgTime * 2 ? `, max ${formatDuration(timing.maxTime)}` : "";
|
|
5860
|
+
consola.log(` ${colors.dim("\u2022")} ${plugin} ${colors.dim(hook)} ${colors.dim("\u2014")} ${durColor(avgLabel)}${colors.dim(maxLabel)} ${colors.dim(`(${timing.count} calls)`)}`);
|
|
5861
|
+
}
|
|
5862
|
+
consola.log("");
|
|
5863
|
+
}
|
|
5864
|
+
}
|
|
5865
|
+
if (report.slowHooks.length > 0) {
|
|
5866
|
+
consola.log(colors.bold(colors.yellow(` Slow Hooks (>${SLOW_HOOK_THRESHOLD_MS}ms own time)`)));
|
|
5867
|
+
consola.log("");
|
|
5868
|
+
for (const hook of report.slowHooks) {
|
|
5869
|
+
const durColor = hook.ownDuration > 500 ? colors.red : hook.ownDuration > 200 ? colors.yellow : colors.dim;
|
|
5870
|
+
const ownLabel = hook.ownDuration !== hook.duration ? `${formatDuration(hook.ownDuration)} own / ${formatDuration(hook.duration)} total` : formatDuration(hook.ownDuration);
|
|
5871
|
+
consola.log(` ${colors.dim("\u2022")} ${hook.name} ${colors.dim("\u2014")} ${durColor(ownLabel)} ${colors.dim(`(${hook.phase})`)}`);
|
|
5872
|
+
}
|
|
5873
|
+
consola.log("");
|
|
5874
|
+
}
|
|
5875
|
+
const significantSubs = subPhases.filter((p) => p.duration > 5);
|
|
5876
|
+
if (significantSubs.length > 0) {
|
|
5877
|
+
consola.log(colors.bold(` Details`));
|
|
5878
|
+
consola.log("");
|
|
5879
|
+
for (const phase of significantSubs) {
|
|
5880
|
+
const durColor = phase.duration > 500 ? colors.red : phase.duration > 100 ? colors.yellow : colors.dim;
|
|
5881
|
+
consola.log(` ${colors.dim("\u2022")} ${phase.name} ${colors.dim("\u2014")} ${durColor(formatDuration(phase.duration))}`);
|
|
5882
|
+
}
|
|
5883
|
+
consola.log("");
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
/**
|
|
5887
|
+
* Generate trace events in Chrome Trace Event format.
|
|
5888
|
+
* The output can be loaded in chrome://tracing or https://ui.perfetto.dev
|
|
5889
|
+
*/
|
|
5890
|
+
getTraceEvents() {
|
|
5891
|
+
const events = [];
|
|
5892
|
+
const pid = 1;
|
|
5893
|
+
const tidPhases = 1;
|
|
5894
|
+
const tidHooks = 2;
|
|
5895
|
+
const tidPluginBase = 10;
|
|
5896
|
+
const toUs = (ms) => Math.round(ms * 1e3 + this.#baseTs);
|
|
5897
|
+
events.push(
|
|
5898
|
+
{ name: "process_name", ph: "M", ts: 0, pid, tid: 0, cat: "", args: { name: "Nuxt Build" } },
|
|
5899
|
+
{ name: "thread_name", ph: "M", ts: 0, pid, tid: tidPhases, cat: "", args: { name: "Build" } },
|
|
5900
|
+
{ name: "thread_name", ph: "M", ts: 0, pid, tid: tidHooks, cat: "", args: { name: "Hooks" } }
|
|
5901
|
+
);
|
|
5902
|
+
const durUs = (ms) => Math.round(ms * 1e3);
|
|
5903
|
+
const globalEnd = performance.now();
|
|
5904
|
+
events.push(
|
|
5905
|
+
{ name: "nuxt build", cat: "build", ph: "B", ts: toUs(this.#globalStart), pid, tid: tidPhases },
|
|
5906
|
+
{ name: "nuxt build", cat: "build", ph: "E", ts: toUs(globalEnd), pid, tid: tidPhases }
|
|
5907
|
+
);
|
|
5908
|
+
for (const phase of this.#phases) {
|
|
5909
|
+
events.push(
|
|
5910
|
+
{
|
|
5911
|
+
name: phase.name,
|
|
5912
|
+
cat: "phase",
|
|
5913
|
+
ph: "B",
|
|
5914
|
+
ts: toUs(phase.startTime),
|
|
5915
|
+
pid,
|
|
5916
|
+
tid: tidPhases,
|
|
5917
|
+
args: {
|
|
5918
|
+
memoryBefore: { rss: phase.memoryBefore.rss, heapUsed: phase.memoryBefore.heapUsed }
|
|
5919
|
+
}
|
|
5920
|
+
},
|
|
5921
|
+
{
|
|
5922
|
+
name: phase.name,
|
|
5923
|
+
cat: "phase",
|
|
5924
|
+
ph: "E",
|
|
5925
|
+
ts: toUs(phase.endTime),
|
|
5926
|
+
pid,
|
|
5927
|
+
tid: tidPhases,
|
|
5928
|
+
args: {
|
|
5929
|
+
memoryDelta: { rss: phase.memoryDelta.rss, heapUsed: phase.memoryDelta.heapUsed }
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
);
|
|
5933
|
+
}
|
|
5934
|
+
for (const hp of this.#hookPhases) {
|
|
5935
|
+
const name = hp.name.startsWith("hook:") ? hp.name.slice(5) : hp.name;
|
|
5936
|
+
events.push(
|
|
5937
|
+
{ name, cat: "hook", ph: "B", ts: toUs(hp.startTime), pid, tid: tidHooks },
|
|
5938
|
+
{ name, cat: "hook", ph: "E", ts: toUs(hp.endTime), pid, tid: tidHooks }
|
|
5939
|
+
);
|
|
5940
|
+
}
|
|
5941
|
+
const viteSpans = this.#bundlerPluginSpans.filter((s) => !s.pluginName.startsWith("nitro:"));
|
|
5942
|
+
const nitroSpans = this.#bundlerPluginSpans.filter((s) => s.pluginName.startsWith("nitro:"));
|
|
5943
|
+
const emitPluginSpans = (spans, label, baseTid) => {
|
|
5944
|
+
if (spans.length === 0) {
|
|
5945
|
+
return;
|
|
5946
|
+
}
|
|
5947
|
+
const sorted = [...spans].sort((a, b) => a.startTime - b.startTime);
|
|
5948
|
+
const laneEnds = [];
|
|
5949
|
+
for (const span of sorted) {
|
|
5950
|
+
const endTime = span.startTime + span.durationMs;
|
|
5951
|
+
let lane = laneEnds.findIndex((end) => end < span.startTime);
|
|
5952
|
+
if (lane === -1) {
|
|
5953
|
+
lane = laneEnds.length;
|
|
5954
|
+
laneEnds.push(0);
|
|
5955
|
+
}
|
|
5956
|
+
laneEnds[lane] = endTime;
|
|
5957
|
+
const tid = baseTid + lane;
|
|
5958
|
+
events.push({
|
|
5959
|
+
name: `${span.pluginName}:${span.hookName}`,
|
|
5960
|
+
cat: label,
|
|
5961
|
+
ph: "X",
|
|
5962
|
+
ts: toUs(span.startTime),
|
|
5963
|
+
dur: durUs(span.durationMs),
|
|
5964
|
+
pid,
|
|
5965
|
+
tid
|
|
5966
|
+
});
|
|
5967
|
+
}
|
|
5968
|
+
for (let i = 0; i < laneEnds.length; i++) {
|
|
5969
|
+
const suffix = laneEnds.length > 1 ? ` ${i + 1}` : "";
|
|
5970
|
+
events.push({
|
|
5971
|
+
name: "thread_name",
|
|
5972
|
+
ph: "M",
|
|
5973
|
+
ts: 0,
|
|
5974
|
+
pid,
|
|
5975
|
+
tid: baseTid + i,
|
|
5976
|
+
cat: "",
|
|
5977
|
+
args: { name: `${label}${suffix}` }
|
|
5978
|
+
});
|
|
5979
|
+
}
|
|
5980
|
+
};
|
|
5981
|
+
emitPluginSpans(viteSpans, "Vite Plugins", tidPluginBase);
|
|
5982
|
+
emitPluginSpans(nitroSpans, "Nitro Plugins", tidPluginBase + 100);
|
|
5983
|
+
for (const phase of this.#phases) {
|
|
5984
|
+
events.push(
|
|
5985
|
+
{
|
|
5986
|
+
name: "Memory",
|
|
5987
|
+
cat: "memory",
|
|
5988
|
+
ph: "C",
|
|
5989
|
+
ts: toUs(phase.startTime),
|
|
5990
|
+
pid,
|
|
5991
|
+
tid: 0,
|
|
5992
|
+
args: { rss: phase.memoryBefore.rss, heapUsed: phase.memoryBefore.heapUsed }
|
|
5993
|
+
},
|
|
5994
|
+
{
|
|
5995
|
+
name: "Memory",
|
|
5996
|
+
cat: "memory",
|
|
5997
|
+
ph: "C",
|
|
5998
|
+
ts: toUs(phase.endTime),
|
|
5999
|
+
pid,
|
|
6000
|
+
tid: 0,
|
|
6001
|
+
args: { rss: phase.memoryAfter.rss, heapUsed: phase.memoryAfter.heapUsed }
|
|
6002
|
+
}
|
|
6003
|
+
);
|
|
6004
|
+
}
|
|
6005
|
+
return events;
|
|
6006
|
+
}
|
|
6007
|
+
writeReport(buildDir, options) {
|
|
6008
|
+
const report = this.getReport();
|
|
6009
|
+
const reportPath = join(buildDir, "perf-report.json");
|
|
6010
|
+
const relativeReportPath = relative(process.cwd(), reportPath).replace(/^(?![^.]{1,2}\/)/, "./");
|
|
6011
|
+
const tracePath = join(buildDir, "perf-trace.json");
|
|
6012
|
+
const relativeTracePath = relative(process.cwd(), tracePath).replace(/^(?![^.]{1,2}\/)/, "./");
|
|
6013
|
+
try {
|
|
6014
|
+
mkdirSync(buildDir, { recursive: true });
|
|
6015
|
+
writeFileSync(reportPath, JSON.stringify(report, null, 2), "utf-8");
|
|
6016
|
+
writeFileSync(tracePath, JSON.stringify({ traceEvents: this.getTraceEvents() }), "utf-8");
|
|
6017
|
+
if (!options?.quiet) {
|
|
6018
|
+
consola.log(colors.dim(` Data dump written to ${relativeReportPath}`));
|
|
6019
|
+
consola.log(colors.dim(` Trace written to ${relativeTracePath} (load in \`https://ui.perfetto.dev\`)`));
|
|
6020
|
+
consola.log("");
|
|
6021
|
+
}
|
|
6022
|
+
} catch {
|
|
6023
|
+
}
|
|
6024
|
+
return reportPath;
|
|
6025
|
+
}
|
|
6026
|
+
dispose() {
|
|
6027
|
+
this.#unsubscribe?.();
|
|
6028
|
+
}
|
|
6029
|
+
#computeSlowHooks(reportedPhaseNames) {
|
|
6030
|
+
const hooks = [];
|
|
6031
|
+
for (const hp of this.#hookPhases) {
|
|
6032
|
+
if (hp.duration < SLOW_HOOK_THRESHOLD_MS) {
|
|
6033
|
+
continue;
|
|
6034
|
+
}
|
|
6035
|
+
const hookName = hp.name.slice(5);
|
|
6036
|
+
if (reportedPhaseNames.has(hookName)) {
|
|
6037
|
+
continue;
|
|
6038
|
+
}
|
|
6039
|
+
let attributedTime = 0;
|
|
6040
|
+
for (const phase of this.#phases) {
|
|
6041
|
+
const overlapStart = Math.max(phase.startTime, hp.startTime);
|
|
6042
|
+
const overlapEnd = Math.min(phase.endTime, hp.endTime);
|
|
6043
|
+
if (overlapEnd > overlapStart) {
|
|
6044
|
+
attributedTime += overlapEnd - overlapStart;
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
for (const other of this.#hookPhases) {
|
|
6048
|
+
if (other === hp) {
|
|
6049
|
+
continue;
|
|
6050
|
+
}
|
|
6051
|
+
if (other.startTime >= hp.startTime && other.endTime <= hp.endTime) {
|
|
6052
|
+
attributedTime += other.duration;
|
|
6053
|
+
}
|
|
6054
|
+
}
|
|
6055
|
+
const ownDuration = round(hp.duration - round(attributedTime));
|
|
6056
|
+
if (ownDuration >= SLOW_HOOK_THRESHOLD_MS) {
|
|
6057
|
+
const parentPhase = this.#phases.find(
|
|
6058
|
+
(p) => p.startTime <= hp.startTime && p.endTime >= hp.endTime
|
|
6059
|
+
);
|
|
6060
|
+
hooks.push({
|
|
6061
|
+
name: hookName,
|
|
6062
|
+
duration: hp.duration,
|
|
6063
|
+
ownDuration,
|
|
6064
|
+
phase: parentPhase?.name || "(between phases)"
|
|
6065
|
+
});
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
return hooks.sort((a, b) => b.ownDuration - a.ownDuration);
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
|
|
4241
6072
|
const schemaModule = defineNuxtModule({
|
|
4242
6073
|
meta: {
|
|
4243
6074
|
name: "nuxt:nuxt-config-schema"
|
|
@@ -4359,654 +6190,201 @@ declare module '@nuxt/schema' {
|
|
|
4359
6190
|
interface NuxtOptions extends Omit<NuxtCustomSchema, 'appConfig'> {}
|
|
4360
6191
|
interface CustomAppConfig extends _CustomAppConfig {}
|
|
4361
6192
|
}
|
|
4362
|
-
|
|
4363
|
-
declare module 'nuxt/schema' {
|
|
4364
|
-
interface NuxtConfig extends Omit<NuxtCustomSchema, 'appConfig'> {}
|
|
4365
|
-
interface NuxtOptions extends Omit<NuxtCustomSchema, 'appConfig'> {}
|
|
4366
|
-
interface CustomAppConfig extends _CustomAppConfig {}
|
|
4367
|
-
}
|
|
4368
|
-
`;
|
|
4369
|
-
const typesPath = resolve(nuxt.options.buildDir, "schema/nuxt.schema.d.ts");
|
|
4370
|
-
await writeFile(typesPath, types, "utf8");
|
|
4371
|
-
await nuxt.hooks.callHook("schema:written");
|
|
4372
|
-
}
|
|
4373
|
-
}
|
|
4374
|
-
});
|
|
4375
|
-
|
|
4376
|
-
const internalOrderMap = {
|
|
4377
|
-
// -40: custom payload revivers (user)
|
|
4378
|
-
"user-revivers": -40,
|
|
4379
|
-
// -20: pre (user) <-- pre mapped to this
|
|
4380
|
-
"user-pre": -20,
|
|
4381
|
-
// 0: default (user) <-- default behavior
|
|
4382
|
-
"user-default": 0,
|
|
4383
|
-
// +20: post (user) <-- post mapped to this
|
|
4384
|
-
"user-post": 20};
|
|
4385
|
-
const orderMap = {
|
|
4386
|
-
pre: internalOrderMap["user-pre"],
|
|
4387
|
-
default: internalOrderMap["user-default"],
|
|
4388
|
-
post: internalOrderMap["user-post"]
|
|
4389
|
-
};
|
|
4390
|
-
const metaCache = {};
|
|
4391
|
-
function extractMetadata(code, loader = "ts") {
|
|
4392
|
-
let meta = {};
|
|
4393
|
-
if (metaCache[code]) {
|
|
4394
|
-
return metaCache[code];
|
|
4395
|
-
}
|
|
4396
|
-
if (/defineNuxtPlugin\s*\([\w(]/.test(code)) {
|
|
4397
|
-
return {};
|
|
4398
|
-
}
|
|
4399
|
-
parseAndWalk(code, `file.${loader}`, (node) => {
|
|
4400
|
-
if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
|
|
4401
|
-
return;
|
|
4402
|
-
}
|
|
4403
|
-
const name = "name" in node.callee && node.callee.name;
|
|
4404
|
-
if (name !== "defineNuxtPlugin" && name !== "definePayloadPlugin") {
|
|
4405
|
-
return;
|
|
4406
|
-
}
|
|
4407
|
-
if (name === "definePayloadPlugin") {
|
|
4408
|
-
meta.order = internalOrderMap["user-revivers"];
|
|
4409
|
-
}
|
|
4410
|
-
const metaArg = node.arguments[1];
|
|
4411
|
-
if (metaArg) {
|
|
4412
|
-
if (metaArg.type !== "ObjectExpression") {
|
|
4413
|
-
throw new Error("Invalid plugin metadata");
|
|
4414
|
-
}
|
|
4415
|
-
meta = extractMetaFromObject(metaArg.properties);
|
|
4416
|
-
}
|
|
4417
|
-
const plugin = node.arguments[0];
|
|
4418
|
-
if (plugin?.type === "ObjectExpression") {
|
|
4419
|
-
meta = defu(extractMetaFromObject(plugin.properties), meta);
|
|
4420
|
-
}
|
|
4421
|
-
meta.order ||= orderMap[meta.enforce || "default"] || orderMap.default;
|
|
4422
|
-
delete meta.enforce;
|
|
4423
|
-
});
|
|
4424
|
-
metaCache[code] = meta;
|
|
4425
|
-
return meta;
|
|
4426
|
-
}
|
|
4427
|
-
const keys = {
|
|
4428
|
-
name: "name",
|
|
4429
|
-
order: "order",
|
|
4430
|
-
enforce: "enforce",
|
|
4431
|
-
dependsOn: "dependsOn"
|
|
4432
|
-
};
|
|
4433
|
-
function isMetadataKey(key) {
|
|
4434
|
-
return typeof key !== "string" ? key.name in keys : key in keys;
|
|
4435
|
-
}
|
|
4436
|
-
function extractMetaFromObject(properties) {
|
|
4437
|
-
const meta = {};
|
|
4438
|
-
for (const property of properties) {
|
|
4439
|
-
if (property.type === "SpreadElement" || !("name" in property.key)) {
|
|
4440
|
-
throw new Error("Invalid plugin metadata");
|
|
4441
|
-
}
|
|
4442
|
-
const propertyKey = property.key.name;
|
|
4443
|
-
if (!isMetadataKey(propertyKey)) {
|
|
4444
|
-
continue;
|
|
4445
|
-
}
|
|
4446
|
-
if (property.value.type === "Literal") {
|
|
4447
|
-
meta[propertyKey] = property.value.value;
|
|
4448
|
-
}
|
|
4449
|
-
if (property.value.type === "UnaryExpression" && property.value.argument.type === "Literal") {
|
|
4450
|
-
meta[propertyKey] = JSON.parse(property.value.operator + property.value.argument.raw);
|
|
4451
|
-
}
|
|
4452
|
-
if (propertyKey === "dependsOn" && property.value.type === "ArrayExpression") {
|
|
4453
|
-
if (property.value.elements.some((e) => !e || e.type !== "Literal" || typeof e.value !== "string")) {
|
|
4454
|
-
throw new Error("dependsOn must take an array of string literals");
|
|
4455
|
-
}
|
|
4456
|
-
meta[propertyKey] = property.value.elements.map((e) => e.value);
|
|
4457
|
-
}
|
|
4458
|
-
}
|
|
4459
|
-
return meta;
|
|
4460
|
-
}
|
|
4461
|
-
const RemovePluginMetadataPlugin = (nuxt) => createUnplugin(() => {
|
|
4462
|
-
return {
|
|
4463
|
-
name: "nuxt:remove-plugin-metadata",
|
|
4464
|
-
transform(code, id) {
|
|
4465
|
-
id = normalize(id);
|
|
4466
|
-
const plugin = nuxt.apps.default?.plugins.find((p) => p.src === id);
|
|
4467
|
-
if (!plugin) {
|
|
4468
|
-
return;
|
|
4469
|
-
}
|
|
4470
|
-
if (!code.trim()) {
|
|
4471
|
-
logger.warn(`Plugin \`${plugin.src}\` has no content.`);
|
|
4472
|
-
return {
|
|
4473
|
-
code: "export default () => {}",
|
|
4474
|
-
map: null
|
|
4475
|
-
};
|
|
4476
|
-
}
|
|
4477
|
-
const exports$1 = findExports(code);
|
|
4478
|
-
const defaultExport = exports$1.find((e) => e.type === "default" || e.name === "default");
|
|
4479
|
-
if (!defaultExport) {
|
|
4480
|
-
logger.warn(`Plugin \`${plugin.src}\` has no default export and will be ignored at build time. Add \`export default defineNuxtPlugin(() => {})\` to your plugin.`);
|
|
4481
|
-
return {
|
|
4482
|
-
code: "export default () => {}",
|
|
4483
|
-
map: null
|
|
4484
|
-
};
|
|
4485
|
-
}
|
|
4486
|
-
const s = new MagicString(code);
|
|
4487
|
-
let wrapped = false;
|
|
4488
|
-
const wrapperNames = /* @__PURE__ */ new Set(["defineNuxtPlugin", "definePayloadPlugin"]);
|
|
4489
|
-
try {
|
|
4490
|
-
parseAndWalk(code, id, (node) => {
|
|
4491
|
-
if (node.type === "ImportSpecifier" && node.imported.type === "Identifier" && (node.imported.name === "defineNuxtPlugin" || node.imported.name === "definePayloadPlugin")) {
|
|
4492
|
-
wrapperNames.add(node.local.name);
|
|
4493
|
-
}
|
|
4494
|
-
if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
|
|
4495
|
-
return;
|
|
4496
|
-
}
|
|
4497
|
-
const name = "name" in node.callee && node.callee.name;
|
|
4498
|
-
if (!name || !wrapperNames.has(name)) {
|
|
4499
|
-
return;
|
|
4500
|
-
}
|
|
4501
|
-
wrapped = true;
|
|
4502
|
-
if (!("order" in plugin) && !("name" in plugin)) {
|
|
4503
|
-
return;
|
|
4504
|
-
}
|
|
4505
|
-
for (const [argIndex, arg] of node.arguments.entries()) {
|
|
4506
|
-
if (arg.type !== "ObjectExpression") {
|
|
4507
|
-
continue;
|
|
4508
|
-
}
|
|
4509
|
-
for (const [propertyIndex, property] of arg.properties.entries()) {
|
|
4510
|
-
if (property.type === "SpreadElement" || !("name" in property.key)) {
|
|
4511
|
-
continue;
|
|
4512
|
-
}
|
|
4513
|
-
const propertyKey = property.key.name;
|
|
4514
|
-
if (propertyKey === "order" || propertyKey === "enforce" || propertyKey === "name") {
|
|
4515
|
-
const nextNode = arg.properties[propertyIndex + 1] || node.arguments[argIndex + 1];
|
|
4516
|
-
const nextIndex = nextNode?.start || arg.end - 1;
|
|
4517
|
-
s.remove(property.start, nextIndex);
|
|
4518
|
-
}
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
});
|
|
4522
|
-
} catch (e) {
|
|
4523
|
-
logger.error(e);
|
|
4524
|
-
return;
|
|
4525
|
-
}
|
|
4526
|
-
if (!wrapped) {
|
|
4527
|
-
logger.warn(`Plugin \`${plugin.src}\` is not wrapped in \`defineNuxtPlugin\`. It is advised to wrap your plugins as in the future this may enable enhancements.`);
|
|
4528
|
-
}
|
|
4529
|
-
if (s.hasChanged()) {
|
|
4530
|
-
return {
|
|
4531
|
-
code: s.toString(),
|
|
4532
|
-
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : null
|
|
4533
|
-
};
|
|
4534
|
-
}
|
|
4535
|
-
}
|
|
4536
|
-
};
|
|
4537
|
-
});
|
|
4538
|
-
|
|
4539
|
-
const AsyncContextInjectionPlugin = (nuxt) => createUnplugin(() => {
|
|
4540
|
-
return {
|
|
4541
|
-
name: "nuxt:vue-async-context",
|
|
4542
|
-
transformInclude(id) {
|
|
4543
|
-
return isVue(id, { type: ["template", "script"] });
|
|
4544
|
-
},
|
|
4545
|
-
transform: {
|
|
4546
|
-
filter: {
|
|
4547
|
-
code: { include: /_withAsyncContext/ }
|
|
4548
|
-
},
|
|
4549
|
-
handler(code) {
|
|
4550
|
-
const s = new MagicString(code);
|
|
4551
|
-
s.prepend('import { withAsyncContext as _withAsyncContext } from "#app/composables/asyncContext";\n');
|
|
4552
|
-
s.replace(/withAsyncContext as _withAsyncContext,?/, "");
|
|
4553
|
-
if (s.hasChanged()) {
|
|
4554
|
-
return {
|
|
4555
|
-
code: s.toString(),
|
|
4556
|
-
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : void 0
|
|
4557
|
-
};
|
|
4558
|
-
}
|
|
4559
|
-
}
|
|
4560
|
-
}
|
|
4561
|
-
};
|
|
4562
|
-
});
|
|
4563
|
-
|
|
4564
|
-
function processImports(imports) {
|
|
4565
|
-
const directImports = /* @__PURE__ */ new Map();
|
|
4566
|
-
const namespaces = /* @__PURE__ */ new Map();
|
|
4567
|
-
for (const i of imports) {
|
|
4568
|
-
const resolvedSpecifier = stripExtension(resolveAlias$1(i.specifier));
|
|
4569
|
-
const namedImports = i.namedImports ?? {};
|
|
4570
|
-
for (const originalIdentifier in namedImports) {
|
|
4571
|
-
const localIdentifier = namedImports[originalIdentifier] || originalIdentifier;
|
|
4572
|
-
directImports.set(localIdentifier, {
|
|
4573
|
-
originalName: originalIdentifier,
|
|
4574
|
-
source: resolvedSpecifier
|
|
4575
|
-
});
|
|
4576
|
-
}
|
|
4577
|
-
if (i.namespacedImport || i.defaultImport) {
|
|
4578
|
-
if (!namespaces.has(resolvedSpecifier)) {
|
|
4579
|
-
namespaces.set(resolvedSpecifier, {
|
|
4580
|
-
namespaces: /* @__PURE__ */ new Set()
|
|
4581
|
-
});
|
|
4582
|
-
}
|
|
4583
|
-
}
|
|
4584
|
-
if (i.defaultImport) {
|
|
4585
|
-
const namespace = i.defaultImport;
|
|
4586
|
-
const entry = namespaces.get(resolvedSpecifier);
|
|
4587
|
-
entry.namespaces.add(namespace);
|
|
4588
|
-
directImports.set(i.defaultImport, {
|
|
4589
|
-
originalName: "default",
|
|
4590
|
-
source: resolvedSpecifier
|
|
4591
|
-
});
|
|
4592
|
-
} else if (i.namespacedImport) {
|
|
4593
|
-
const namespace = i.namespacedImport;
|
|
4594
|
-
const entry = namespaces.get(resolvedSpecifier);
|
|
4595
|
-
entry.namespaces.add(namespace);
|
|
4596
|
-
}
|
|
4597
|
-
}
|
|
4598
|
-
return {
|
|
4599
|
-
directImports,
|
|
4600
|
-
namespaces
|
|
4601
|
-
};
|
|
4602
|
-
}
|
|
4603
|
-
function parseStaticFunctionCall(node, filter) {
|
|
4604
|
-
const callExpression = node.type === "CallExpression" ? node : node.type === "ChainExpression" && node.expression.type === "CallExpression" ? node.expression : null;
|
|
4605
|
-
if (!callExpression) {
|
|
4606
|
-
return null;
|
|
4607
|
-
}
|
|
4608
|
-
let functionName;
|
|
4609
|
-
let identifierNode;
|
|
4610
|
-
if (callExpression.callee.type === "Identifier") {
|
|
4611
|
-
functionName = callExpression.callee.name;
|
|
4612
|
-
identifierNode = callExpression.callee;
|
|
4613
|
-
} else if (callExpression.callee.type === "ParenthesizedExpression") {
|
|
4614
|
-
if (callExpression.callee.expression.type === "Identifier") {
|
|
4615
|
-
functionName = callExpression.callee.expression.name;
|
|
4616
|
-
identifierNode = callExpression.callee;
|
|
4617
|
-
} else if ((callExpression.callee.expression.type === "TSAsExpression" || callExpression.callee.expression.type === "TSTypeAssertion" || callExpression.callee.expression.type === "TSNonNullExpression") && callExpression.callee.expression.expression.type === "Identifier") {
|
|
4618
|
-
functionName = callExpression.callee.expression.expression.name;
|
|
4619
|
-
identifierNode = callExpression.callee;
|
|
6193
|
+
|
|
6194
|
+
declare module 'nuxt/schema' {
|
|
6195
|
+
interface NuxtConfig extends Omit<NuxtCustomSchema, 'appConfig'> {}
|
|
6196
|
+
interface NuxtOptions extends Omit<NuxtCustomSchema, 'appConfig'> {}
|
|
6197
|
+
interface CustomAppConfig extends _CustomAppConfig {}
|
|
6198
|
+
}
|
|
6199
|
+
`;
|
|
6200
|
+
const typesPath = resolve(nuxt.options.buildDir, "schema/nuxt.schema.d.ts");
|
|
6201
|
+
await writeFile(typesPath, types, "utf8");
|
|
6202
|
+
await nuxt.hooks.callHook("schema:written");
|
|
4620
6203
|
}
|
|
4621
6204
|
}
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
6205
|
+
});
|
|
6206
|
+
|
|
6207
|
+
const internalOrderMap = {
|
|
6208
|
+
// -40: custom payload revivers (user)
|
|
6209
|
+
"user-revivers": -40,
|
|
6210
|
+
// -20: pre (user) <-- pre mapped to this
|
|
6211
|
+
"user-pre": -20,
|
|
6212
|
+
// 0: default (user) <-- default behavior
|
|
6213
|
+
"user-default": 0,
|
|
6214
|
+
// +20: post (user) <-- post mapped to this
|
|
6215
|
+
"user-post": 20};
|
|
6216
|
+
const orderMap = {
|
|
6217
|
+
pre: internalOrderMap["user-pre"],
|
|
6218
|
+
default: internalOrderMap["user-default"],
|
|
6219
|
+
post: internalOrderMap["user-post"]
|
|
6220
|
+
};
|
|
6221
|
+
const metaCache = {};
|
|
6222
|
+
function extractMetadata(code, loader = "ts") {
|
|
6223
|
+
let meta = {};
|
|
6224
|
+
if (metaCache[code]) {
|
|
6225
|
+
return metaCache[code];
|
|
4629
6226
|
}
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
if (memberExpression.object.type === "Identifier") {
|
|
4633
|
-
memberObjectName = memberExpression.object.name;
|
|
4634
|
-
} else if (memberExpression.object.type === "ParenthesizedExpression") {
|
|
4635
|
-
if (memberExpression.object.expression.type === "Identifier") {
|
|
4636
|
-
memberObjectName = memberExpression.object.expression.name;
|
|
4637
|
-
} else if ((memberExpression.object.expression.type === "TSAsExpression" || memberExpression.object.expression.type === "TSTypeAssertion" || memberExpression.object.expression.type === "TSNonNullExpression") && memberExpression.object.expression.expression.type === "Identifier") {
|
|
4638
|
-
memberObjectName = memberExpression.object.expression.expression.name;
|
|
4639
|
-
}
|
|
4640
|
-
}
|
|
4641
|
-
if (memberObjectName) {
|
|
4642
|
-
if (memberExpression.property.type === "Identifier" && filter.test(memberExpression.property.name)) {
|
|
4643
|
-
return {
|
|
4644
|
-
name: memberExpression.property.name,
|
|
4645
|
-
namespace: memberObjectName,
|
|
4646
|
-
node: memberExpression.property
|
|
4647
|
-
};
|
|
4648
|
-
}
|
|
4649
|
-
if (memberExpression.property.type === "Literal" && typeof memberExpression.property.value === "string" && filter.test(memberExpression.property.value)) {
|
|
4650
|
-
return {
|
|
4651
|
-
name: memberExpression.property.value,
|
|
4652
|
-
namespace: memberObjectName,
|
|
4653
|
-
node: memberExpression
|
|
4654
|
-
};
|
|
4655
|
-
}
|
|
4656
|
-
}
|
|
4657
|
-
return null;
|
|
6227
|
+
if (/defineNuxtPlugin\s*\([\w(]/.test(code)) {
|
|
6228
|
+
return {};
|
|
4658
6229
|
}
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
return {
|
|
4663
|
-
...val,
|
|
4664
|
-
callExpression
|
|
4665
|
-
};
|
|
6230
|
+
parseAndWalk(code, `file.${loader}`, (node) => {
|
|
6231
|
+
if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
|
|
6232
|
+
return;
|
|
4666
6233
|
}
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
return {
|
|
4671
|
-
...val,
|
|
4672
|
-
node: callExpression.callee,
|
|
4673
|
-
callExpression
|
|
4674
|
-
};
|
|
6234
|
+
const name = "name" in node.callee && node.callee.name;
|
|
6235
|
+
if (name !== "defineNuxtPlugin" && name !== "definePayloadPlugin") {
|
|
6236
|
+
return;
|
|
4675
6237
|
}
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
}
|
|
4679
|
-
function parseStaticExportIdentifiers(node, filter) {
|
|
4680
|
-
if (node.type === "ExportNamedDeclaration" && node.exportKind !== "type") {
|
|
4681
|
-
if (node.declaration?.type === "VariableDeclaration") {
|
|
4682
|
-
return node.declaration.declarations.map((d) => {
|
|
4683
|
-
if (d.id.type === "Identifier" && (true)) {
|
|
4684
|
-
return {
|
|
4685
|
-
localName: d.id.name,
|
|
4686
|
-
exportedName: d.id.name
|
|
4687
|
-
};
|
|
4688
|
-
}
|
|
4689
|
-
return null;
|
|
4690
|
-
}).filter((v) => !!v);
|
|
6238
|
+
if (name === "definePayloadPlugin") {
|
|
6239
|
+
meta.order = internalOrderMap["user-revivers"];
|
|
4691
6240
|
}
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
exportedName: node.declaration.id.name
|
|
4697
|
-
}];
|
|
6241
|
+
const metaArg = node.arguments[1];
|
|
6242
|
+
if (metaArg) {
|
|
6243
|
+
if (metaArg.type !== "ObjectExpression") {
|
|
6244
|
+
throw new Error("Invalid plugin metadata");
|
|
4698
6245
|
}
|
|
4699
|
-
|
|
6246
|
+
meta = extractMetaFromObject(metaArg.properties);
|
|
4700
6247
|
}
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
localName: node.declaration.id.name,
|
|
4705
|
-
exportedName: node.declaration.id.name
|
|
4706
|
-
}];
|
|
4707
|
-
}
|
|
4708
|
-
return [];
|
|
6248
|
+
const plugin = node.arguments[0];
|
|
6249
|
+
if (plugin?.type === "ObjectExpression") {
|
|
6250
|
+
meta = defu(extractMetaFromObject(plugin.properties), meta);
|
|
4709
6251
|
}
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
6252
|
+
meta.order ||= orderMap[meta.enforce || "default"] || orderMap.default;
|
|
6253
|
+
delete meta.enforce;
|
|
6254
|
+
});
|
|
6255
|
+
metaCache[code] = meta;
|
|
6256
|
+
return meta;
|
|
6257
|
+
}
|
|
6258
|
+
const keys = {
|
|
6259
|
+
name: "name",
|
|
6260
|
+
order: "order",
|
|
6261
|
+
enforce: "enforce",
|
|
6262
|
+
dependsOn: "dependsOn"
|
|
6263
|
+
};
|
|
6264
|
+
function isMetadataKey(key) {
|
|
6265
|
+
return typeof key !== "string" ? key.name in keys : key in keys;
|
|
6266
|
+
}
|
|
6267
|
+
function extractMetaFromObject(properties) {
|
|
6268
|
+
const meta = {};
|
|
6269
|
+
for (const property of properties) {
|
|
6270
|
+
if (property.type === "SpreadElement" || !("name" in property.key)) {
|
|
6271
|
+
throw new Error("Invalid plugin metadata");
|
|
4720
6272
|
}
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
if (node.declaration.type === "Identifier") {
|
|
4725
|
-
return [{
|
|
4726
|
-
localName: node.declaration.name,
|
|
4727
|
-
exportedName: "default"
|
|
4728
|
-
}];
|
|
6273
|
+
const propertyKey = property.key.name;
|
|
6274
|
+
if (!isMetadataKey(propertyKey)) {
|
|
6275
|
+
continue;
|
|
4729
6276
|
}
|
|
4730
|
-
if (
|
|
4731
|
-
|
|
4732
|
-
return [{
|
|
4733
|
-
localName: node.declaration.id.name,
|
|
4734
|
-
exportedName: "default"
|
|
4735
|
-
}];
|
|
4736
|
-
}
|
|
4737
|
-
return [];
|
|
6277
|
+
if (property.value.type === "Literal") {
|
|
6278
|
+
meta[propertyKey] = property.value.value;
|
|
4738
6279
|
}
|
|
4739
|
-
if (
|
|
4740
|
-
|
|
4741
|
-
return [{
|
|
4742
|
-
localName: node.declaration.id.name,
|
|
4743
|
-
exportedName: "default"
|
|
4744
|
-
}];
|
|
4745
|
-
}
|
|
4746
|
-
return [];
|
|
6280
|
+
if (property.value.type === "UnaryExpression" && property.value.argument.type === "Literal") {
|
|
6281
|
+
meta[propertyKey] = JSON.parse(property.value.operator + property.value.argument.raw);
|
|
4747
6282
|
}
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
{
|
|
4752
|
-
return [{
|
|
4753
|
-
localName: node.expression.name,
|
|
4754
|
-
exportedName: "default"
|
|
4755
|
-
}];
|
|
6283
|
+
if (propertyKey === "dependsOn" && property.value.type === "ArrayExpression") {
|
|
6284
|
+
if (property.value.elements.some((e) => !e || e.type !== "Literal" || typeof e.value !== "string")) {
|
|
6285
|
+
throw new Error("dependsOn must take an array of string literals");
|
|
4756
6286
|
}
|
|
6287
|
+
meta[propertyKey] = property.value.elements.map((e) => e.value);
|
|
4757
6288
|
}
|
|
4758
6289
|
}
|
|
4759
|
-
return
|
|
4760
|
-
}
|
|
4761
|
-
|
|
4762
|
-
const stringTypes = ["Literal", "TemplateLiteral"];
|
|
4763
|
-
const NUXT_LIB_RE = /node_modules\/(?:nuxt|nuxt3|nuxt-nightly|@nuxt)\//;
|
|
4764
|
-
const SUPPORTED_EXT_RE$1 = /\.(?:m?[jt]sx?|vue)/;
|
|
4765
|
-
const SCRIPT_RE$1 = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i;
|
|
4766
|
-
const NUXT_INJECTED_MARKER = "/* nuxt-injected */";
|
|
4767
|
-
function shouldTransformFile(id, extensions) {
|
|
4768
|
-
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
4769
|
-
return !NUXT_LIB_RE.test(pathname) && (extensions instanceof RegExp ? extensions.test(pathname) : new RegExp(`\\.(${extensions.map((e) => escapeRE(e)).join("|")})$`).test(pathname)) && parseQuery(search).type !== "style" && !parseQuery(search).macro;
|
|
6290
|
+
return meta;
|
|
4770
6291
|
}
|
|
4771
|
-
const
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
defaultExportSources.add(parsedSource.name);
|
|
4780
|
-
functionName = camelCase(parsedSource.name);
|
|
4781
|
-
}
|
|
4782
|
-
if (import.meta.dev) {
|
|
4783
|
-
const sourcesToFunctionMeta2 = namesToSourcesToFunctionMeta.get(functionName);
|
|
4784
|
-
const existingEntry = sourcesToFunctionMeta2?.get(fnSource);
|
|
4785
|
-
if (existingEntry?.source && existingEntry.source === fnSource) {
|
|
4786
|
-
logger.warn(`[nuxt:compiler] [keyed-functions] Duplicate function name \`${functionName}\`${functionName !== f.name ? ` defined as \`${f.name}\`` : ""} with ${f.source ? `the same source \`${f.source}\`` : "no source"} found. Overwriting the existing entry.`);
|
|
6292
|
+
const RemovePluginMetadataPlugin = (nuxt) => createUnplugin(() => {
|
|
6293
|
+
return {
|
|
6294
|
+
name: "nuxt:remove-plugin-metadata",
|
|
6295
|
+
transform(code, id) {
|
|
6296
|
+
id = normalize(id);
|
|
6297
|
+
const plugin = nuxt.apps.default?.plugins.find((p) => p.src === id);
|
|
6298
|
+
if (!plugin) {
|
|
6299
|
+
return;
|
|
4787
6300
|
}
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
if (f.source && typeof f.source === "string") {
|
|
4804
|
-
sources.add(f.source);
|
|
6301
|
+
if (!code.trim()) {
|
|
6302
|
+
logger.warn(`Plugin \`${plugin.src}\` has no content.`);
|
|
6303
|
+
return {
|
|
6304
|
+
code: "export default () => {}",
|
|
6305
|
+
map: null
|
|
6306
|
+
};
|
|
6307
|
+
}
|
|
6308
|
+
const exports$1 = findExports(code);
|
|
6309
|
+
const defaultExport = exports$1.find((e) => e.type === "default" || e.name === "default");
|
|
6310
|
+
if (!defaultExport) {
|
|
6311
|
+
logger.warn(`Plugin \`${plugin.src}\` has no default export and will be ignored at build time. Add \`export default defineNuxtPlugin(() => {})\` to your plugin.`);
|
|
6312
|
+
return {
|
|
6313
|
+
code: "export default () => {}",
|
|
6314
|
+
map: null
|
|
6315
|
+
};
|
|
4805
6316
|
}
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
transform: {
|
|
4814
|
-
filter: {
|
|
4815
|
-
code: { include: CODE_INCLUDE_RE }
|
|
4816
|
-
},
|
|
4817
|
-
async handler(code, _id) {
|
|
4818
|
-
const { 0: script = code, index: codeIndex = 0 } = code.match(SCRIPT_RE$1) || { 0: code, index: 0 };
|
|
4819
|
-
const id = stripExtension(_id);
|
|
4820
|
-
const { directImports, namespaces } = processImports(findStaticImports(script).map((i) => parseStaticImport(i)));
|
|
4821
|
-
const shouldConsiderExports = sources.has(id);
|
|
4822
|
-
const localNamesToExportedName = /* @__PURE__ */ new Map();
|
|
4823
|
-
const possibleLocalFunctionNames = new Set(namesToSourcesToFunctionMeta.keys());
|
|
4824
|
-
for (const [localName, directImport] of directImports) {
|
|
4825
|
-
const functionName = directImport.originalName === "default" ? camelCase(parse$1(directImport.source).name) : directImport.originalName;
|
|
4826
|
-
if (namesToSourcesToFunctionMeta.has(functionName)) {
|
|
4827
|
-
possibleLocalFunctionNames.add(localName);
|
|
4828
|
-
}
|
|
4829
|
-
}
|
|
4830
|
-
const autoImports = await options.getAutoImports();
|
|
4831
|
-
const autoImportsToSources = new Map(autoImports.map((i) => [i.as || i.name, i.from]));
|
|
4832
|
-
function getFunctionMetaByLocalName(localName, source) {
|
|
4833
|
-
if (!localName) {
|
|
4834
|
-
return;
|
|
4835
|
-
}
|
|
4836
|
-
const exportedName = localNamesToExportedName.get(localName);
|
|
4837
|
-
if (exportedName) {
|
|
4838
|
-
return namesToSourcesToFunctionMeta.get(exportedName)?.get(source);
|
|
4839
|
-
}
|
|
4840
|
-
const directImport = directImports.get(localName);
|
|
4841
|
-
if (directImport) {
|
|
4842
|
-
const functionName = directImport.originalName === "default" ? camelCase(parse$1(directImport.source).name) : directImport.originalName;
|
|
4843
|
-
const sourcesToMetas = namesToSourcesToFunctionMeta.get(functionName);
|
|
4844
|
-
if (!sourcesToMetas) {
|
|
4845
|
-
return;
|
|
4846
|
-
}
|
|
4847
|
-
const fnMeta = sourcesToMetas.get(source);
|
|
4848
|
-
if (fnMeta) {
|
|
4849
|
-
return fnMeta;
|
|
4850
|
-
}
|
|
4851
|
-
const backwardsCompatibleFnMeta = sourcesToMetas.get("");
|
|
4852
|
-
if (backwardsCompatibleFnMeta?.source === void 0) {
|
|
4853
|
-
const autoImportResolvedSource = stripExtension(resolveAlias$1(autoImportsToSources.get(localName) ?? ""));
|
|
4854
|
-
if (autoImportResolvedSource === source) {
|
|
4855
|
-
return backwardsCompatibleFnMeta;
|
|
4856
|
-
}
|
|
4857
|
-
} else if (backwardsCompatibleFnMeta.source instanceof RegExp && backwardsCompatibleFnMeta.source.test(source)) {
|
|
4858
|
-
return backwardsCompatibleFnMeta;
|
|
4859
|
-
}
|
|
4860
|
-
return;
|
|
4861
|
-
}
|
|
4862
|
-
return namesToSourcesToFunctionMeta.get(localName)?.get(source);
|
|
4863
|
-
}
|
|
4864
|
-
function _resolvePath(path) {
|
|
4865
|
-
let p = path;
|
|
4866
|
-
if (isAbsolute(p)) {
|
|
4867
|
-
return p;
|
|
4868
|
-
}
|
|
4869
|
-
p = resolveAlias$1(p, options.alias);
|
|
4870
|
-
if (isAbsolute(p)) {
|
|
4871
|
-
return p;
|
|
4872
|
-
}
|
|
4873
|
-
return join(parse$1(id).dir, p);
|
|
4874
|
-
}
|
|
4875
|
-
const s = new MagicString(code);
|
|
4876
|
-
let count = 0;
|
|
4877
|
-
const scopeTracker = new ScopeTracker({
|
|
4878
|
-
preserveExitedScopes: true
|
|
4879
|
-
});
|
|
4880
|
-
const { program } = parseAndWalk(code, _id, {
|
|
4881
|
-
scopeTracker,
|
|
4882
|
-
enter(node) {
|
|
4883
|
-
if (!shouldConsiderExports) {
|
|
4884
|
-
return;
|
|
4885
|
-
}
|
|
4886
|
-
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") {
|
|
4887
|
-
return;
|
|
4888
|
-
}
|
|
4889
|
-
const result = parseStaticExportIdentifiers(node);
|
|
4890
|
-
for (const exportMeta of result) {
|
|
4891
|
-
const { localName, exportedName } = exportMeta;
|
|
4892
|
-
const functionName = exportedName === "default" ? camelCase(parse$1(id).name) : getFunctionMetaByLocalName(exportedName, id)?.name;
|
|
4893
|
-
if (!functionName) {
|
|
4894
|
-
continue;
|
|
4895
|
-
}
|
|
4896
|
-
localNamesToExportedName.set(localName, functionName);
|
|
4897
|
-
}
|
|
4898
|
-
}
|
|
4899
|
-
});
|
|
4900
|
-
scopeTracker.freeze();
|
|
4901
|
-
for (const localName of localNamesToExportedName.keys()) {
|
|
4902
|
-
possibleLocalFunctionNames.add(localName);
|
|
4903
|
-
}
|
|
4904
|
-
const LOCAL_FUNCTION_NAMES_RE = new RegExp(`\\b(${[...possibleLocalFunctionNames].map((f) => escapeRE(f)).join("|")})\\b`);
|
|
4905
|
-
function processKeyedFunction(walkContext, node, handler) {
|
|
4906
|
-
if (node.type !== "CallExpression" && node.type !== "ChainExpression") {
|
|
4907
|
-
return;
|
|
4908
|
-
}
|
|
4909
|
-
const parsedCall = parseStaticFunctionCall(node, LOCAL_FUNCTION_NAMES_RE);
|
|
4910
|
-
if (!parsedCall) {
|
|
4911
|
-
return;
|
|
4912
|
-
}
|
|
4913
|
-
const functionScopeTrackerNode = scopeTracker.getDeclaration(!parsedCall.namespace ? parsedCall.name : parsedCall.namespace);
|
|
4914
|
-
function isKeyedFunctionImport(node2) {
|
|
4915
|
-
return node2?.type === "Import" && node2.importNode.importKind !== "type";
|
|
4916
|
-
}
|
|
4917
|
-
let importSourceResolved;
|
|
4918
|
-
if (localNamesToExportedName.has(parsedCall.name) && functionScopeTrackerNode?.scope === "") {
|
|
4919
|
-
importSourceResolved = id;
|
|
4920
|
-
} else if (isKeyedFunctionImport(functionScopeTrackerNode)) {
|
|
4921
|
-
importSourceResolved = stripExtension(_resolvePath(functionScopeTrackerNode.importNode.source.value));
|
|
6317
|
+
const s = new MagicString(code);
|
|
6318
|
+
let wrapped = false;
|
|
6319
|
+
const wrapperNames = /* @__PURE__ */ new Set(["defineNuxtPlugin", "definePayloadPlugin"]);
|
|
6320
|
+
try {
|
|
6321
|
+
parseAndWalk(code, id, (node) => {
|
|
6322
|
+
if (node.type === "ImportSpecifier" && node.imported.type === "Identifier" && (node.imported.name === "defineNuxtPlugin" || node.imported.name === "definePayloadPlugin")) {
|
|
6323
|
+
wrapperNames.add(node.local.name);
|
|
4922
6324
|
}
|
|
4923
|
-
if (
|
|
4924
|
-
walkContext.skip();
|
|
6325
|
+
if (node.type !== "CallExpression" || node.callee.type !== "Identifier") {
|
|
4925
6326
|
return;
|
|
4926
6327
|
}
|
|
4927
|
-
const
|
|
4928
|
-
if (!
|
|
4929
|
-
walkContext.skip();
|
|
6328
|
+
const name = "name" in node.callee && node.callee.name;
|
|
6329
|
+
if (!name || !wrapperNames.has(name)) {
|
|
4930
6330
|
return;
|
|
4931
6331
|
}
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
walkContext.skip();
|
|
4935
|
-
return;
|
|
4936
|
-
}
|
|
4937
|
-
if (
|
|
4938
|
-
// the function is imported
|
|
4939
|
-
isKeyedFunctionImport(functionScopeTrackerNode) && // import { useKeyed } from '...'
|
|
4940
|
-
(functionScopeTrackerNode.node.type === "ImportSpecifier" && functionScopeTrackerNode.node.importKind !== "type" || functionScopeTrackerNode.node.type === "ImportDefaultSpecifier" && fnMeta.name === "default") && // the function is imported from the correct source when `source` is specified
|
|
4941
|
-
(typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === importSourceResolved || !fnMeta.source && stripExtension(_resolvePath(autoImportsToSources.get(parsedCall.name) ?? "")) === importSourceResolved || fnMeta.source instanceof RegExp && fnMeta.source.test(importSourceResolved)) || localNamesToExportedName.has(parsedCall.name) && functionScopeTrackerNode?.scope === ""
|
|
4942
|
-
) {
|
|
4943
|
-
handler({ parsedCall, fnMeta });
|
|
4944
|
-
}
|
|
4945
|
-
walkContext.skip();
|
|
6332
|
+
wrapped = true;
|
|
6333
|
+
if (!("order" in plugin) && !("name" in plugin)) {
|
|
4946
6334
|
return;
|
|
4947
6335
|
}
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
if (namespacedImportMeta && namespacedImportMeta.namespaces.has(parsedCall.namespace) && namespaceScopeTrackerNode?.type === "Import" && namespaceScopeTrackerNode.node.type === "ImportNamespaceSpecifier") {
|
|
4952
|
-
handler({ parsedCall, fnMeta });
|
|
6336
|
+
for (const [argIndex, arg] of node.arguments.entries()) {
|
|
6337
|
+
if (arg.type !== "ObjectExpression") {
|
|
6338
|
+
continue;
|
|
4953
6339
|
}
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
}
|
|
4958
|
-
walk(program, {
|
|
4959
|
-
scopeTracker,
|
|
4960
|
-
enter(node) {
|
|
4961
|
-
processKeyedFunction(this, node, ({ parsedCall, fnMeta }) => {
|
|
4962
|
-
const lastArgument = parsedCall.callExpression.arguments[parsedCall.callExpression.arguments.length - 1];
|
|
4963
|
-
if (lastArgument?.type === "Literal" && typeof lastArgument.value === "string" && lastArgument.end + NUXT_INJECTED_MARKER.length + 1 < parsedCall.callExpression.end) {
|
|
4964
|
-
let wasKeyInjected = true;
|
|
4965
|
-
for (let i2 = 0; i2 < NUXT_INJECTED_MARKER.length; i2++) {
|
|
4966
|
-
if (code[codeIndex + lastArgument.end + 1 + i2] !== NUXT_INJECTED_MARKER[i2]) {
|
|
4967
|
-
wasKeyInjected = false;
|
|
4968
|
-
break;
|
|
4969
|
-
}
|
|
4970
|
-
}
|
|
4971
|
-
if (wasKeyInjected) {
|
|
4972
|
-
return;
|
|
4973
|
-
}
|
|
4974
|
-
}
|
|
4975
|
-
switch (parsedCall.name) {
|
|
4976
|
-
case "useState":
|
|
4977
|
-
if (stringTypes.includes(parsedCall.callExpression.arguments[0]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/state", options.alias))) {
|
|
4978
|
-
return;
|
|
4979
|
-
}
|
|
4980
|
-
break;
|
|
4981
|
-
case "useFetch":
|
|
4982
|
-
case "useLazyFetch":
|
|
4983
|
-
if (stringTypes.includes(parsedCall.callExpression.arguments[1]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/fetch", options.alias))) {
|
|
4984
|
-
return;
|
|
4985
|
-
}
|
|
4986
|
-
break;
|
|
4987
|
-
case "useAsyncData":
|
|
4988
|
-
case "useLazyAsyncData":
|
|
4989
|
-
if (stringTypes.includes(parsedCall.callExpression.arguments[0]?.type) && typeof fnMeta.source === "string" && stripExtension(fnMeta.source) === stripExtension(resolveAlias$1("#app/composables/asyncData", options.alias))) {
|
|
4990
|
-
return;
|
|
4991
|
-
}
|
|
4992
|
-
break;
|
|
6340
|
+
for (const [propertyIndex, property] of arg.properties.entries()) {
|
|
6341
|
+
if (property.type === "SpreadElement" || !("name" in property.key)) {
|
|
6342
|
+
continue;
|
|
4993
6343
|
}
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
6344
|
+
const propertyKey = property.key.name;
|
|
6345
|
+
if (propertyKey === "order" || propertyKey === "enforce" || propertyKey === "name") {
|
|
6346
|
+
const nextNode = arg.properties[propertyIndex + 1] || node.arguments[argIndex + 1];
|
|
6347
|
+
const nextIndex = nextNode?.start || arg.end - 1;
|
|
6348
|
+
s.remove(property.start, nextIndex);
|
|
4997
6349
|
}
|
|
4998
|
-
|
|
4999
|
-
s.appendLeft(
|
|
5000
|
-
codeIndex + parsedCall.callExpression.end - 1,
|
|
5001
|
-
(parsedCall.callExpression.arguments.length && !endsWithComma ? ", " : "") + "'$" + hash(`${_id}-${++count}`).slice(0, 10) + `' ${NUXT_INJECTED_MARKER}`
|
|
5002
|
-
);
|
|
5003
|
-
});
|
|
6350
|
+
}
|
|
5004
6351
|
}
|
|
5005
6352
|
});
|
|
6353
|
+
} catch (e) {
|
|
6354
|
+
logger.error(e);
|
|
6355
|
+
return;
|
|
6356
|
+
}
|
|
6357
|
+
if (!wrapped) {
|
|
6358
|
+
logger.warn(`Plugin \`${plugin.src}\` is not wrapped in \`defineNuxtPlugin\`. It is advised to wrap your plugins as in the future this may enable enhancements.`);
|
|
6359
|
+
}
|
|
6360
|
+
if (s.hasChanged()) {
|
|
6361
|
+
return {
|
|
6362
|
+
code: s.toString(),
|
|
6363
|
+
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : null
|
|
6364
|
+
};
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
};
|
|
6368
|
+
});
|
|
6369
|
+
|
|
6370
|
+
const AsyncContextInjectionPlugin = (nuxt) => createUnplugin(() => {
|
|
6371
|
+
return {
|
|
6372
|
+
name: "nuxt:vue-async-context",
|
|
6373
|
+
transformInclude(id) {
|
|
6374
|
+
return isVue(id, { type: ["template", "script"] });
|
|
6375
|
+
},
|
|
6376
|
+
transform: {
|
|
6377
|
+
filter: {
|
|
6378
|
+
code: { include: /_withAsyncContext/ }
|
|
6379
|
+
},
|
|
6380
|
+
handler(code) {
|
|
6381
|
+
const s = new MagicString(code);
|
|
6382
|
+
s.prepend('import { withAsyncContext as _withAsyncContext } from "#app/composables/asyncContext";\n');
|
|
6383
|
+
s.replace(/withAsyncContext as _withAsyncContext,?/, "");
|
|
5006
6384
|
if (s.hasChanged()) {
|
|
5007
6385
|
return {
|
|
5008
6386
|
code: s.toString(),
|
|
5009
|
-
map: options.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
6387
|
+
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server ? s.generateMap({ hires: true }) : void 0
|
|
5010
6388
|
};
|
|
5011
6389
|
}
|
|
5012
6390
|
}
|
|
@@ -5071,8 +6449,10 @@ function PrehydrateTransformPlugin(options = {}) {
|
|
|
5071
6449
|
|
|
5072
6450
|
const functionsToExtract = /* @__PURE__ */ new Set(["useAsyncData", "useLazyAsyncData"]);
|
|
5073
6451
|
const FUNCTIONS_RE = /\buse(?:Lazy)?AsyncData\b/;
|
|
5074
|
-
const SUPPORTED_EXT_RE =
|
|
6452
|
+
const SUPPORTED_EXT_RE = /^[^?]*\.(?:m?[jt]sx?|vue)(?:$|\?)/;
|
|
5075
6453
|
const SCRIPT_RE = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i;
|
|
6454
|
+
const STYLE_QUERY_RE = /[?&]type=style/;
|
|
6455
|
+
const MACRO_QUERY_RE = /[?&]macro(?:=|&|$)/;
|
|
5076
6456
|
const ExtractAsyncDataHandlersPlugin = (options) => createUnplugin(() => {
|
|
5077
6457
|
const asyncDatas = {};
|
|
5078
6458
|
let count = 0;
|
|
@@ -5089,14 +6469,11 @@ const ExtractAsyncDataHandlersPlugin = (options) => createUnplugin(() => {
|
|
|
5089
6469
|
return asyncDatas[id];
|
|
5090
6470
|
}
|
|
5091
6471
|
},
|
|
5092
|
-
transformInclude(id) {
|
|
5093
|
-
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
|
|
5094
|
-
return SUPPORTED_EXT_RE.test(pathname) && parseQuery(search).type !== "style" && !parseQuery(search).macro;
|
|
5095
|
-
},
|
|
5096
6472
|
transform: {
|
|
5097
6473
|
filter: {
|
|
5098
6474
|
id: {
|
|
5099
|
-
|
|
6475
|
+
include: SUPPORTED_EXT_RE,
|
|
6476
|
+
exclude: [/nuxt\/(src|dist)\/app/, STYLE_QUERY_RE, MACRO_QUERY_RE]
|
|
5100
6477
|
},
|
|
5101
6478
|
code: { include: FUNCTIONS_RE }
|
|
5102
6479
|
},
|
|
@@ -5310,8 +6687,13 @@ function escapeDirectory(path) {
|
|
|
5310
6687
|
function createNuxt(options) {
|
|
5311
6688
|
const hooks = createHooks();
|
|
5312
6689
|
const { callHook, callHookParallel, callHookWith } = hooks;
|
|
5313
|
-
|
|
5314
|
-
|
|
6690
|
+
if (options.experimental.asyncCallHook) {
|
|
6691
|
+
hooks.callHook = (...args) => Promise.resolve().then(() => runWithNuxtContext(nuxt, () => callHook(...args)));
|
|
6692
|
+
hooks.callHookParallel = (...args) => Promise.resolve().then(() => runWithNuxtContext(nuxt, () => callHookParallel(...args)) ?? []);
|
|
6693
|
+
} else {
|
|
6694
|
+
hooks.callHook = (...args) => runWithNuxtContext(nuxt, () => callHook(...args));
|
|
6695
|
+
hooks.callHookParallel = (...args) => runWithNuxtContext(nuxt, () => callHookParallel(...args));
|
|
6696
|
+
}
|
|
5315
6697
|
hooks.callHookWith = (...args) => runWithNuxtContext(nuxt, () => callHookWith(...args));
|
|
5316
6698
|
const nuxt = {
|
|
5317
6699
|
__name: randomUUID(),
|
|
@@ -5322,7 +6704,9 @@ function createNuxt(options) {
|
|
|
5322
6704
|
addHooks: hooks.addHooks,
|
|
5323
6705
|
hook: hooks.hook,
|
|
5324
6706
|
ready: () => runWithNuxtContext(nuxt, () => initNuxt(nuxt)),
|
|
5325
|
-
close: () =>
|
|
6707
|
+
close: async () => {
|
|
6708
|
+
await hooks.callHook("close", nuxt);
|
|
6709
|
+
},
|
|
5326
6710
|
vfs: {},
|
|
5327
6711
|
apps: {},
|
|
5328
6712
|
runWithContext: (fn) => runWithNuxtContext(nuxt, fn),
|
|
@@ -5391,6 +6775,7 @@ const nightlies = {
|
|
|
5391
6775
|
};
|
|
5392
6776
|
let warnedAboutCompatDate = false;
|
|
5393
6777
|
async function initNuxt(nuxt) {
|
|
6778
|
+
nuxt._perf?.startPhase("init");
|
|
5394
6779
|
const layerDirs = getLayerDirectories(nuxt);
|
|
5395
6780
|
for (const config of nuxt.options._layers.map((layer) => layer.config).reverse()) {
|
|
5396
6781
|
if (config.hooks) {
|
|
@@ -5473,7 +6858,7 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5473
6858
|
tsConfig: { compilerOptions: { paths: { ...paths } } }
|
|
5474
6859
|
});
|
|
5475
6860
|
});
|
|
5476
|
-
const
|
|
6861
|
+
const serverBuilderReference = typeof nuxt.options.server.builder === "string" ? nuxt.options.server.builder === "@nuxt/nitro-server" ? { path: resolveModulePath(nuxt.options.server.builder, { from: import.meta.url }).replace(".mjs", ".d.mts") } : { types: nuxt.options.server.builder } : void 0;
|
|
5477
6862
|
nuxt.hook("prepare:types", async (opts) => {
|
|
5478
6863
|
opts.references.push({ path: resolve(nuxt.options.buildDir, "types/plugins.d.ts") });
|
|
5479
6864
|
if (nuxt.options.typescript.shim) {
|
|
@@ -5487,13 +6872,13 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5487
6872
|
opts.nodeReferences.push({ path: resolve(nuxt.options.buildDir, "types/runtime-config.d.ts") });
|
|
5488
6873
|
opts.nodeReferences.push({ path: resolve(nuxt.options.buildDir, "types/app.config.d.ts") });
|
|
5489
6874
|
opts.nodeReferences.push({ types: "nuxt" });
|
|
5490
|
-
opts.nodeReferences.push({
|
|
6875
|
+
opts.nodeReferences.push({ path: resolveModulePath("@nuxt/vite-builder", { from: import.meta.url }).replace(".mjs", ".d.mts") });
|
|
5491
6876
|
if (typeof nuxt.options.builder === "string" && nuxt.options.builder !== "@nuxt/vite-builder") {
|
|
5492
6877
|
opts.nodeReferences.push({ types: nuxt.options.builder });
|
|
5493
6878
|
}
|
|
5494
|
-
if (
|
|
5495
|
-
opts.references.push(
|
|
5496
|
-
opts.nodeReferences.push(
|
|
6879
|
+
if (serverBuilderReference) {
|
|
6880
|
+
opts.references.push(serverBuilderReference);
|
|
6881
|
+
opts.nodeReferences.push(serverBuilderReference);
|
|
5497
6882
|
}
|
|
5498
6883
|
opts.sharedReferences.push({ path: resolve(nuxt.options.buildDir, "types/runtime-config.d.ts") });
|
|
5499
6884
|
opts.sharedReferences.push({ path: resolve(nuxt.options.buildDir, "types/app.config.d.ts") });
|
|
@@ -5514,8 +6899,8 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5514
6899
|
nuxt.hook("nitro:prepare:types", (opts) => {
|
|
5515
6900
|
opts.references.push({ path: resolve(nuxt.options.buildDir, "types/app.config.d.ts") });
|
|
5516
6901
|
opts.references.push({ path: resolve(nuxt.options.buildDir, "types/runtime-config.d.ts") });
|
|
5517
|
-
if (
|
|
5518
|
-
opts.references.push(
|
|
6902
|
+
if (serverBuilderReference) {
|
|
6903
|
+
opts.references.push(serverBuilderReference);
|
|
5519
6904
|
}
|
|
5520
6905
|
});
|
|
5521
6906
|
if (nuxt.options.scripts) {
|
|
@@ -5563,31 +6948,48 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5563
6948
|
composables: nuxt.options.optimization.treeShake.composables.client
|
|
5564
6949
|
}), { server: false });
|
|
5565
6950
|
}
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
6951
|
+
if (!nuxt.options.test) {
|
|
6952
|
+
const sharedDir = withTrailingSlash(resolve(nuxt.options.rootDir, nuxt.options.dir.shared));
|
|
6953
|
+
const relativeSharedDir = withTrailingSlash(relative(nuxt.options.rootDir, resolve(nuxt.options.rootDir, nuxt.options.dir.shared)));
|
|
6954
|
+
const sharedPatterns = [/^#shared\//, new RegExp("^" + escapeRE(sharedDir)), new RegExp("^" + escapeRE(relativeSharedDir))];
|
|
6955
|
+
const sharedProtectionConfig = {
|
|
6956
|
+
cwd: nuxt.options.rootDir,
|
|
6957
|
+
trace: true,
|
|
6958
|
+
include: sharedPatterns,
|
|
6959
|
+
patterns: createImportProtectionPatterns(nuxt, { context: "shared" })
|
|
6960
|
+
};
|
|
6961
|
+
addBuildPlugin({
|
|
6962
|
+
vite: () => ImpoundPlugin.vite(sharedProtectionConfig),
|
|
6963
|
+
webpack: () => ImpoundPlugin.webpack(sharedProtectionConfig),
|
|
6964
|
+
rspack: () => ImpoundPlugin.rspack(sharedProtectionConfig)
|
|
6965
|
+
}, { server: false, prepend: true });
|
|
6966
|
+
const nuxtProtectionConfig = {
|
|
6967
|
+
cwd: nuxt.options.rootDir,
|
|
6968
|
+
trace: true,
|
|
6969
|
+
// Exclude top-level resolutions by plugins
|
|
6970
|
+
exclude: [relative(nuxt.options.rootDir, join(nuxt.options.srcDir, "index.html")), ...sharedPatterns],
|
|
6971
|
+
patterns: createImportProtectionPatterns(nuxt, { context: "nuxt-app" })
|
|
6972
|
+
};
|
|
6973
|
+
addBuildPlugin({
|
|
6974
|
+
webpack: () => ImpoundPlugin.webpack(nuxtProtectionConfig),
|
|
6975
|
+
rspack: () => ImpoundPlugin.rspack(nuxtProtectionConfig)
|
|
6976
|
+
});
|
|
6977
|
+
for (const envOptions of [
|
|
6978
|
+
{ client: false },
|
|
6979
|
+
{ server: false }
|
|
6980
|
+
]) {
|
|
6981
|
+
const error = envOptions.client === false ? false : true;
|
|
6982
|
+
const vitePlugins = [ImpoundPlugin.vite({ ...nuxtProtectionConfig, error, ...error === false && { warn: "once" } })].flat().map((p) => Object.assign(p, { name: `nuxt:import-protection:${p.name}` }));
|
|
6983
|
+
const mainPlugins = vitePlugins.filter((p) => !p.name.includes("trace"));
|
|
6984
|
+
const tracePlugins = vitePlugins.filter((p) => p.name.includes("trace"));
|
|
6985
|
+
if (mainPlugins.length) {
|
|
6986
|
+
addVitePlugin(() => mainPlugins, { ...envOptions, prepend: true });
|
|
6987
|
+
}
|
|
6988
|
+
if (tracePlugins.length) {
|
|
6989
|
+
addVitePlugin(() => tracePlugins, envOptions);
|
|
6990
|
+
}
|
|
6991
|
+
}
|
|
6992
|
+
}
|
|
5591
6993
|
});
|
|
5592
6994
|
if (!nuxt.options.dev) {
|
|
5593
6995
|
addBuildPlugin(DevOnlyPlugin({
|
|
@@ -5633,6 +7035,8 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5633
7035
|
nuxt.options.modulesDir.push(join(dirs.root, "node_modules"));
|
|
5634
7036
|
}
|
|
5635
7037
|
}
|
|
7038
|
+
nuxt._perf?.endPhase("init");
|
|
7039
|
+
nuxt._perf?.startPhase("modules");
|
|
5636
7040
|
await nuxt.callHook("modules:before");
|
|
5637
7041
|
const { paths: watchedModulePaths, resolvedModulePaths, modules } = await resolveModules(nuxt);
|
|
5638
7042
|
nuxt.options.watch.push(...watchedModulePaths);
|
|
@@ -5700,6 +7104,13 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5700
7104
|
filePath: resolve(nuxt.options.appDir, "components/nuxt-route-announcer"),
|
|
5701
7105
|
mode: "client"
|
|
5702
7106
|
});
|
|
7107
|
+
addComponent({
|
|
7108
|
+
name: "NuxtAnnouncer",
|
|
7109
|
+
priority: 10,
|
|
7110
|
+
// built-in that we do not expect the user to override
|
|
7111
|
+
filePath: resolve(nuxt.options.appDir, "components/nuxt-announcer"),
|
|
7112
|
+
mode: "client"
|
|
7113
|
+
});
|
|
5703
7114
|
if (nuxt.options.experimental.clientFallback) {
|
|
5704
7115
|
addComponent({
|
|
5705
7116
|
name: "NuxtClientFallback",
|
|
@@ -5740,21 +7151,9 @@ Using \`${fallbackCompatibilityDate}\` as fallback. More info at: ${colors.under
|
|
|
5740
7151
|
await installModules(modules, resolvedModulePaths, nuxt);
|
|
5741
7152
|
nuxt._ignore = ignore(nuxt.options.ignoreOptions);
|
|
5742
7153
|
nuxt._ignore.add(resolveIgnorePatterns());
|
|
5743
|
-
let unimport;
|
|
5744
|
-
nuxt.hook("imports:context", (ctx) => {
|
|
5745
|
-
unimport = ctx;
|
|
5746
|
-
});
|
|
5747
7154
|
await nuxt.callHook("modules:done");
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
source: typeof source === "string" ? await resolvePath(source, { fallbackToOriginal: true }) ?? source : source
|
|
5751
|
-
})));
|
|
5752
|
-
addBuildPlugin(KeyedFunctionsPlugin({
|
|
5753
|
-
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client,
|
|
5754
|
-
keyedFunctions: normalizedKeyedFunctions,
|
|
5755
|
-
alias: nuxt.options.alias,
|
|
5756
|
-
getAutoImports: unimport.getImports
|
|
5757
|
-
}));
|
|
7155
|
+
nuxt._perf?.endPhase("modules");
|
|
7156
|
+
nuxt._perf?.collectModuleTimings(nuxt.options._installedModules);
|
|
5758
7157
|
nuxt.options.css = nuxt.options.css.filter((value, index, array) => !array.includes(value, index + 1));
|
|
5759
7158
|
if (nuxt.options.experimental.componentIslands) {
|
|
5760
7159
|
addComponent({
|
|
@@ -5849,6 +7248,7 @@ export default defineNuxtPlugin({
|
|
|
5849
7248
|
});
|
|
5850
7249
|
addModuleTranspiles(nuxt);
|
|
5851
7250
|
await bundleServer(nuxt);
|
|
7251
|
+
nuxt._perf?.startPhase("ready");
|
|
5852
7252
|
if (nuxt.options.experimental.payloadExtraction) {
|
|
5853
7253
|
addPlugin(resolve(nuxt.options.appDir, "plugins/payload.client"));
|
|
5854
7254
|
}
|
|
@@ -5856,9 +7256,21 @@ export default defineNuxtPlugin({
|
|
|
5856
7256
|
logger.info(`Running with compatibility version \`${nuxt.options.future.compatibilityVersion}\``);
|
|
5857
7257
|
}
|
|
5858
7258
|
await nuxt.callHook("ready", nuxt);
|
|
7259
|
+
nuxt._perf?.endPhase("ready");
|
|
5859
7260
|
}
|
|
5860
7261
|
async function loadNuxt(opts) {
|
|
7262
|
+
let perf;
|
|
7263
|
+
const cliStartTime = globalThis.__nuxt_cli__?.startTime;
|
|
7264
|
+
const perfOverride = typeof opts.overrides?.debug === "object" && opts.overrides.debug.perf;
|
|
7265
|
+
if (perfOverride) {
|
|
7266
|
+
perf = new NuxtPerfProfiler({ startTime: cliStartTime });
|
|
7267
|
+
perf.startPhase("config");
|
|
7268
|
+
}
|
|
5861
7269
|
const options = await loadNuxtConfig(opts);
|
|
7270
|
+
if (!perf && typeof options.debug === "object" && options.debug.perf) {
|
|
7271
|
+
perf = new NuxtPerfProfiler({ startTime: cliStartTime });
|
|
7272
|
+
}
|
|
7273
|
+
perf?.endPhase("config");
|
|
5862
7274
|
options.appDir = options.alias["#app"] = withTrailingSlash(resolve(distDir, "app"));
|
|
5863
7275
|
options._majorVersion = 4;
|
|
5864
7276
|
for (const key in options.app.head || {}) {
|
|
@@ -5886,6 +7298,7 @@ async function loadNuxt(opts) {
|
|
|
5886
7298
|
}
|
|
5887
7299
|
}
|
|
5888
7300
|
options._modules.push(pagesModule, metaModule, componentsModule);
|
|
7301
|
+
options._modules.push(compilerModule);
|
|
5889
7302
|
const importIncludes = [];
|
|
5890
7303
|
for (const layer of options._layers) {
|
|
5891
7304
|
if (layer.cwd && layer.cwd.includes("node_modules")) {
|
|
@@ -5934,6 +7347,29 @@ async function loadNuxt(opts) {
|
|
|
5934
7347
|
}
|
|
5935
7348
|
});
|
|
5936
7349
|
const nuxt = createNuxt(options);
|
|
7350
|
+
if (perf) {
|
|
7351
|
+
nuxt._perf = perf;
|
|
7352
|
+
perf.installHookInterceptors(nuxt.hooks);
|
|
7353
|
+
const quiet = typeof options.debug === "object" && options.debug.perf === "quiet";
|
|
7354
|
+
const title = nuxt.options.dev ? "Nuxt Performance Report" : "Nuxt Build Performance";
|
|
7355
|
+
let flushed = false;
|
|
7356
|
+
const flush = () => {
|
|
7357
|
+
if (flushed || !perf) {
|
|
7358
|
+
return;
|
|
7359
|
+
}
|
|
7360
|
+
flushed = true;
|
|
7361
|
+
if (!quiet) {
|
|
7362
|
+
perf.printReport({ title });
|
|
7363
|
+
}
|
|
7364
|
+
perf.writeReport(nuxt.options.buildDir, { quiet });
|
|
7365
|
+
perf.dispose();
|
|
7366
|
+
};
|
|
7367
|
+
nuxt.hook("close", flush);
|
|
7368
|
+
process.once("exit", flush);
|
|
7369
|
+
nuxt.hook("close", () => {
|
|
7370
|
+
process.off("exit", flush);
|
|
7371
|
+
});
|
|
7372
|
+
}
|
|
5937
7373
|
nuxt.runWithContext(() => {
|
|
5938
7374
|
if (opts.overrides?.hooks) {
|
|
5939
7375
|
nuxt.hooks.addHooks(opts.overrides.hooks);
|
|
@@ -5942,6 +7378,9 @@ async function loadNuxt(opts) {
|
|
|
5942
7378
|
createDebugger(nuxt.hooks, { tag: "nuxt" });
|
|
5943
7379
|
}
|
|
5944
7380
|
});
|
|
7381
|
+
if (!nuxt.options._prepare && !nuxt.options.dev && nuxt.options.experimental.buildCache) {
|
|
7382
|
+
nuxt.hooks.hookOnce("modules:before", () => restoreCachedBuildId(nuxt));
|
|
7383
|
+
}
|
|
5945
7384
|
if (opts.ready !== false) {
|
|
5946
7385
|
await nuxt.ready();
|
|
5947
7386
|
}
|
|
@@ -6510,7 +7949,7 @@ const nuxtConfigTemplate = {
|
|
|
6510
7949
|
const shouldEnableComponentIslands = ctx.nuxt.options.experimental.componentIslands && (ctx.nuxt.options.dev || ctx.nuxt.options.experimental.componentIslands !== "auto" || ctx.app.pages?.some((p) => p.mode === "server") || ctx.app.components?.some((c) => c.mode === "server" && !ctx.app.components.some((other) => other.pascalName === c.pascalName && other.mode === "client")));
|
|
6511
7950
|
const nitro = useNitro();
|
|
6512
7951
|
const hasCachedRoutes = Object.values(nitro.options.routeRules).some((r) => r.isr || r.cache);
|
|
6513
|
-
const payloadExtraction = !!ctx.nuxt.options.experimental.payloadExtraction && (nitro.options.static || hasCachedRoutes || nitro.options.prerender.routes.length > 0 || Object.values(nitro.options.routeRules).some((r) => r.prerender));
|
|
7952
|
+
const payloadExtraction = !!ctx.nuxt.options.experimental.payloadExtraction && (nitro.options.static || hasCachedRoutes || nitro.options.prerender.routes && nitro.options.prerender.routes.length > 0 || Object.values(nitro.options.routeRules).some((r) => r.prerender));
|
|
6514
7953
|
return [
|
|
6515
7954
|
...Object.entries(ctx.nuxt.options.app).map(([k, v]) => `export const ${camelCase("app-" + k)} = ${JSON.stringify(v)}`),
|
|
6516
7955
|
`export const renderJsonPayloads = ${!!ctx.nuxt.options.experimental.renderJsonPayloads}`,
|
|
@@ -6525,6 +7964,7 @@ const nuxtConfigTemplate = {
|
|
|
6525
7964
|
`export const devLogs = ${JSON.stringify(ctx.nuxt.options.features.devLogs)}`,
|
|
6526
7965
|
`export const nuxtLinkDefaults = ${JSON.stringify(ctx.nuxt.options.experimental.defaults.nuxtLink)}`,
|
|
6527
7966
|
`export const asyncDataDefaults = ${JSON.stringify(ctx.nuxt.options.experimental.defaults.useAsyncData)}`,
|
|
7967
|
+
`export const useStateDefaults = ${JSON.stringify(ctx.nuxt.options.experimental.defaults.useState)}`,
|
|
6528
7968
|
`export const fetchDefaults = ${JSON.stringify(fetchDefaults)}`,
|
|
6529
7969
|
`export const vueAppRootContainer = ${ctx.nuxt.options.app.rootAttrs.id ? `'#${ctx.nuxt.options.app.rootAttrs.id}'` : `'body > ${ctx.nuxt.options.app.rootTag}'`}`,
|
|
6530
7970
|
`export const viewTransition = ${ctx.nuxt.options.experimental.viewTransition}`,
|
|
@@ -6537,7 +7977,8 @@ const nuxtConfigTemplate = {
|
|
|
6537
7977
|
`export const purgeCachedData = ${!!ctx.nuxt.options.experimental.purgeCachedData}`,
|
|
6538
7978
|
`export const granularCachedData = ${!!ctx.nuxt.options.experimental.granularCachedData}`,
|
|
6539
7979
|
`export const pendingWhenIdle = ${!!ctx.nuxt.options.experimental.pendingWhenIdle}`,
|
|
6540
|
-
`export const alwaysRunFetchOnKeyChange = ${!!ctx.nuxt.options.experimental.alwaysRunFetchOnKeyChange}
|
|
7980
|
+
`export const alwaysRunFetchOnKeyChange = ${!!ctx.nuxt.options.experimental.alwaysRunFetchOnKeyChange}`,
|
|
7981
|
+
`export const asyncCallHook = ${!!ctx.nuxt.options.experimental.asyncCallHook}`
|
|
6541
7982
|
].join("\n\n");
|
|
6542
7983
|
}
|
|
6543
7984
|
};
|
|
@@ -6647,9 +8088,9 @@ async function generateApp(nuxt, app, options = {}) {
|
|
|
6647
8088
|
changedTemplates.push(template);
|
|
6648
8089
|
}
|
|
6649
8090
|
const perf = performance.now() - start;
|
|
6650
|
-
const
|
|
6651
|
-
if (nuxt.options.debug && nuxt.options.debug.templates ||
|
|
6652
|
-
logger.info(`Compiled \`${template.filename}\` in ${
|
|
8091
|
+
const compileTime = Math.round(perf * 100) / 100;
|
|
8092
|
+
if (nuxt.options.debug && nuxt.options.debug.templates || compileTime > 500) {
|
|
8093
|
+
logger.info(`Compiled \`${template.filename}\` in ${compileTime}ms`);
|
|
6653
8094
|
}
|
|
6654
8095
|
if (template.modified && template.write) {
|
|
6655
8096
|
dirs.add(dirname(fullPath));
|
|
@@ -6773,7 +8214,7 @@ async function annotatePlugins(nuxt, plugins) {
|
|
|
6773
8214
|
const _plugins = [];
|
|
6774
8215
|
for (const plugin of plugins) {
|
|
6775
8216
|
try {
|
|
6776
|
-
const code =
|
|
8217
|
+
const code = nuxt.vfs[plugin.src] ?? await promises.readFile(plugin.src, "utf-8");
|
|
6777
8218
|
_plugins.push({
|
|
6778
8219
|
...await extractMetadata(code, IS_TSX.test(plugin.src) ? "tsx" : "ts"),
|
|
6779
8220
|
...plugin
|
|
@@ -6831,29 +8272,29 @@ ${warningsAsList}`;
|
|
|
6831
8272
|
logger.warn(warning);
|
|
6832
8273
|
}
|
|
6833
8274
|
}
|
|
6834
|
-
|
|
6835
|
-
return
|
|
8275
|
+
function checkViteConfig() {
|
|
8276
|
+
return checkAndWarnAboutConfigFileExistence({
|
|
6836
8277
|
fileName: "vite.config",
|
|
6837
8278
|
extensions: [".js", ".mjs", ".ts", ".cjs", ".mts", ".cts"],
|
|
6838
8279
|
createWarningMessage: (foundFile) => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.vite\` instead. You can read more in \`https://nuxt.com/docs/4.x/api/nuxt-config#vite\`.`
|
|
6839
8280
|
});
|
|
6840
8281
|
}
|
|
6841
|
-
|
|
6842
|
-
return
|
|
8282
|
+
function checkWebpackConfig() {
|
|
8283
|
+
return checkAndWarnAboutConfigFileExistence({
|
|
6843
8284
|
fileName: "webpack.config",
|
|
6844
8285
|
extensions: [".js", ".mjs", ".ts", ".cjs", ".mts", ".cts", "coffee"],
|
|
6845
8286
|
createWarningMessage: (foundFile) => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.webpack\` instead. You can read more in \`https://nuxt.com/docs/4.x/api/nuxt-config#webpack-1\`.`
|
|
6846
8287
|
});
|
|
6847
8288
|
}
|
|
6848
|
-
|
|
6849
|
-
return
|
|
8289
|
+
function checkNitroConfig() {
|
|
8290
|
+
return checkAndWarnAboutConfigFileExistence({
|
|
6850
8291
|
fileName: "nitro.config",
|
|
6851
8292
|
extensions: [".ts", ".mts"],
|
|
6852
8293
|
createWarningMessage: (foundFile) => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.nitro\` instead. You can read more in \`https://nuxt.com/docs/4.x/api/nuxt-config#nitro\`.`
|
|
6853
8294
|
});
|
|
6854
8295
|
}
|
|
6855
|
-
|
|
6856
|
-
return
|
|
8296
|
+
function checkPostCSSConfig() {
|
|
8297
|
+
return checkAndWarnAboutConfigFileExistence({
|
|
6857
8298
|
fileName: "postcss.config",
|
|
6858
8299
|
extensions: [".js", ".cjs"],
|
|
6859
8300
|
createWarningMessage: (foundFile) => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.postcss\` instead. You can read more in \`https://nuxt.com/docs/4.x/api/nuxt-config#postcss\`.`
|
|
@@ -6867,240 +8308,13 @@ async function checkAndWarnAboutConfigFileExistence(options) {
|
|
|
6867
8308
|
}
|
|
6868
8309
|
}
|
|
6869
8310
|
|
|
6870
|
-
async function getVueHash(nuxt) {
|
|
6871
|
-
const id = "vue";
|
|
6872
|
-
const { hash: hash2 } = await getHashes(nuxt, {
|
|
6873
|
-
id,
|
|
6874
|
-
cwd: (layer) => layer.config.srcDir || layer.cwd,
|
|
6875
|
-
patterns: (layer) => {
|
|
6876
|
-
const srcDir = layer.config.srcDir || layer.cwd;
|
|
6877
|
-
return [
|
|
6878
|
-
"**",
|
|
6879
|
-
`!${relative(srcDir, layer.config.serverDir || join(layer.cwd, "server"))}/**`,
|
|
6880
|
-
`!${relative(srcDir, resolve$1(layer.cwd, layer.config.dir?.public || "public"))}/**`,
|
|
6881
|
-
"!node_modules/**",
|
|
6882
|
-
"!nuxt.config.*"
|
|
6883
|
-
];
|
|
6884
|
-
},
|
|
6885
|
-
configOverrides: {
|
|
6886
|
-
buildId: void 0,
|
|
6887
|
-
serverDir: void 0,
|
|
6888
|
-
nitro: void 0,
|
|
6889
|
-
devServer: void 0,
|
|
6890
|
-
runtimeConfig: void 0,
|
|
6891
|
-
logLevel: void 0,
|
|
6892
|
-
devServerHandlers: void 0,
|
|
6893
|
-
devtools: void 0
|
|
6894
|
-
}
|
|
6895
|
-
});
|
|
6896
|
-
const cacheFile = join(getCacheDir(nuxt), id, hash2 + ".tar");
|
|
6897
|
-
return {
|
|
6898
|
-
hash: hash2,
|
|
6899
|
-
async collectCache() {
|
|
6900
|
-
const start = Date.now();
|
|
6901
|
-
await writeCache(nuxt.options.buildDir, nuxt.options.buildDir, cacheFile);
|
|
6902
|
-
const elapsed = Date.now() - start;
|
|
6903
|
-
consola.success(`Cached Vue client and server builds in \`${elapsed}ms\`.`);
|
|
6904
|
-
},
|
|
6905
|
-
async restoreCache() {
|
|
6906
|
-
const start = Date.now();
|
|
6907
|
-
const res = await restoreCache(nuxt.options.buildDir, cacheFile);
|
|
6908
|
-
const elapsed = Date.now() - start;
|
|
6909
|
-
if (res) {
|
|
6910
|
-
consola.success(`Restored Vue client and server builds from cache in \`${elapsed}ms\`.`);
|
|
6911
|
-
}
|
|
6912
|
-
return res;
|
|
6913
|
-
}
|
|
6914
|
-
};
|
|
6915
|
-
}
|
|
6916
|
-
async function cleanupCaches(nuxt) {
|
|
6917
|
-
const start = Date.now();
|
|
6918
|
-
const caches = await glob(["*/*.tar"], {
|
|
6919
|
-
cwd: getCacheDir(nuxt),
|
|
6920
|
-
absolute: true
|
|
6921
|
-
});
|
|
6922
|
-
if (caches.length >= 10) {
|
|
6923
|
-
const cachesWithMeta = await Promise.all(caches.map(async (cache) => {
|
|
6924
|
-
return [cache, await stat(cache).then((r) => r.mtime.getTime()).catch(() => 0)];
|
|
6925
|
-
}));
|
|
6926
|
-
cachesWithMeta.sort((a, b) => a[1] - b[1]);
|
|
6927
|
-
for (const [cache] of cachesWithMeta.slice(0, cachesWithMeta.length - 10)) {
|
|
6928
|
-
await unlink(cache);
|
|
6929
|
-
}
|
|
6930
|
-
const elapsed = Date.now() - start;
|
|
6931
|
-
consola.success(`Cleaned up old build caches in \`${elapsed}ms\`.`);
|
|
6932
|
-
}
|
|
6933
|
-
}
|
|
6934
|
-
async function getHashes(nuxt, options) {
|
|
6935
|
-
if (nuxt[`_${options.id}BuildHash`]) {
|
|
6936
|
-
return nuxt[`_${options.id}BuildHash`];
|
|
6937
|
-
}
|
|
6938
|
-
const start = Date.now();
|
|
6939
|
-
const hashSources = [];
|
|
6940
|
-
let layerCtr = 0;
|
|
6941
|
-
for (const layer of nuxt.options._layers) {
|
|
6942
|
-
if (layer.cwd.includes("node_modules")) {
|
|
6943
|
-
continue;
|
|
6944
|
-
}
|
|
6945
|
-
const layerName = `layer#${layerCtr++}`;
|
|
6946
|
-
hashSources.push({
|
|
6947
|
-
name: `${layerName}:config`,
|
|
6948
|
-
data: serialize({
|
|
6949
|
-
...layer.config,
|
|
6950
|
-
...options.configOverrides || {}
|
|
6951
|
-
})
|
|
6952
|
-
});
|
|
6953
|
-
const normalizeFiles = (files) => files.map((f) => ({
|
|
6954
|
-
name: f.name,
|
|
6955
|
-
size: f.attrs?.size,
|
|
6956
|
-
data: hash(f.data)
|
|
6957
|
-
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
6958
|
-
const isIgnored = createIsIgnored(nuxt);
|
|
6959
|
-
const sourceFiles = await readFilesRecursive(options.cwd(layer), {
|
|
6960
|
-
shouldIgnore: isIgnored,
|
|
6961
|
-
// TODO: Validate if works with absolute paths
|
|
6962
|
-
cwd: nuxt.options.rootDir,
|
|
6963
|
-
patterns: options.patterns(layer)
|
|
6964
|
-
});
|
|
6965
|
-
hashSources.push({
|
|
6966
|
-
name: `${layerName}:src`,
|
|
6967
|
-
data: normalizeFiles(sourceFiles)
|
|
6968
|
-
});
|
|
6969
|
-
const rootFiles = await readFilesRecursive(layer.config?.rootDir || layer.cwd, {
|
|
6970
|
-
shouldIgnore: isIgnored,
|
|
6971
|
-
// TODO: Validate if works with absolute paths
|
|
6972
|
-
cwd: nuxt.options.rootDir,
|
|
6973
|
-
patterns: [
|
|
6974
|
-
".nuxtrc",
|
|
6975
|
-
".npmrc",
|
|
6976
|
-
"package.json",
|
|
6977
|
-
"package-lock.json",
|
|
6978
|
-
"yarn.lock",
|
|
6979
|
-
"pnpm-lock.yaml",
|
|
6980
|
-
"tsconfig.json",
|
|
6981
|
-
"bun.lock",
|
|
6982
|
-
"bun.lockb"
|
|
6983
|
-
]
|
|
6984
|
-
});
|
|
6985
|
-
hashSources.push({
|
|
6986
|
-
name: `${layerName}:root`,
|
|
6987
|
-
data: normalizeFiles(rootFiles)
|
|
6988
|
-
});
|
|
6989
|
-
}
|
|
6990
|
-
hashSources.sort((a, b) => a.name.localeCompare(b.name));
|
|
6991
|
-
const res = nuxt[`_${options.id}BuildHash`] = {
|
|
6992
|
-
hash: hash(hashSources),
|
|
6993
|
-
sources: hashSources
|
|
6994
|
-
};
|
|
6995
|
-
const elapsed = Date.now() - start;
|
|
6996
|
-
consola.debug(`Computed \`${options.id}\` build hash in \`${elapsed}ms\`.`);
|
|
6997
|
-
return res;
|
|
6998
|
-
}
|
|
6999
|
-
async function readFilesRecursive(dir, opts) {
|
|
7000
|
-
if (Array.isArray(dir)) {
|
|
7001
|
-
return (await Promise.all(dir.map((d) => readFilesRecursive(d, opts)))).flat();
|
|
7002
|
-
}
|
|
7003
|
-
const files = await glob(opts.patterns, { cwd: dir });
|
|
7004
|
-
const fileEntries = await Promise.all(files.map(async (fileName) => {
|
|
7005
|
-
if (!opts.shouldIgnore?.(fileName)) {
|
|
7006
|
-
const file = await readFileWithMeta(dir, fileName);
|
|
7007
|
-
if (!file) {
|
|
7008
|
-
return;
|
|
7009
|
-
}
|
|
7010
|
-
return {
|
|
7011
|
-
...file,
|
|
7012
|
-
name: relative(opts.cwd, join(dir, file.name))
|
|
7013
|
-
};
|
|
7014
|
-
}
|
|
7015
|
-
}));
|
|
7016
|
-
return fileEntries.filter(Boolean);
|
|
7017
|
-
}
|
|
7018
|
-
async function readFileWithMeta(dir, fileName, count = 0) {
|
|
7019
|
-
let fd = void 0;
|
|
7020
|
-
try {
|
|
7021
|
-
fd = await open(resolve$1(dir, fileName));
|
|
7022
|
-
const stats = await fd.stat();
|
|
7023
|
-
if (!stats?.isFile()) {
|
|
7024
|
-
return;
|
|
7025
|
-
}
|
|
7026
|
-
const mtime = stats.mtime.getTime();
|
|
7027
|
-
const data = await fd.readFile();
|
|
7028
|
-
if ((await fd.stat()).mtime.getTime() !== mtime) {
|
|
7029
|
-
if (count < 5) {
|
|
7030
|
-
return readFileWithMeta(dir, fileName, count + 1);
|
|
7031
|
-
}
|
|
7032
|
-
console.warn(`Failed to read file \`${fileName}\` as it changed during read.`);
|
|
7033
|
-
return;
|
|
7034
|
-
}
|
|
7035
|
-
return {
|
|
7036
|
-
name: fileName,
|
|
7037
|
-
data,
|
|
7038
|
-
attrs: {
|
|
7039
|
-
mtime,
|
|
7040
|
-
size: stats.size
|
|
7041
|
-
}
|
|
7042
|
-
};
|
|
7043
|
-
} catch (err) {
|
|
7044
|
-
console.warn(`Failed to read file \`${fileName}\`:`, err);
|
|
7045
|
-
} finally {
|
|
7046
|
-
await fd?.close();
|
|
7047
|
-
}
|
|
7048
|
-
}
|
|
7049
|
-
async function restoreCache(cwd, cacheFile) {
|
|
7050
|
-
if (!existsSync(cacheFile)) {
|
|
7051
|
-
return false;
|
|
7052
|
-
}
|
|
7053
|
-
const files = parseTar(await readFile(cacheFile));
|
|
7054
|
-
for (const file of files) {
|
|
7055
|
-
let fd = void 0;
|
|
7056
|
-
try {
|
|
7057
|
-
const filePath = resolve$1(cwd, file.name);
|
|
7058
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
7059
|
-
fd = await open(filePath, "w");
|
|
7060
|
-
const stats = await fd.stat().catch(() => null);
|
|
7061
|
-
if (stats?.isFile() && stats.size) {
|
|
7062
|
-
const lastModified = Number.parseInt(file.attrs?.mtime?.toString().padEnd(13, "0") || "0");
|
|
7063
|
-
if (stats.mtime.getTime() >= lastModified) {
|
|
7064
|
-
consola.debug(`Skipping \`${file.name}\` (up to date or newer than cache)`);
|
|
7065
|
-
continue;
|
|
7066
|
-
}
|
|
7067
|
-
}
|
|
7068
|
-
await fd.writeFile(file.data);
|
|
7069
|
-
} catch (err) {
|
|
7070
|
-
console.error(err);
|
|
7071
|
-
} finally {
|
|
7072
|
-
await fd?.close();
|
|
7073
|
-
}
|
|
7074
|
-
}
|
|
7075
|
-
return true;
|
|
7076
|
-
}
|
|
7077
|
-
async function writeCache(cwd, sources, cacheFile) {
|
|
7078
|
-
const fileEntries = await readFilesRecursive(sources, {
|
|
7079
|
-
patterns: ["**/*", "!analyze/**"],
|
|
7080
|
-
cwd
|
|
7081
|
-
});
|
|
7082
|
-
const tarData = createTar(fileEntries);
|
|
7083
|
-
await mkdir(dirname(cacheFile), { recursive: true });
|
|
7084
|
-
await writeFile(cacheFile, tarData);
|
|
7085
|
-
}
|
|
7086
|
-
function getCacheDir(nuxt) {
|
|
7087
|
-
let cacheDir = join(nuxt.options.workspaceDir, "node_modules");
|
|
7088
|
-
if (!existsSync(cacheDir)) {
|
|
7089
|
-
for (const dir of [...nuxt.options.modulesDir].sort((a, b) => a.length - b.length)) {
|
|
7090
|
-
if (existsSync(dir)) {
|
|
7091
|
-
cacheDir = dir;
|
|
7092
|
-
break;
|
|
7093
|
-
}
|
|
7094
|
-
}
|
|
7095
|
-
}
|
|
7096
|
-
return join(cacheDir, ".cache/nuxt/builds");
|
|
7097
|
-
}
|
|
7098
|
-
|
|
7099
8311
|
async function build(nuxt) {
|
|
8312
|
+
nuxt._perf?.startPhase("app:generate");
|
|
7100
8313
|
const app = createApp(nuxt);
|
|
7101
8314
|
nuxt.apps.default = app;
|
|
7102
8315
|
const generateApp$1 = debounce(() => generateApp(nuxt, app), void 0, { leading: true });
|
|
7103
8316
|
await generateApp$1();
|
|
8317
|
+
nuxt._perf?.endPhase("app:generate");
|
|
7104
8318
|
if (nuxt.options.dev) {
|
|
7105
8319
|
watch(nuxt);
|
|
7106
8320
|
nuxt.hook("builder:watch", async (event, relativePath) => {
|
|
@@ -7131,7 +8345,8 @@ async function build(nuxt) {
|
|
|
7131
8345
|
const { restoreCache, collectCache } = await getVueHash(nuxt);
|
|
7132
8346
|
if (await restoreCache()) {
|
|
7133
8347
|
await nuxt.callHook("build:done");
|
|
7134
|
-
|
|
8348
|
+
await nuxt.callHook("close", nuxt);
|
|
8349
|
+
return;
|
|
7135
8350
|
}
|
|
7136
8351
|
nuxt.hooks.hookOnce("nitro:build:before", () => collectCache());
|
|
7137
8352
|
nuxt.hooks.hookOnce("close", () => cleanupCaches(nuxt));
|
|
@@ -7146,7 +8361,9 @@ async function build(nuxt) {
|
|
|
7146
8361
|
checkForExternalConfigurationFiles().catch((e) => logger.warn("Problem checking for external configuration files.", e));
|
|
7147
8362
|
});
|
|
7148
8363
|
}
|
|
8364
|
+
nuxt._perf?.startPhase("build:bundle");
|
|
7149
8365
|
await bundle(nuxt);
|
|
8366
|
+
nuxt._perf?.endPhase("build:bundle");
|
|
7150
8367
|
await nuxt.callHook("build:done");
|
|
7151
8368
|
if (!nuxt.options.dev) {
|
|
7152
8369
|
await nuxt.callHook("close", nuxt);
|
|
@@ -7172,7 +8389,15 @@ async function watch(nuxt) {
|
|
|
7172
8389
|
function createWatcher() {
|
|
7173
8390
|
const nuxt = useNuxt();
|
|
7174
8391
|
const isIgnored2 = createIsIgnored(nuxt);
|
|
7175
|
-
const
|
|
8392
|
+
const layerDirs = getLayerDirectories(nuxt);
|
|
8393
|
+
const paths = [];
|
|
8394
|
+
for (const layer of layerDirs) {
|
|
8395
|
+
paths.push(layer.app);
|
|
8396
|
+
if (!layer.server.startsWith(layer.app.replace(/\/?$/, "/"))) {
|
|
8397
|
+
paths.push(layer.server);
|
|
8398
|
+
}
|
|
8399
|
+
}
|
|
8400
|
+
const watcher = watch$1(paths, {
|
|
7176
8401
|
...nuxt.options.watchers.chokidar,
|
|
7177
8402
|
ignoreInitial: true,
|
|
7178
8403
|
ignored: [isIgnored2, /[\\/]node_modules[\\/]/]
|
|
@@ -7305,10 +8530,12 @@ async function loadBuilder(nuxt, builder) {
|
|
|
7305
8530
|
function resolvePathsToWatch(nuxt, opts = {}) {
|
|
7306
8531
|
const pathsToWatch = /* @__PURE__ */ new Set();
|
|
7307
8532
|
for (const dirs of getLayerDirectories(nuxt)) {
|
|
7308
|
-
if (!
|
|
7309
|
-
|
|
8533
|
+
if (!isIgnored(dirs.app)) {
|
|
8534
|
+
pathsToWatch.add(dirs.app);
|
|
8535
|
+
}
|
|
8536
|
+
if (!isIgnored(dirs.server) && !dirs.server.startsWith(dirs.app.replace(/\/?$/, "/"))) {
|
|
8537
|
+
pathsToWatch.add(dirs.server);
|
|
7310
8538
|
}
|
|
7311
|
-
pathsToWatch.add(dirs.app);
|
|
7312
8539
|
}
|
|
7313
8540
|
for (const pattern of nuxt.options.watch) {
|
|
7314
8541
|
if (typeof pattern !== "string") {
|