@nuxt/hints 0.0.0 → 1.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/client/200.html +1 -0
- package/dist/client/404.html +1 -0
- package/dist/client/_nuxt/2EtD6e53.js +1 -0
- package/dist/client/_nuxt/2GP93Pxi.js +1 -0
- package/dist/client/_nuxt/3e1v2bzS.js +1 -0
- package/dist/client/_nuxt/5i3qLPDT.js +1 -0
- package/dist/client/_nuxt/B0m2ddpp.js +1 -0
- package/dist/client/_nuxt/B1dDrJ26.js +1 -0
- package/dist/client/_nuxt/B6aJPvgy.js +1 -0
- package/dist/client/_nuxt/B7mTdjB0.js +1 -0
- package/dist/client/_nuxt/BEDo0Tqx.js +1 -0
- package/dist/client/_nuxt/BGJmEYvX.js +1 -0
- package/dist/client/_nuxt/BHrmToEH.js +1 -0
- package/dist/client/_nuxt/BIGW1oBm.js +1 -0
- package/dist/client/_nuxt/BLmx8bSh.js +1 -0
- package/dist/client/_nuxt/BLtJtn59.js +1 -0
- package/dist/client/_nuxt/BPQ3VLAy.js +1 -0
- package/dist/client/_nuxt/BXkSAIEj.js +1 -0
- package/dist/client/_nuxt/BfHTSMKl.js +1 -0
- package/dist/client/_nuxt/BfjtVDDH.js +1 -0
- package/dist/client/_nuxt/BgDCqdQA.js +1 -0
- package/dist/client/_nuxt/Bkuqu6BP.js +1 -0
- package/dist/client/_nuxt/Bp3cYrEr.js +1 -0
- package/dist/client/_nuxt/Br6cN0cg.js +1 -0
- package/dist/client/_nuxt/BthQWCQV.js +1 -0
- package/dist/client/_nuxt/Buea-lGh.js +1 -0
- package/dist/client/_nuxt/Bw305WKR.js +1 -0
- package/dist/client/_nuxt/BzJJZx-M.js +1 -0
- package/dist/client/_nuxt/C-Jbm3Hp.js +1 -0
- package/dist/client/_nuxt/C39BiMTA.js +1 -0
- package/dist/client/_nuxt/C8M2exoo.js +1 -0
- package/dist/client/_nuxt/C9dUb6Cb.js +1 -0
- package/dist/client/_nuxt/C9oPPf7i.js +1 -0
- package/dist/client/_nuxt/C9tS-k6U.js +1 -0
- package/dist/client/_nuxt/CDVJQ6XC.js +1 -0
- package/dist/client/_nuxt/CEG3Q07z.js +1 -0
- package/dist/client/_nuxt/CFHQjOhq.js +1 -0
- package/dist/client/_nuxt/CG6Dc4jp.js +1 -0
- package/dist/client/_nuxt/CGQlbfJh.js +6 -0
- package/dist/client/_nuxt/CH1njM8p.js +1 -0
- package/dist/client/_nuxt/CJC4nrSc.js +1 -0
- package/dist/client/_nuxt/CMFEf1DS.js +1 -0
- package/dist/client/_nuxt/COt5Ahok.js +1 -0
- package/dist/client/_nuxt/CS3Unz2-.js +1 -0
- package/dist/client/_nuxt/CTRr51gU.js +1 -0
- package/dist/client/_nuxt/CVO1_9PV.js +1 -0
- package/dist/client/_nuxt/CVdnzihN.js +1 -0
- package/dist/client/_nuxt/CXZktZb0.js +1 -0
- package/dist/client/_nuxt/CXtECtnM.js +1 -0
- package/dist/client/_nuxt/CYsAdtH9.js +1 -0
- package/dist/client/_nuxt/CafNBF8u.js +1 -0
- package/dist/client/_nuxt/CbfX1IO0.js +1 -0
- package/dist/client/_nuxt/CfQXZHmo.js +1 -0
- package/dist/client/_nuxt/CgjmDhmW.js +1 -0
- package/dist/client/_nuxt/Cj5Yp3dK.js +1 -0
- package/dist/client/_nuxt/CkXjmgJE.js +1 -0
- package/dist/client/_nuxt/Cl0AqbOI.js +1 -0
- package/dist/client/_nuxt/Cm3UrAx6.js +1 -0
- package/dist/client/_nuxt/CmIQRyeF.js +1 -0
- package/dist/client/_nuxt/Cmh6b_Ma.js +1 -0
- package/dist/client/_nuxt/CnK8MTSM.js +1 -0
- package/dist/client/_nuxt/CnnebwVN.js +1 -0
- package/dist/client/_nuxt/Cp-IABpG.js +1 -0
- package/dist/client/_nuxt/Csfq5Kiy.js +1 -0
- package/dist/client/_nuxt/CufHLc7y.js +1 -0
- package/dist/client/_nuxt/Cuk6v7N8.js +1 -0
- package/dist/client/_nuxt/Cv9koXgw.js +1 -0
- package/dist/client/_nuxt/Cvjx9yec.js +1 -0
- package/dist/client/_nuxt/Cw07ACep.js +1 -0
- package/dist/client/_nuxt/CxbxFI8M.js +1 -0
- package/dist/client/_nuxt/CyktbL80.js +1 -0
- package/dist/client/_nuxt/CylS5w8V.js +1 -0
- package/dist/client/_nuxt/D-2ljcwZ.js +1 -0
- package/dist/client/_nuxt/D0r3Knsf.js +1 -0
- package/dist/client/_nuxt/D4h5O-jR.js +1 -0
- package/dist/client/_nuxt/D5KoaKCx.js +1 -0
- package/dist/client/_nuxt/D7VJQ_DO.js +1 -0
- package/dist/client/_nuxt/D7oLnXFd.js +1 -0
- package/dist/client/_nuxt/D87Tk5Gz.js +1 -0
- package/dist/client/_nuxt/DAi9KRSo.js +1 -0
- package/dist/client/_nuxt/DDBovgxi.js +1 -0
- package/dist/client/_nuxt/DFWUc33u.js +1 -0
- package/dist/client/_nuxt/DGP4VlC8.js +1 -0
- package/dist/client/_nuxt/DGztddWO.js +1 -0
- package/dist/client/_nuxt/DH5Ifo-i.js +1 -0
- package/dist/client/_nuxt/DH652Aoo.js +6 -0
- package/dist/client/_nuxt/DHJKELXO.js +1 -0
- package/dist/client/_nuxt/DJJ7OUMB.js +1 -0
- package/dist/client/_nuxt/DNMeEaky.js +1 -0
- package/dist/client/_nuxt/DPfMkruS.js +1 -0
- package/dist/client/_nuxt/DQyhUUbL.js +1 -0
- package/dist/client/_nuxt/DRw_LuNl.js +1 -0
- package/dist/client/_nuxt/DU1UobuO.js +1 -0
- package/dist/client/_nuxt/DU4nAREn.js +9 -0
- package/dist/client/_nuxt/DUszq2jm.js +1 -0
- package/dist/client/_nuxt/DVMEJ2y_.js +1 -0
- package/dist/client/_nuxt/DWedfzmr.js +1 -0
- package/dist/client/_nuxt/DXbdFlpD.js +1 -0
- package/dist/client/_nuxt/DZxFcAj9.js +1 -0
- package/dist/client/_nuxt/DcaNXYhu.js +1 -0
- package/dist/client/_nuxt/Ddv68eIx.js +1 -0
- package/dist/client/_nuxt/Des-eS-w.js +1 -0
- package/dist/client/_nuxt/DiinP2Uv.js +1 -0
- package/dist/client/_nuxt/DnULxvSX.js +1 -0
- package/dist/client/_nuxt/Do-INFgi.js +1 -0
- package/dist/client/_nuxt/DqwNpetd.js +1 -0
- package/dist/client/_nuxt/Dx-B1_4e.js +1 -0
- package/dist/client/_nuxt/DxNHbxmM.js +1 -0
- package/dist/client/_nuxt/DxSwrfjg.js +1 -0
- package/dist/client/_nuxt/E3gJ1_iC.js +1 -0
- package/dist/client/_nuxt/GsRaNv29.js +1 -0
- package/dist/client/_nuxt/L9t79GZl.js +1 -0
- package/dist/client/_nuxt/MKoRwnMq.js +1 -0
- package/dist/client/_nuxt/MzD3tlZU.js +1 -0
- package/dist/client/_nuxt/NleAzG8P.js +1 -0
- package/dist/client/_nuxt/PoHY5YXO.js +1 -0
- package/dist/client/_nuxt/TsXTqZ29.js +1 -0
- package/dist/client/_nuxt/Xqf5ue2O.js +1 -0
- package/dist/client/_nuxt/Yzrsuije.js +1 -0
- package/dist/client/_nuxt/bN70gL4F.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -0
- package/dist/client/_nuxt/builds/meta/13453bb2-1adb-44c7-ac19-ec44784e7219.json +1 -0
- package/dist/client/_nuxt/eOWES_5F.js +1 -0
- package/dist/client/_nuxt/entry.CqH3PPiL.css +1 -0
- package/dist/client/_nuxt/error-404.CrTd3IxL.css +1 -0
- package/dist/client/_nuxt/error-500.evxQRSU6.css +1 -0
- package/dist/client/_nuxt/fuZLfV_i.js +1 -0
- package/dist/client/_nuxt/g9-lgVsj.js +1 -0
- package/dist/client/_nuxt/hJgmCMqR.js +1 -0
- package/dist/client/_nuxt/hegEt444.js +1 -0
- package/dist/client/_nuxt/hydration.B5wxUWyr.css +1 -0
- package/dist/client/_nuxt/m17aaUwq.js +1 -0
- package/dist/client/_nuxt/nO2mFgKf.js +1 -0
- package/dist/client/_nuxt/qj2RPQZX.js +1 -0
- package/dist/client/_nuxt/rlWm2Bc0.js +1 -0
- package/dist/client/_nuxt/sLvN_949.js +1 -0
- package/dist/client/_nuxt/tqtdBwhO.js +1 -0
- package/dist/client/_nuxt/umNIi3wV.js +21 -0
- package/dist/client/_nuxt/wDzz0qaB.js +1 -0
- package/dist/client/_nuxt/z9IIGYC-.js +1 -0
- package/dist/client/hydration/index.html +1 -0
- package/dist/client/index.html +1 -0
- package/dist/client/third-party-scripts/index.html +1 -0
- package/dist/client/web-vitals/index.html +1 -0
- package/dist/module.d.mts +9 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +115 -0
- package/dist/runtime/core/components/nuxt-island.d.ts +137 -0
- package/dist/runtime/core/components/nuxt-island.js +14 -0
- package/dist/runtime/core/plugins/vue-tracer-state.client.d.ts +2 -0
- package/dist/runtime/core/plugins/vue-tracer-state.client.js +7 -0
- package/dist/runtime/hydration/composables.d.ts +5 -0
- package/dist/runtime/hydration/composables.js +46 -0
- package/dist/runtime/hydration/plugin.client.d.ts +2 -0
- package/dist/runtime/hydration/plugin.client.js +11 -0
- package/dist/runtime/third-party-scripts/nitro.plugin.d.ts +2 -0
- package/dist/runtime/third-party-scripts/nitro.plugin.js +48 -0
- package/dist/runtime/third-party-scripts/plugin.client.d.ts +2 -0
- package/dist/runtime/third-party-scripts/plugin.client.js +88 -0
- package/dist/runtime/types.d.ts +48 -0
- package/dist/runtime/web-vitals/plugin.client.d.ts +13 -0
- package/dist/runtime/web-vitals/plugin.client.js +137 -0
- package/dist/runtime/web-vitals/utils.d.ts +35 -0
- package/dist/runtime/web-vitals/utils.js +13 -0
- package/dist/types.d.mts +3 -0
- package/package.json +61 -2
- /package/dist/{.gitkeep → client/_nuxt/third-party-scripts.tn0RQdqM.css} +0 -0
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { addDevServerHandler, defineNuxtModule, createResolver, addPlugin, addBuildPlugin, addComponent, addServerPlugin } from '@nuxt/kit';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { eventHandler, proxyRequest } from 'h3';
|
|
4
|
+
import MagicString from 'magic-string';
|
|
5
|
+
import { createUnplugin } from 'unplugin';
|
|
6
|
+
|
|
7
|
+
const DEVTOOLS_UI_ROUTE = "/__nuxt-hints";
|
|
8
|
+
const DEVTOOLS_UI_LOCAL_PORT = 3300;
|
|
9
|
+
function setupDevToolsUI(nuxt, resolver) {
|
|
10
|
+
const clientPath = resolver.resolve("./client");
|
|
11
|
+
const isProductionBuild = existsSync(clientPath);
|
|
12
|
+
if (isProductionBuild) {
|
|
13
|
+
nuxt.hook("vite:serverCreated", async (server) => {
|
|
14
|
+
const sirv = await import('sirv').then((r) => r.default || r);
|
|
15
|
+
server.middlewares.use(
|
|
16
|
+
DEVTOOLS_UI_ROUTE,
|
|
17
|
+
sirv(clientPath, { dev: true, single: true })
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
addDevServerHandler({
|
|
22
|
+
route: DEVTOOLS_UI_ROUTE,
|
|
23
|
+
handler: eventHandler((e) => {
|
|
24
|
+
return proxyRequest(e, "http://localhost:" + DEVTOOLS_UI_LOCAL_PORT + DEVTOOLS_UI_ROUTE + e.path);
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
29
|
+
tabs.push({
|
|
30
|
+
name: "hints",
|
|
31
|
+
title: "Hints",
|
|
32
|
+
icon: "carbon:idea",
|
|
33
|
+
category: "analyze",
|
|
34
|
+
view: {
|
|
35
|
+
type: "iframe",
|
|
36
|
+
src: DEVTOOLS_UI_ROUTE
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const ID_INCLUDE = /\.vue$/;
|
|
43
|
+
const ID_EXCLUDE = /node_modules/;
|
|
44
|
+
const InjectHydrationPlugin = createUnplugin(() => {
|
|
45
|
+
return {
|
|
46
|
+
name: "@nuxt/hints:inject-hydration-check",
|
|
47
|
+
enforce: "pre",
|
|
48
|
+
transformInclude(id) {
|
|
49
|
+
return id.endsWith(".vue") && !id.includes("node_modules");
|
|
50
|
+
},
|
|
51
|
+
transform: {
|
|
52
|
+
filter: {
|
|
53
|
+
id: {
|
|
54
|
+
include: ID_INCLUDE,
|
|
55
|
+
exclude: ID_EXCLUDE
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
handler(code) {
|
|
59
|
+
const m = new MagicString(code);
|
|
60
|
+
const re = /<script\s+setup[^>]*>/g;
|
|
61
|
+
const match = re.exec(code);
|
|
62
|
+
if (!match) {
|
|
63
|
+
return code;
|
|
64
|
+
}
|
|
65
|
+
m.appendRight(
|
|
66
|
+
match.index + match[0].length,
|
|
67
|
+
`
|
|
68
|
+
import { useHydrationCheck } from '@nuxt/hints/runtime/hydration/composables'
|
|
69
|
+
useHydrationCheck();`
|
|
70
|
+
);
|
|
71
|
+
return {
|
|
72
|
+
code: m.toString(),
|
|
73
|
+
map: m.generateMap({ hires: true })
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const module$1 = defineNuxtModule({
|
|
81
|
+
meta: {
|
|
82
|
+
name: "@nuxt/hints",
|
|
83
|
+
configKey: "hints"
|
|
84
|
+
},
|
|
85
|
+
defaults: {
|
|
86
|
+
devtools: true
|
|
87
|
+
},
|
|
88
|
+
setup(options, nuxt) {
|
|
89
|
+
if (!nuxt.options.dev) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const resolver = createResolver(import.meta.url);
|
|
93
|
+
addPlugin(resolver.resolve("./runtime/web-vitals/plugin.client"));
|
|
94
|
+
addPlugin(resolver.resolve("./runtime/hydration/plugin.client"));
|
|
95
|
+
addBuildPlugin(InjectHydrationPlugin);
|
|
96
|
+
addComponent({
|
|
97
|
+
name: "NuxtIsland",
|
|
98
|
+
filePath: resolver.resolve("./runtime/core/components/nuxt-island"),
|
|
99
|
+
priority: 1e3
|
|
100
|
+
});
|
|
101
|
+
addPlugin(resolver.resolve("./runtime/third-party-scripts/plugin.client"));
|
|
102
|
+
addServerPlugin(resolver.resolve("./runtime/third-party-scripts/nitro.plugin"));
|
|
103
|
+
nuxt.hook("prepare:types", ({ references }) => {
|
|
104
|
+
references.push({
|
|
105
|
+
types: resolver.resolve("./runtime/types.d.ts")
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
if (options.devtools) {
|
|
109
|
+
setupDevToolsUI(nuxt, resolver);
|
|
110
|
+
addPlugin(resolver.resolve("./runtime/core/plugins/vue-tracer-state.client"));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export { module$1 as default };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
declare const HintsNuxtIsland: {
|
|
2
|
+
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
|
|
3
|
+
name: {
|
|
4
|
+
type: StringConstructor;
|
|
5
|
+
required: true;
|
|
6
|
+
};
|
|
7
|
+
lazy: BooleanConstructor;
|
|
8
|
+
props: {
|
|
9
|
+
type: ObjectConstructor;
|
|
10
|
+
default: () => undefined;
|
|
11
|
+
};
|
|
12
|
+
context: {
|
|
13
|
+
type: ObjectConstructor;
|
|
14
|
+
default: () => {};
|
|
15
|
+
};
|
|
16
|
+
scopeId: {
|
|
17
|
+
type: import("vue").PropType<string | undefined | null>;
|
|
18
|
+
default: () => undefined;
|
|
19
|
+
};
|
|
20
|
+
source: {
|
|
21
|
+
type: StringConstructor;
|
|
22
|
+
default: () => undefined;
|
|
23
|
+
};
|
|
24
|
+
dangerouslyLoadClientComponents: {
|
|
25
|
+
type: BooleanConstructor;
|
|
26
|
+
default: boolean;
|
|
27
|
+
};
|
|
28
|
+
}>> & Readonly<{
|
|
29
|
+
onError?: ((...args: any[]) => any) | undefined;
|
|
30
|
+
}>, (_ctx: any, _cache: any) => (import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
}> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}>[])[] | import("vue").VNode<any, any, {
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}>[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "error"[], import("vue").PublicProps, {
|
|
37
|
+
props: Record<string, any>;
|
|
38
|
+
source: string;
|
|
39
|
+
scopeId: string | null | undefined;
|
|
40
|
+
lazy: boolean;
|
|
41
|
+
context: Record<string, any>;
|
|
42
|
+
dangerouslyLoadClientComponents: boolean;
|
|
43
|
+
}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
|
|
44
|
+
P: {};
|
|
45
|
+
B: {};
|
|
46
|
+
D: {};
|
|
47
|
+
C: {};
|
|
48
|
+
M: {};
|
|
49
|
+
Defaults: {};
|
|
50
|
+
}, Readonly<import("vue").ExtractPropTypes<{
|
|
51
|
+
name: {
|
|
52
|
+
type: StringConstructor;
|
|
53
|
+
required: true;
|
|
54
|
+
};
|
|
55
|
+
lazy: BooleanConstructor;
|
|
56
|
+
props: {
|
|
57
|
+
type: ObjectConstructor;
|
|
58
|
+
default: () => undefined;
|
|
59
|
+
};
|
|
60
|
+
context: {
|
|
61
|
+
type: ObjectConstructor;
|
|
62
|
+
default: () => {};
|
|
63
|
+
};
|
|
64
|
+
scopeId: {
|
|
65
|
+
type: import("vue").PropType<string | undefined | null>;
|
|
66
|
+
default: () => undefined;
|
|
67
|
+
};
|
|
68
|
+
source: {
|
|
69
|
+
type: StringConstructor;
|
|
70
|
+
default: () => undefined;
|
|
71
|
+
};
|
|
72
|
+
dangerouslyLoadClientComponents: {
|
|
73
|
+
type: BooleanConstructor;
|
|
74
|
+
default: boolean;
|
|
75
|
+
};
|
|
76
|
+
}>> & Readonly<{
|
|
77
|
+
onError?: ((...args: any[]) => any) | undefined;
|
|
78
|
+
}>, (_ctx: any, _cache: any) => (import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
}> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
81
|
+
[key: string]: any;
|
|
82
|
+
}>[])[] | import("vue").VNode<any, any, {
|
|
83
|
+
[key: string]: any;
|
|
84
|
+
}>[], {}, {}, {}, {
|
|
85
|
+
props: Record<string, any>;
|
|
86
|
+
source: string;
|
|
87
|
+
scopeId: string | null | undefined;
|
|
88
|
+
lazy: boolean;
|
|
89
|
+
context: Record<string, any>;
|
|
90
|
+
dangerouslyLoadClientComponents: boolean;
|
|
91
|
+
}>;
|
|
92
|
+
__isFragment?: never;
|
|
93
|
+
__isTeleport?: never;
|
|
94
|
+
__isSuspense?: never;
|
|
95
|
+
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
|
|
96
|
+
name: {
|
|
97
|
+
type: StringConstructor;
|
|
98
|
+
required: true;
|
|
99
|
+
};
|
|
100
|
+
lazy: BooleanConstructor;
|
|
101
|
+
props: {
|
|
102
|
+
type: ObjectConstructor;
|
|
103
|
+
default: () => undefined;
|
|
104
|
+
};
|
|
105
|
+
context: {
|
|
106
|
+
type: ObjectConstructor;
|
|
107
|
+
default: () => {};
|
|
108
|
+
};
|
|
109
|
+
scopeId: {
|
|
110
|
+
type: import("vue").PropType<string | undefined | null>;
|
|
111
|
+
default: () => undefined;
|
|
112
|
+
};
|
|
113
|
+
source: {
|
|
114
|
+
type: StringConstructor;
|
|
115
|
+
default: () => undefined;
|
|
116
|
+
};
|
|
117
|
+
dangerouslyLoadClientComponents: {
|
|
118
|
+
type: BooleanConstructor;
|
|
119
|
+
default: boolean;
|
|
120
|
+
};
|
|
121
|
+
}>> & Readonly<{
|
|
122
|
+
onError?: ((...args: any[]) => any) | undefined;
|
|
123
|
+
}>, (_ctx: any, _cache: any) => (import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
124
|
+
[key: string]: any;
|
|
125
|
+
}> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
126
|
+
[key: string]: any;
|
|
127
|
+
}>[])[] | import("vue").VNode<any, any, {
|
|
128
|
+
[key: string]: any;
|
|
129
|
+
}>[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "error"[], "error", {
|
|
130
|
+
props: Record<string, any>;
|
|
131
|
+
source: string;
|
|
132
|
+
scopeId: string | null | undefined;
|
|
133
|
+
lazy: boolean;
|
|
134
|
+
context: Record<string, any>;
|
|
135
|
+
dangerouslyLoadClientComponents: boolean;
|
|
136
|
+
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps;
|
|
137
|
+
export default HintsNuxtIsland;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import NuxtIsland from "#app/components/nuxt-island";
|
|
2
|
+
import { useNuxtApp } from "#imports";
|
|
3
|
+
const originalSetup = NuxtIsland.setup;
|
|
4
|
+
const HintsNuxtIsland = Object.assign({}, NuxtIsland, {
|
|
5
|
+
setup(props, ctx) {
|
|
6
|
+
if (useNuxtApp().ssrContext?.islandContext) {
|
|
7
|
+
console.warn(
|
|
8
|
+
`[@nuxt/hints] Nesting islands within islands is not recommanded for performance reasons. This leads to waterfall calls.`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
return originalSetup(props, ctx);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
export default HintsNuxtIsland;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as tracerOverlay from "vite-plugin-vue-tracer/client/overlay";
|
|
2
|
+
import * as tracerRecord from "vite-plugin-vue-tracer/client/record";
|
|
3
|
+
import { defineNuxtPlugin } from "#imports";
|
|
4
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
5
|
+
nuxtApp.__tracerOverlay = tracerOverlay;
|
|
6
|
+
nuxtApp.__tracerRecord = tracerRecord;
|
|
7
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getCurrentInstance, onMounted } from "vue";
|
|
2
|
+
import { useNuxtApp } from "#imports";
|
|
3
|
+
function formatHTML(html) {
|
|
4
|
+
if (!html) return "";
|
|
5
|
+
let formatted = "";
|
|
6
|
+
let indent = 0;
|
|
7
|
+
const tags = html.split(/(<\/?[^>]+>)/g);
|
|
8
|
+
for (const tag of tags) {
|
|
9
|
+
if (!tag.trim()) continue;
|
|
10
|
+
if (tag.startsWith("</")) {
|
|
11
|
+
indent--;
|
|
12
|
+
formatted += "\n" + " ".repeat(Math.max(0, indent)) + tag;
|
|
13
|
+
} else if (tag.startsWith("<") && !tag.endsWith("/>") && !tag.includes("<!")) {
|
|
14
|
+
formatted += "\n" + " ".repeat(indent) + tag;
|
|
15
|
+
indent++;
|
|
16
|
+
} else if (tag.startsWith("<")) {
|
|
17
|
+
formatted += "\n" + " ".repeat(indent) + tag;
|
|
18
|
+
} else {
|
|
19
|
+
formatted += "\n" + " ".repeat(indent) + tag.trim();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return formatted.trim();
|
|
23
|
+
}
|
|
24
|
+
export function useHydrationCheck() {
|
|
25
|
+
if (import.meta.server) return;
|
|
26
|
+
const nuxtApp = useNuxtApp();
|
|
27
|
+
if (!nuxtApp.isHydrating) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const instance = getCurrentInstance();
|
|
31
|
+
if (!instance) return;
|
|
32
|
+
const htmlPrehydration = formatHTML(instance.vnode.el?.outerHTML);
|
|
33
|
+
const vnodePrehydration = instance.vnode;
|
|
34
|
+
onMounted(() => {
|
|
35
|
+
const htmlPostHydration = formatHTML(instance.vnode.el?.outerHTML);
|
|
36
|
+
if (htmlPrehydration !== htmlPostHydration) {
|
|
37
|
+
nuxtApp.__hints.hydration.push({
|
|
38
|
+
instance,
|
|
39
|
+
vnode: vnodePrehydration,
|
|
40
|
+
htmlPreHydration: htmlPrehydration,
|
|
41
|
+
htmlPostHydration
|
|
42
|
+
});
|
|
43
|
+
console.warn(`[nuxt/hints:hydration] Component ${instance.type.name ?? instance.type.displayName ?? instance.type.__name ?? instance.type.__file} seems to have different html pre and post-hydration. Please make sure you don't have any hydration issue.`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineNuxtPlugin, useNuxtApp } from "#imports";
|
|
2
|
+
import { defu } from "defu";
|
|
3
|
+
export default defineNuxtPlugin({
|
|
4
|
+
name: "@nuxt/hints:hydration",
|
|
5
|
+
setup() {
|
|
6
|
+
const nuxtApp = useNuxtApp();
|
|
7
|
+
nuxtApp.__hints = defu(nuxtApp.__hints, {
|
|
8
|
+
hydration: []
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export default function(nitroApp) {
|
|
2
|
+
nitroApp.hooks.hook("render:html", ({ head }) => {
|
|
3
|
+
head.unshift(`
|
|
4
|
+
<script>
|
|
5
|
+
window.__hints_TPC_start_time = Date.now();
|
|
6
|
+
|
|
7
|
+
function __hints_TPC_saveTime(script, startTime) {
|
|
8
|
+
script.__hints_TPC_end_time = Date.now();
|
|
9
|
+
const scriptStartTime = startTime || script.__hints_TPC_start_time || window.__hints_TPC_start_time;
|
|
10
|
+
|
|
11
|
+
const resourceEntries = performance.getEntriesByName(script.src)
|
|
12
|
+
const scriptEntry = resourceEntries.find(entry => entry.name === script.src)
|
|
13
|
+
|
|
14
|
+
if (scriptEntry) {
|
|
15
|
+
// Calculate parse + execute time using modern API
|
|
16
|
+
const navigationEntry = performance.getEntriesByType('navigation')[0]
|
|
17
|
+
const navigationStart = navigationEntry ? performance.timeOrigin : performance.timeOrigin
|
|
18
|
+
|
|
19
|
+
script.requestTime = (scriptEntry.responseStart - scriptEntry.requestStart);
|
|
20
|
+
script.downloadTime = (scriptEntry.responseEnd - scriptEntry.responseStart);
|
|
21
|
+
script.totalNetworkTime = (scriptEntry.responseEnd - scriptEntry.startTime);
|
|
22
|
+
script.parseExecuteTime = script.__hints_TPC_end_time - (navigationStart + scriptEntry.responseEnd);
|
|
23
|
+
script.loaded = true;
|
|
24
|
+
console.log('[@nuxt/hints]: \u{1F4CA} Detailed timing for', script.src, {
|
|
25
|
+
'Request': script.requestTime.toFixed(2) + 'ms',
|
|
26
|
+
'Download': script.downloadTime.toFixed(2) + 'ms',
|
|
27
|
+
'Total Network': script.totalNetworkTime.toFixed(2) + 'ms',
|
|
28
|
+
'Parse + Execute': script.parseExecuteTime.toFixed(2) + 'ms'
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
<\/script>
|
|
33
|
+
`);
|
|
34
|
+
head.push(`
|
|
35
|
+
<script>
|
|
36
|
+
for (const script of document.scripts) {
|
|
37
|
+
if (script.src && !script.src.startsWith(window.location.origin)) {
|
|
38
|
+
script.__hints_TPC_start_time = window.__hints_TPC_start_time || Date.now();
|
|
39
|
+
script.onload = function(_) {
|
|
40
|
+
__hints_TPC_saveTime(script, script.__hints_TPC_start_time);
|
|
41
|
+
}
|
|
42
|
+
__hints_TPC_saveTime(script, script.__hints_TPC_start_time);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
<\/script>
|
|
46
|
+
`);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { defineNuxtPlugin, ref, useNuxtApp } from "#imports";
|
|
2
|
+
const EXTENSIONS_SCHEMES_RE = /^(chrome-extension|moz-extension|safari-extension|ms-browser-extension):/;
|
|
3
|
+
function isExtensionScript(src) {
|
|
4
|
+
try {
|
|
5
|
+
const url = new URL(src, window.location.origin);
|
|
6
|
+
return EXTENSIONS_SCHEMES_RE.test(url.protocol);
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function isSameOriginScript(src) {
|
|
12
|
+
try {
|
|
13
|
+
const url = new URL(src, window.location.origin);
|
|
14
|
+
return url.origin === window.location.origin;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function isIgnoredScript(src) {
|
|
20
|
+
return isSameOriginScript(src) || isExtensionScript(src);
|
|
21
|
+
}
|
|
22
|
+
export default defineNuxtPlugin({
|
|
23
|
+
name: "nuxt-hints:third-party-scripts",
|
|
24
|
+
setup() {
|
|
25
|
+
const nuxtApp = useNuxtApp();
|
|
26
|
+
const scripts = nuxtApp.__hints_tpc = ref([]);
|
|
27
|
+
const isUsingNuxtScripts = !!nuxtApp.$scripts;
|
|
28
|
+
nuxtApp.hook("hints:scripts:added", (script) => {
|
|
29
|
+
scripts.value.push({ element: script, loaded: false });
|
|
30
|
+
});
|
|
31
|
+
nuxtApp.hook("hints:scripts:loaded", (script) => {
|
|
32
|
+
const existingScript = scripts.value.find((s) => s.element === script);
|
|
33
|
+
if (existingScript) {
|
|
34
|
+
existingScript.loaded = true;
|
|
35
|
+
} else {
|
|
36
|
+
console.warn(`[@nuxt/hints]: Script loaded event received for a script not tracked: ${script.src}. Please open an issue with a minimal reproduction if you think this is a bug.`);
|
|
37
|
+
scripts.value.push({ element: script, loaded: true });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
nuxtApp.hooks.hookOnce("app:mounted", () => {
|
|
41
|
+
let hasThirdPartyScript = false;
|
|
42
|
+
for (const script of document.scripts) {
|
|
43
|
+
if (script.src && !isIgnoredScript(script.src)) {
|
|
44
|
+
hasThirdPartyScript = true;
|
|
45
|
+
onScriptAdded(script);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (hasThirdPartyScript && !isUsingNuxtScripts) {
|
|
49
|
+
console.info("\u2139\uFE0F [@nuxt/hints]: Third-party scripts detected on page load: consider using @nuxt/scripts");
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const observer = new MutationObserver((mutations) => {
|
|
53
|
+
for (const mutation of mutations) {
|
|
54
|
+
if (mutation.type === "childList") {
|
|
55
|
+
for (const node of mutation.addedNodes) {
|
|
56
|
+
if (isScript(node) && node.src && !isIgnoredScript(node.src)) {
|
|
57
|
+
onScriptAdded(node);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
observer.observe(document.documentElement, {
|
|
64
|
+
childList: true,
|
|
65
|
+
subtree: true
|
|
66
|
+
});
|
|
67
|
+
function onScriptAdded(script) {
|
|
68
|
+
if (!script.crossOrigin) {
|
|
69
|
+
console.warn(`[@nuxt/hints]: Third-party script "${script.src}" is missing crossorigin attribute. Consider adding crossorigin="anonymous" for better security and error reporting.`);
|
|
70
|
+
}
|
|
71
|
+
nuxtApp.callHook("hints:scripts:added", script).then(() => {
|
|
72
|
+
if (!script.loaded) {
|
|
73
|
+
script.onload = () => {
|
|
74
|
+
window.__hints_TPC_saveTime(script, script.__hints_TPC_start_time);
|
|
75
|
+
nuxtApp.callHook("hints:scripts:loaded", script);
|
|
76
|
+
};
|
|
77
|
+
} else {
|
|
78
|
+
window.__hints_TPC_saveTime(script, script.__hints_TPC_start_time);
|
|
79
|
+
nuxtApp.callHook("hints:scripts:loaded", script);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
console.info(`\u2139\uFE0F [@nuxt/hints]: Dynamically added third-party script detected: ${script.src}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
function isScript(node) {
|
|
87
|
+
return node.nodeName === "SCRIPT";
|
|
88
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ComponentInternalInstance, VNode, Ref } from 'vue'
|
|
2
|
+
import type { LCPMetricWithAttribution, INPMetricWithAttribution, CLSMetricWithAttribution } from 'web-vitals/attribution'
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
__hints_TPC_start_time: number
|
|
7
|
+
__hints_TPC_saveTime: (script: HTMLScriptElement, startTime?: number) => void
|
|
8
|
+
}
|
|
9
|
+
interface HTMLScriptElement {
|
|
10
|
+
__hints_TPC_start_time?: number
|
|
11
|
+
__hints_TPC_end_time?: number
|
|
12
|
+
requestTime?: number
|
|
13
|
+
downloadTime?: number
|
|
14
|
+
totalNetworkTime?: number
|
|
15
|
+
parseExecuteTime?: number
|
|
16
|
+
loaded?: boolean
|
|
17
|
+
}
|
|
18
|
+
interface Element {
|
|
19
|
+
__vnode?: VNode
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
declare module '#app' {
|
|
23
|
+
interface RuntimeNuxtHooks {
|
|
24
|
+
'hints:scripts:added': (script: HTMLScriptElement) => void
|
|
25
|
+
'hints:scripts:loaded': (script: HTMLScriptElement) => void
|
|
26
|
+
|
|
27
|
+
'hints:webvitals:sync': (webvitals: NuxtApp['__hints']['webvitals']) => void
|
|
28
|
+
'hints:webvitals:lcp': (metric: LCPMetricWithAttribution) => void
|
|
29
|
+
'hints:webvitals:inp': (metric: INPMetricWithAttribution) => void
|
|
30
|
+
'hints:webvitals:cls': (metric: CLSMetricWithAttribution) => void
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface NuxtApp {
|
|
34
|
+
__hints_tpc: Ref<{ element: HTMLScriptElement, loaded: boolean }[]>
|
|
35
|
+
__hints: {
|
|
36
|
+
hydration: { instance: ComponentInternalInstance, vnode: VNode, htmlPreHydration: string | undefined, htmlPostHydration: string | undefined }[]
|
|
37
|
+
webvitals: {
|
|
38
|
+
lcp: Ref<LCPMetricWithAttribution[]>
|
|
39
|
+
inp: Ref<INPMetricWithAttribution[]>
|
|
40
|
+
cls: Ref<CLSMetricWithAttribution[]>
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
__tracerOverlay: typeof import('vite-plugin-vue-tracer/client/overlay')
|
|
44
|
+
__tracerRecord: typeof import('vite-plugin-vue-tracer/client/record')
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface PerformanceEntry {
|
|
3
|
+
element?: HTMLElement;
|
|
4
|
+
sources?: {
|
|
5
|
+
node: HTMLElement;
|
|
6
|
+
currentRect: DOMRect;
|
|
7
|
+
previousRect: DOMRect;
|
|
8
|
+
}[];
|
|
9
|
+
value?: number;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
13
|
+
export default _default;
|