@nuxt/hints 1.0.0-alpha.9 → 1.0.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.
Files changed (278) hide show
  1. package/README.md +50 -3
  2. package/dist/client/200.html +1 -1
  3. package/dist/client/404.html +1 -1
  4. package/dist/client/_nuxt/2UxHyX5q.js +1 -0
  5. package/dist/client/_nuxt/4A_iFExJ.js +1 -0
  6. package/dist/client/_nuxt/85-TOEBH.js +1 -0
  7. package/dist/client/_nuxt/B1yitclQ.js +1 -0
  8. package/dist/client/_nuxt/B7c-h3xW.js +1 -0
  9. package/dist/client/_nuxt/{BS0rITwE.js → BAtxTl2q.js} +1 -1
  10. package/dist/client/_nuxt/BBf5iR-q.js +1 -0
  11. package/dist/client/_nuxt/BERRCDM3.js +1 -0
  12. package/dist/client/_nuxt/BETggiCN.js +1 -0
  13. package/dist/client/_nuxt/BEwlwnbL.js +1 -0
  14. package/dist/client/_nuxt/BFfxhgS-.js +1 -0
  15. package/dist/client/_nuxt/BGHnOYBU.js +1 -0
  16. package/dist/client/_nuxt/BH7IYjvW.js +1 -0
  17. package/dist/client/_nuxt/BJDFO7_C.js +1 -0
  18. package/dist/client/_nuxt/BM1_JUlF.js +1 -0
  19. package/dist/client/_nuxt/BMWR74SV.js +1 -0
  20. package/dist/client/_nuxt/BQ8w6xss.js +1 -0
  21. package/dist/client/_nuxt/BR5kRUq4.js +1 -0
  22. package/dist/client/_nuxt/BRHolxvo.js +1 -0
  23. package/dist/client/_nuxt/BRZ36xJF.js +1 -0
  24. package/dist/client/_nuxt/BTJTHyun.js +1 -0
  25. package/dist/client/_nuxt/BTifaqeh.js +1 -0
  26. package/dist/client/_nuxt/BV7otONQ.js +1 -0
  27. package/dist/client/_nuxt/BVQ-GDCI.js +1 -0
  28. package/dist/client/_nuxt/BWvSN4gD.js +1 -0
  29. package/dist/client/_nuxt/{BKRej55Q.js → BY2SE5zy.js} +1 -1
  30. package/dist/client/_nuxt/BYV0-3_D.js +1 -0
  31. package/dist/client/_nuxt/BYunw83y.js +1 -0
  32. package/dist/client/_nuxt/BZvkOJ9d.js +1 -0
  33. package/dist/client/_nuxt/B_m7g4N7.js +1 -0
  34. package/dist/client/_nuxt/BcOcwvcX.js +1 -0
  35. package/dist/client/_nuxt/BcVCzyr7.js +1 -0
  36. package/dist/client/_nuxt/BdImnpbu.js +1 -0
  37. package/dist/client/_nuxt/BdnUsdx6.js +1 -0
  38. package/dist/client/_nuxt/BdyeT68K.js +1 -0
  39. package/dist/client/_nuxt/BeH2EWoN.js +1 -0
  40. package/dist/client/_nuxt/BhOHFoWU.js +1 -0
  41. package/dist/client/_nuxt/BkioyH1T.js +1 -0
  42. package/dist/client/_nuxt/BmXAJ9_W.js +1 -0
  43. package/dist/client/_nuxt/Bmn6On1c.js +1 -0
  44. package/dist/client/_nuxt/Bp6g37R7.js +1 -0
  45. package/dist/client/_nuxt/BqTXFGrv.js +1 -0
  46. package/dist/client/_nuxt/BqWnGSMi.js +1 -0
  47. package/dist/client/_nuxt/BqYA7rlc.js +1 -0
  48. package/dist/client/_nuxt/{DOJAAXAk.js → BsJUmJIm.js} +1 -1
  49. package/dist/client/_nuxt/BsS91CYL.js +1 -0
  50. package/dist/client/_nuxt/BspZqrRM.js +1 -0
  51. package/dist/client/_nuxt/BtCnVYZw.js +1 -0
  52. package/dist/client/_nuxt/BtOb2qkB.js +1 -0
  53. package/dist/client/_nuxt/BtqSS_iP.js +1 -0
  54. package/dist/client/_nuxt/BuQSe7zV.js +13 -0
  55. package/dist/client/_nuxt/Bv_4Rxtq.js +1 -0
  56. package/dist/client/_nuxt/BvzEVeQv.js +1 -0
  57. package/dist/client/_nuxt/BxgE0vQu.js +1 -0
  58. package/dist/client/_nuxt/{CuE35eZa.js → Bz59FrZb.js} +1 -1
  59. package/dist/client/_nuxt/BzTr9Aqm.js +1 -0
  60. package/dist/client/_nuxt/C-HG3fhB.js +1 -0
  61. package/dist/client/_nuxt/C-SQnVFl.js +1 -0
  62. package/dist/client/_nuxt/C0HS_06l.js +1 -0
  63. package/dist/client/_nuxt/C0hk2d4L.js +1 -0
  64. package/dist/client/_nuxt/C151Ov-r.js +1 -0
  65. package/dist/client/_nuxt/C2t-YnRu.js +1 -0
  66. package/dist/client/_nuxt/C3B-1QV4.js +1 -0
  67. package/dist/client/_nuxt/C4EeE6gA.js +1 -0
  68. package/dist/client/_nuxt/C4IJs8-o.js +1 -0
  69. package/dist/client/_nuxt/C5BYcBs_.js +1 -0
  70. package/dist/client/_nuxt/C5YyOfLZ.js +1 -0
  71. package/dist/client/_nuxt/C7zT0LnQ.js +1 -0
  72. package/dist/client/_nuxt/{CTf7BuVz.js → C8XNfCrI.js} +1 -1
  73. package/dist/client/_nuxt/C8lEn-DE.js +1 -0
  74. package/dist/client/_nuxt/C98Dy4si.js +1 -0
  75. package/dist/client/_nuxt/C9XAeP06.js +1 -0
  76. package/dist/client/_nuxt/CDx5xZoG.js +1 -0
  77. package/dist/client/_nuxt/CEL-wOlO.js +1 -0
  78. package/dist/client/_nuxt/CENFIVCM.js +1 -0
  79. package/dist/client/_nuxt/CEu0bR-o.js +1 -0
  80. package/dist/client/_nuxt/CF10PKvl.js +1 -0
  81. package/dist/client/_nuxt/CG8Ifv2g.js +1 -0
  82. package/dist/client/_nuxt/CHLpvVh8.js +1 -0
  83. package/dist/client/_nuxt/CHM0blh-.js +1 -0
  84. package/dist/client/_nuxt/CJc9bBzg.js +1 -0
  85. package/dist/client/_nuxt/CKIfxQSi.js +1 -0
  86. package/dist/client/_nuxt/CLZrNe3w.js +1 -0
  87. package/dist/client/_nuxt/CLxacb5B.js +1 -0
  88. package/dist/client/_nuxt/CO1LY3CK.js +1 -0
  89. package/dist/client/_nuxt/COcwbKMJ.js +1 -0
  90. package/dist/client/_nuxt/COkxafJQ.js +1 -0
  91. package/dist/client/_nuxt/CSXwinHm.js +1 -0
  92. package/dist/client/_nuxt/CXDyekYo.js +3 -0
  93. package/dist/client/_nuxt/CYpkKp66.js +1 -0
  94. package/dist/client/_nuxt/{BFRyJUvr.js → CZ1OMT3Z.js} +1 -1
  95. package/dist/client/_nuxt/CZhp0h8q.js +1 -0
  96. package/dist/client/_nuxt/CbFg5uaA.js +1 -0
  97. package/dist/client/_nuxt/CeAyd5Ju.js +1 -0
  98. package/dist/client/_nuxt/CeZK1NFH.js +1 -0
  99. package/dist/client/_nuxt/CenWIFCC.js +1 -0
  100. package/dist/client/_nuxt/Cg-RD9OK.js +1 -0
  101. package/dist/client/_nuxt/CgK0fS9t.js +1 -0
  102. package/dist/client/_nuxt/CgrjxMR_.js +6 -0
  103. package/dist/client/_nuxt/ChMvpjG-.js +1 -0
  104. package/dist/client/_nuxt/CkByrt1z.js +1 -0
  105. package/dist/client/_nuxt/CklMAg4u.js +1 -0
  106. package/dist/client/_nuxt/Cl_HNi2c.js +4 -0
  107. package/dist/client/_nuxt/Cn7AkR1O.js +1 -0
  108. package/dist/client/_nuxt/CnnmHF94.js +1 -0
  109. package/dist/client/_nuxt/CnsnAmq5.js +1 -0
  110. package/dist/client/_nuxt/Co6uUVPk.js +1 -0
  111. package/dist/client/_nuxt/CoDkCxhg.js +1 -0
  112. package/dist/client/_nuxt/CpOuai2O.js +1 -0
  113. package/dist/client/_nuxt/Cq5zzVJU.js +1 -0
  114. package/dist/client/_nuxt/CquLrc37.js +1 -0
  115. package/dist/client/_nuxt/CsfeWuGM.js +1 -0
  116. package/dist/client/_nuxt/CuPHTKiy.js +1 -0
  117. package/dist/client/_nuxt/CwoSXNpI.js +1 -0
  118. package/dist/client/_nuxt/CxGSJlkm.js +1 -0
  119. package/dist/client/_nuxt/CxLEBnE3.js +1 -0
  120. package/dist/client/_nuxt/Cz2AlsmD.js +1 -0
  121. package/dist/client/_nuxt/CzTSHFRz.js +1 -0
  122. package/dist/client/_nuxt/D0YGMca9.js +1 -0
  123. package/dist/client/_nuxt/D17OF-Vu.js +1 -0
  124. package/dist/client/_nuxt/D1j8_8rp.js +1 -0
  125. package/dist/client/_nuxt/D3lLCCz7.js +1 -0
  126. package/dist/client/_nuxt/D5-asLiD.js +1 -0
  127. package/dist/client/_nuxt/D53aC0YG.js +1 -0
  128. package/dist/client/_nuxt/D7o27uSR.js +1 -0
  129. package/dist/client/_nuxt/D82EKSYY.js +1 -0
  130. package/dist/client/_nuxt/D82vCrfD.js +1 -0
  131. package/dist/client/_nuxt/D8_7TLub.js +1 -0
  132. package/dist/client/_nuxt/D8l8udqQ.js +1 -0
  133. package/dist/client/_nuxt/D93ZcfNL.js +1 -0
  134. package/dist/client/_nuxt/D97Zzqfu.js +1 -0
  135. package/dist/client/_nuxt/DDvzSYfr.js +1 -0
  136. package/dist/client/_nuxt/DFQXde-d.js +1 -0
  137. package/dist/client/_nuxt/DFXneXwc.js +1 -0
  138. package/dist/client/_nuxt/DHCkPAjA.js +1 -0
  139. package/dist/client/_nuxt/DM8c43g1.js +1 -0
  140. package/dist/client/_nuxt/DMLP1f5n.js +24 -0
  141. package/dist/client/_nuxt/DMzUqQB5.js +1 -0
  142. package/dist/client/_nuxt/{DOHcV6MR.js → DO_IqDaw.js} +1 -1
  143. package/dist/client/_nuxt/DPOp833l.js +1 -0
  144. package/dist/client/_nuxt/DRJZaHtK.js +1 -0
  145. package/dist/client/_nuxt/DRg8JJMk.js +1 -0
  146. package/dist/client/_nuxt/DV7GczEv.js +1 -0
  147. package/dist/client/_nuxt/DVFEvuxE.js +1 -0
  148. package/dist/client/_nuxt/DVxCFoDh.js +1 -0
  149. package/dist/client/_nuxt/DWrx1Km3.js +1 -0
  150. package/dist/client/_nuxt/DXmwc3jG.js +1 -0
  151. package/dist/client/_nuxt/DXvB9xmW.js +1 -0
  152. package/dist/client/_nuxt/DZf3V79B.js +1 -0
  153. package/dist/client/_nuxt/DZu-aV2c.js +1 -0
  154. package/dist/client/_nuxt/D_Q5rh1f.js +1 -0
  155. package/dist/client/_nuxt/Da5cRb03.js +1 -0
  156. package/dist/client/_nuxt/Dd19v3D-.js +1 -0
  157. package/dist/client/_nuxt/DdkO51Og.js +1 -0
  158. package/dist/client/_nuxt/Df6bDoY_.js +1 -0
  159. package/dist/client/_nuxt/DhmSosst.js +1 -0
  160. package/dist/client/_nuxt/DjAJT7YJ.js +1 -0
  161. package/dist/client/_nuxt/DkFqJrB1.js +1 -0
  162. package/dist/client/_nuxt/DkwncUOv.js +1 -0
  163. package/dist/client/_nuxt/Dpen1YoG.js +1 -0
  164. package/dist/client/_nuxt/Dph4kLrZ.js +1 -0
  165. package/dist/client/_nuxt/{BHYWC4mf.js → Dq5iEy-J.js} +1 -1
  166. package/dist/client/_nuxt/DsOJ9woJ.js +1 -0
  167. package/dist/client/_nuxt/DsumFeuD.js +1 -0
  168. package/dist/client/_nuxt/{BMheLZQI.js → DuO5kjlf.js} +1 -1
  169. package/dist/client/_nuxt/DvAmuSmV.js +1 -0
  170. package/dist/client/_nuxt/DyxjwDmM.js +1 -0
  171. package/dist/client/_nuxt/Dzze3sRP.js +1 -0
  172. package/dist/client/_nuxt/FtFNcQmh.js +1 -0
  173. package/dist/client/_nuxt/IF9eRakj.js +1 -0
  174. package/dist/client/_nuxt/IeuSbFQv.js +1 -0
  175. package/dist/client/_nuxt/LCb0JLof.js +1 -0
  176. package/dist/client/_nuxt/P80f7IUj.js +1 -0
  177. package/dist/client/_nuxt/Pmp26Uib.js +1 -0
  178. package/dist/client/_nuxt/QIJgUcNo.js +1 -0
  179. package/dist/client/_nuxt/RxLv4Mw1.js +1 -0
  180. package/dist/client/_nuxt/VOosw3JB.js +1 -0
  181. package/dist/client/_nuxt/Ve4PFQV2.js +1 -0
  182. package/dist/client/_nuxt/YqXBG_HV.js +1 -0
  183. package/dist/client/_nuxt/_H4v1dQx.js +1 -0
  184. package/dist/client/_nuxt/_ykCGR6B.js +1 -0
  185. package/dist/client/_nuxt/{BZWgH84o.js → a9uSpr3S.js} +1 -1
  186. package/dist/client/_nuxt/bCR0ucgS.js +1 -0
  187. package/dist/client/_nuxt/builds/latest.json +1 -1
  188. package/dist/client/_nuxt/builds/meta/99ecb9ec-79bf-4090-9942-9ce383dac370.json +1 -0
  189. package/dist/client/_nuxt/dwOrl1Do.js +1 -0
  190. package/dist/client/_nuxt/{entry.bXb283Sw.css → entry.D5OyC1nV.css} +1 -1
  191. package/dist/client/_nuxt/eo99z4R2.js +1 -0
  192. package/dist/client/_nuxt/error-404.B6ZMX39t.css +1 -0
  193. package/dist/client/_nuxt/error-500.dS86tDkg.css +1 -0
  194. package/dist/client/_nuxt/fKv21gyL.js +1 -0
  195. package/dist/client/_nuxt/gcz8RCvz.js +1 -0
  196. package/dist/client/_nuxt/hydration.BczHrsb5.css +1 -0
  197. package/dist/client/_nuxt/k_qm7-4y.js +1 -0
  198. package/dist/client/_nuxt/lXgVvXCa.js +1 -0
  199. package/dist/client/_nuxt/mWjccvbQ.js +1 -0
  200. package/dist/client/_nuxt/mjskCLCv.js +1 -0
  201. package/dist/client/_nuxt/n2N0HUVH.js +1 -0
  202. package/dist/client/_nuxt/oH_c3LbQ.js +1 -0
  203. package/dist/client/_nuxt/rGO070M0.js +1 -0
  204. package/dist/client/_nuxt/rZm6bMo-.js +1 -0
  205. package/dist/client/_nuxt/u5AG7uiY.js +1 -0
  206. package/dist/client/_nuxt/uYugtg8r.js +1 -0
  207. package/dist/client/_nuxt/vGWfd6FD.js +1 -0
  208. package/dist/client/_nuxt/yv6CvBhz.js +1 -0
  209. package/dist/client/component-lazy-load/index.html +1 -1
  210. package/dist/client/html-validate/index.html +1 -0
  211. package/dist/client/hydration/index.html +1 -1
  212. package/dist/client/index.html +1 -1
  213. package/dist/client/third-party-scripts/index.html +1 -1
  214. package/dist/client/web-vitals/index.html +1 -1
  215. package/dist/module.d.mts +5 -1
  216. package/dist/module.json +1 -1
  217. package/dist/module.mjs +75 -37
  218. package/dist/runtime/core/components/nuxt-island.d.ts +136 -1
  219. package/dist/runtime/core/features.d.ts +6 -0
  220. package/dist/runtime/core/features.js +17 -0
  221. package/dist/runtime/core/plugins/features.client.d.ts +2 -0
  222. package/dist/runtime/core/plugins/features.client.js +16 -0
  223. package/dist/runtime/core/plugins/vue-tracer-state.client.d.ts +1 -1
  224. package/dist/runtime/core/types.d.ts +17 -0
  225. package/dist/runtime/core/types.js +0 -0
  226. package/dist/runtime/feature-options.d.ts +8 -0
  227. package/dist/runtime/feature-options.js +0 -0
  228. package/dist/runtime/html-validate/handlers/delete.d.ts +1 -0
  229. package/dist/runtime/html-validate/handlers/delete.js +17 -0
  230. package/dist/runtime/html-validate/handlers/get.d.ts +2 -0
  231. package/dist/runtime/html-validate/handlers/get.js +5 -0
  232. package/dist/runtime/html-validate/handlers/nitro-handlers.plugin.d.ts +3 -0
  233. package/dist/runtime/html-validate/handlers/nitro-handlers.plugin.js +36 -0
  234. package/dist/runtime/html-validate/nitro.plugin.d.ts +3 -0
  235. package/dist/runtime/html-validate/nitro.plugin.js +54 -0
  236. package/dist/runtime/html-validate/plugin.client.d.ts +2 -0
  237. package/dist/runtime/html-validate/plugin.client.js +28 -0
  238. package/dist/runtime/html-validate/storage.d.ts +1 -0
  239. package/dist/runtime/html-validate/storage.js +2 -0
  240. package/dist/runtime/html-validate/types.d.ts +8 -0
  241. package/dist/runtime/html-validate/types.js +0 -0
  242. package/dist/runtime/html-validate/utils.d.ts +3 -0
  243. package/dist/runtime/html-validate/utils.js +12 -0
  244. package/dist/runtime/hydration/composables.js +15 -13
  245. package/dist/runtime/hydration/plugin.client.d.ts +1 -1
  246. package/dist/runtime/hydration/utils.d.ts +1 -0
  247. package/dist/runtime/hydration/utils.js +2 -0
  248. package/dist/runtime/lazy-load/plugin.client.d.ts +1 -1
  249. package/dist/runtime/lazy-load/plugin.client.js +3 -3
  250. package/dist/runtime/lazy-load/utils.d.ts +1 -0
  251. package/dist/runtime/lazy-load/utils.js +2 -0
  252. package/dist/runtime/logger.d.ts +2 -0
  253. package/dist/runtime/logger.js +6 -0
  254. package/dist/runtime/third-party-scripts/plugin.client.d.ts +1 -1
  255. package/dist/runtime/third-party-scripts/plugin.client.js +28 -8
  256. package/dist/runtime/third-party-scripts/types.d.ts +6 -0
  257. package/dist/runtime/third-party-scripts/types.js +0 -0
  258. package/dist/runtime/third-party-scripts/utils.d.ts +1 -0
  259. package/dist/runtime/third-party-scripts/utils.js +2 -0
  260. package/dist/runtime/types.d.ts +12 -0
  261. package/dist/runtime/web-vitals/plugin.client.d.ts +1 -1
  262. package/dist/runtime/web-vitals/plugin.client.js +124 -94
  263. package/dist/runtime/web-vitals/types.d.ts +4 -0
  264. package/dist/runtime/web-vitals/types.js +0 -0
  265. package/dist/runtime/web-vitals/utils.d.ts +1 -0
  266. package/dist/runtime/web-vitals/utils.js +2 -0
  267. package/package.json +21 -17
  268. package/dist/client/_nuxt/16LZ-2rN.js +0 -1
  269. package/dist/client/_nuxt/BOWvZIQC.js +0 -4
  270. package/dist/client/_nuxt/BY53PIN5.js +0 -1
  271. package/dist/client/_nuxt/BYo9cb9R.js +0 -36
  272. package/dist/client/_nuxt/D7xuZOu8.js +0 -1
  273. package/dist/client/_nuxt/DaNrdrhj.js +0 -1
  274. package/dist/client/_nuxt/GiOWC8es.js +0 -6
  275. package/dist/client/_nuxt/builds/meta/9cd25584-d8cd-4e50-8973-949eec6b2524.json +0 -1
  276. package/dist/client/_nuxt/error-404.LspKb3Ne.css +0 -1
  277. package/dist/client/_nuxt/error-500.B_qDdXYW.css +0 -1
  278. package/dist/client/_nuxt/hydration.CLUG10u4.css +0 -1
@@ -2,11 +2,13 @@ import type { VNode, Ref } from 'vue'
2
2
  import type { LCPMetricWithAttribution, INPMetricWithAttribution, CLSMetricWithAttribution } from 'web-vitals/attribution'
3
3
  import type { HydrationMismatchPayload, LocalHydrationMismatch } from './hydration/types'
4
4
  import type { DirectImportInfo, LazyHydrationState } from './lazy-load/composables'
5
+ import type { Features } from './core/types'
5
6
 
6
7
  declare global {
7
8
  interface Window {
8
9
  __hints_TPC_start_time: number
9
10
  __hints_TPC_saveTime: (script: HTMLScriptElement, startTime?: number) => void
11
+ __hints_html_validation?: import('./html-validate/types').HtmlValidateReport
10
12
  }
11
13
  interface HTMLScriptElement {
12
14
  __hints_TPC_start_time?: number
@@ -36,6 +38,11 @@ declare module '#app' {
36
38
  interface NuxtApp {
37
39
  __tracerOverlay: typeof import('vite-plugin-vue-tracer/client/overlay')
38
40
  __tracerRecord: typeof import('vite-plugin-vue-tracer/client/record')
41
+ hints: {
42
+ config: {
43
+ features: Features
44
+ }
45
+ }
39
46
  }
40
47
 
41
48
  interface NuxtPayload {
@@ -52,6 +59,7 @@ declare module '#app' {
52
59
  element: HTMLScriptElement
53
60
  loaded: boolean
54
61
  }[]>
62
+ htmlValidateResult?: import('./html-validate/types').HtmlValidateReport
55
63
  }
56
64
  }
57
65
  }
@@ -61,6 +69,10 @@ declare module 'nitropack' {
61
69
  // Core hints hooks
62
70
  'hints:sse:setup': (context: import('./core/server/types').HintsSseContext) => void
63
71
 
72
+ // html-validate hooks
73
+ 'hints:html-validate:report': (report: import('./html-validate/types').HtmlValidateReport) => void
74
+ 'hints:html-validate:deleted': (id: string) => void
75
+
64
76
  // Hydration hooks
65
77
  'hints:hydration:mismatch': (payload: HydrationMismatchPayload) => void
66
78
  'hints:hydration:cleared': (payload: { id: string[] }) => void
@@ -9,5 +9,5 @@ declare global {
9
9
  value?: number;
10
10
  }
11
11
  }
12
- declare const _default: any;
12
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
13
13
  export default _default;
@@ -1,20 +1,33 @@
1
1
  import { defineNuxtPlugin, useNuxtApp } from "#imports";
2
2
  import { onINP, onLCP, onCLS } from "web-vitals/attribution";
3
3
  import { defu } from "defu";
4
- import { ref } from "vue";
5
- import { logger } from "../logger.js";
4
+ import { shallowRef } from "vue";
5
+ import { logger } from "./utils.js";
6
+ import { getFeatureOptions } from "../core/features.js";
6
7
  function isImgElement(element) {
7
8
  return element instanceof Element && element.tagName === "IMG";
8
9
  }
10
+ function isIgnoredDomain(src, ignoreDomains) {
11
+ if (ignoreDomains.length === 0) return false;
12
+ try {
13
+ const url = new URL(src);
14
+ return ignoreDomains.some((domain) => url.hostname === domain || url.hostname.endsWith(`.${domain}`));
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
9
19
  export default defineNuxtPlugin({
10
20
  name: "nuxt-hints:performance",
11
21
  setup() {
12
22
  const nuxtApp = useNuxtApp();
23
+ const opts = getFeatureOptions("webVitals") ?? {};
24
+ const trackedMetrics = opts.trackedMetrics ?? ["LCP", "INP", "CLS"];
25
+ const ignoreDomains = opts.ignoreDomains ?? [];
13
26
  nuxtApp.payload.__hints = defu(nuxtApp.payload.__hints, {
14
27
  webvitals: {
15
- lcp: ref([]),
16
- inp: ref([]),
17
- cls: ref([])
28
+ lcp: shallowRef([]),
29
+ inp: shallowRef([]),
30
+ cls: shallowRef([])
18
31
  }
19
32
  });
20
33
  nuxtApp.hook("hints:webvitals:sync", (webvitals) => {
@@ -23,113 +36,130 @@ export default defineNuxtPlugin({
23
36
  webvitals.cls.value = [...nuxtApp.payload.__hints.webvitals.cls.value];
24
37
  });
25
38
  nuxtApp.hook("app:mounted", () => {
26
- onINP((metric) => {
27
- if (metric.rating === "good") {
28
- return;
29
- }
30
- logger.info(
31
- "[web-vitals] INP Metric: ",
32
- metric
33
- );
34
- nuxtApp.payload.__hints.webvitals.inp.value.push(metric);
35
- nuxtApp.callHook("hints:webvitals:inp", metric);
36
- }, {
37
- reportAllChanges: true
38
- });
39
- onLCP((metric) => {
40
- if (metric.rating === "good") {
41
- return;
42
- }
43
- logger.info(
44
- `[web-vitals] LCP Metric: `,
45
- metric
46
- );
47
- nuxtApp.payload.__hints.webvitals.lcp.value.push(metric);
48
- nuxtApp.callHook("hints:webvitals:lcp", metric);
49
- for (const performanceEntry of metric.entries) {
50
- if (!performanceEntry.element || !isImgElement(performanceEntry.element)) {
51
- continue;
39
+ if (trackedMetrics.includes("INP")) {
40
+ onINP((metric) => {
41
+ if (metric.rating === "good") {
42
+ return;
52
43
  }
53
- if (performanceEntry.element.attributes?.getNamedItem("loading")?.value === "lazy") {
54
- logger.warn(
55
- '[performance] LCP Element should not have `loading="lazy"` \n\n Learn more: https://web.dev/optimize-lcp/#optimize-the-priority-the-resource-is-given'
56
- );
44
+ logger.info(
45
+ "[web-vitals] INP Metric: ",
46
+ metric
47
+ );
48
+ nuxtApp.payload.__hints.webvitals.inp.value.push(metric);
49
+ nuxtApp.callHook("hints:webvitals:inp", metric);
50
+ }, {
51
+ reportAllChanges: true
52
+ });
53
+ }
54
+ if (trackedMetrics.includes("LCP")) {
55
+ onLCP((metric) => {
56
+ if (metric.rating === "good") {
57
+ return;
57
58
  }
58
- if (hasImageFormat(performanceEntry.element.src)) {
59
- if (!performanceEntry.element.src.includes("webp") || !performanceEntry.element.src.includes("avif")) {
59
+ logger.info(
60
+ `[web-vitals] LCP Metric: `,
61
+ metric
62
+ );
63
+ nuxtApp.payload.__hints.webvitals.lcp.value.push(metric);
64
+ nuxtApp.callHook("hints:webvitals:lcp", metric);
65
+ for (const performanceEntry of metric.entries) {
66
+ if (!performanceEntry.element || !isImgElement(performanceEntry.element)) {
67
+ continue;
68
+ }
69
+ if (isIgnoredDomain(performanceEntry.element.src, ignoreDomains)) {
70
+ continue;
71
+ }
72
+ if (performanceEntry.element.attributes?.getNamedItem("loading")?.value === "lazy") {
60
73
  logger.warn(
61
- "[performance] LCP Element can be served in a next gen format like `webp` or `avif` \n\n Learn more: https://web.dev/choose-the-right-image-format/ \n\n Use: https://image.nuxt.com/usage/nuxt-img#format"
74
+ '[performance] LCP Element should not have `loading="lazy"` \n\n Learn more: https://web.dev/optimize-lcp/#optimize-the-priority-the-resource-is-given'
62
75
  );
63
76
  }
64
- }
65
- if (performanceEntry.element.fetchPriority !== "high") {
66
- logger.warn(
67
- '[performance] LCP Element can have `fetchPriority="high"` to load as soon as possible \n\n Learn more: https://web.dev/optimize-lcp/#optimize-the-priority-the-resource-is-given'
68
- );
69
- }
70
- if (!performanceEntry.element.attributes.getNamedItem("height") || !performanceEntry.element.attributes.getNamedItem("width")) {
71
- logger.warn(
72
- "[performance] Images should have `width` and `height` sizes set \n\n Learn more: https://web.dev/optimize-cls/#images-without-dimensions \n\n Use: https://image.nuxt.com/usage/nuxt-img#width-height"
73
- );
74
- }
75
- if (performanceEntry.startTime > 2500) {
76
- logger.warn(
77
- `[performance] LCP Element loaded in ${performanceEntry.startTime} miliseconds. Good result is below 2500 miliseconds
77
+ if (hasImageFormat(performanceEntry.element.src)) {
78
+ if (!performanceEntry.element.src.includes("webp") && !performanceEntry.element.src.includes("avif")) {
79
+ logger.warn(
80
+ "[performance] LCP Element can be served in a next gen format like `webp` or `avif` \n\n Learn more: https://web.dev/choose-the-right-image-format/ \n\n Use: https://image.nuxt.com/usage/nuxt-img#format"
81
+ );
82
+ }
83
+ }
84
+ if (performanceEntry.element.fetchPriority !== "high") {
85
+ logger.warn(
86
+ '[performance] LCP Element can have `fetchPriority="high"` to load as soon as possible \n\n Learn more: https://web.dev/optimize-lcp/#optimize-the-priority-the-resource-is-given'
87
+ );
88
+ }
89
+ if (!performanceEntry.element.hasAttribute("width") || !performanceEntry.element.hasAttribute("height")) {
90
+ logger.warn(
91
+ "[performance] Images should have `width` and `height` sizes set \n\n Learn more: https://web.dev/optimize-cls/#images-without-dimensions \n\n Use: https://image.nuxt.com/usage/nuxt-img#width-height"
92
+ );
93
+ }
94
+ if (performanceEntry.startTime > 2500) {
95
+ logger.warn(
96
+ `[performance] LCP Element loaded in ${performanceEntry.startTime} miliseconds. Good result is below 2500 miliseconds
78
97
 
79
98
  Learn more: https://web.dev/lcp/#what-is-a-good-lcp-score`
80
- );
99
+ );
100
+ }
101
+ if (!isElementPreloaded(performanceEntry.element.src)) {
102
+ logger.warn(
103
+ "[performance] LCP Element can be preloaded in `head` to improve load time \n\n Learn more: https://web.dev/optimize-lcp/#optimize-when-the-resource-is-discovered \n\n Use: https://image.nuxt.com/usage/nuxt-img#preload"
104
+ );
105
+ }
81
106
  }
82
- if (!isElementPreloaded(performanceEntry.element.src)) {
83
- logger.warn(
84
- "[performance] LCP Element can be preloaded in `head` to improve load time \n\n Learn more: https://web.dev/optimize-lcp/#optimize-when-the-resource-is-discovered \n\n Use: https://image.nuxt.com/usage/nuxt-img#preload"
85
- );
107
+ }, {
108
+ reportAllChanges: true
109
+ });
110
+ }
111
+ if (trackedMetrics.includes("CLS")) {
112
+ onCLS((metric) => {
113
+ if (metric.rating === "good") {
114
+ return;
86
115
  }
87
- }
88
- }, {
89
- reportAllChanges: true
90
- });
91
- onCLS((metric) => {
92
- if (metric.rating === "good") {
93
- return;
94
- }
95
- logger.info(
96
- "[web-vitals] CLS Metric: ",
97
- metric
98
- );
99
- nuxtApp.callHook(
100
- "hints:webvitals:cls",
101
- metric
102
- );
103
- nuxtApp.payload.__hints.webvitals.cls.value.push(metric);
104
- for (const entry of metric.entries) {
105
- const performanceEntry = entry;
106
- if (!performanceEntry.sources?.[0]) return;
107
- const sourceElement = performanceEntry.sources?.[0].node;
108
- if (!sourceElement || sourceElement.parentElement?.className.includes("nuxt-devtools")) return;
109
116
  logger.info(
110
- "[performance] Potential CLS Element: ",
111
- sourceElement
117
+ "[web-vitals] CLS Metric: ",
118
+ metric
112
119
  );
113
- if ((performanceEntry.value ?? 0) > 0.1) {
114
- logger.warn(
115
- `[performance] CLS was ${performanceEntry.value}. Good result is below 0.1
120
+ nuxtApp.callHook(
121
+ "hints:webvitals:cls",
122
+ metric
123
+ );
124
+ nuxtApp.payload.__hints.webvitals.cls.value.push(metric);
125
+ for (const entry of metric.entries) {
126
+ const performanceEntry = entry;
127
+ if (!performanceEntry.sources?.[0]) continue;
128
+ const sourceElement = performanceEntry.sources?.[0].node;
129
+ if (!sourceElement || sourceElement.parentElement?.className.includes("nuxt-devtools")) continue;
130
+ logger.info(
131
+ "[performance] Potential CLS Element: ",
132
+ sourceElement
133
+ );
134
+ if ((performanceEntry.value ?? 0) > 0.1) {
135
+ logger.warn(
136
+ `[performance] CLS was ${performanceEntry.value}. Good result is below 0.1
116
137
 
117
138
  Learn more: https://web.dev/articles/cls#what-is-a-good-cls-score`
118
- );
119
- }
120
- if (isImgElement(sourceElement) && (!sourceElement.attributes.getNamedItem("height") || !sourceElement.attributes.getNamedItem("width"))) {
121
- logger.warn(
122
- "[performance] Images should have `width` and `height` sizes set \n\n Learn more: https://web.dev/optimize-cls/#images-without-dimensions \n\n Use: https://image.nuxt.com/usage/nuxt-img#width-height"
123
- );
139
+ );
140
+ }
141
+ if (isImgElement(sourceElement) && (!sourceElement.attributes.getNamedItem("height") || !sourceElement.attributes.getNamedItem("width"))) {
142
+ logger.warn(
143
+ "[performance] Images should have `width` and `height` sizes set \n\n Learn more: https://web.dev/optimize-cls/#images-without-dimensions \n\n Use: https://image.nuxt.com/usage/nuxt-img#width-height"
144
+ );
145
+ }
124
146
  }
125
- }
126
- });
147
+ }, {
148
+ reportAllChanges: true
149
+ });
150
+ }
127
151
  });
128
152
  }
129
153
  });
154
+ const IMAGE_FORMATS = ["avif", "jpg", "jpeg", "png", "webp"];
130
155
  const hasImageFormat = (src) => {
131
- const imageFormats = ["avif", "jpg", "jpeg", "png", "webp"];
132
- return imageFormats.some((format) => src.includes(format));
156
+ let pathname;
157
+ try {
158
+ pathname = new URL(src, window.location.href).pathname;
159
+ } catch {
160
+ pathname = src;
161
+ }
162
+ return IMAGE_FORMATS.some((format) => pathname.includes(format));
133
163
  };
134
164
  const isElementPreloaded = (src) => {
135
165
  return Array.from(document.head.childNodes).filter(
@@ -0,0 +1,4 @@
1
+ export interface WebVitalsFeatureOptions {
2
+ ignoreDomains?: string[];
3
+ trackedMetrics?: Array<'LCP' | 'INP' | 'CLS'>;
4
+ }
File without changes
@@ -1,3 +1,4 @@
1
+ export declare const logger: import("consola").ConsolaInstance;
1
2
  export declare enum ImagePerformanceIssueType {
2
3
  LazyAttrOnLCPElement = 0,
3
4
  ImgFormat = 1,
@@ -1,3 +1,5 @@
1
+ import { createHintsLogger } from "../logger.js";
2
+ export const logger = createHintsLogger("webVitals");
1
3
  export var ImagePerformanceIssueType = /* @__PURE__ */ ((ImagePerformanceIssueType2) => {
2
4
  ImagePerformanceIssueType2[ImagePerformanceIssueType2["LazyAttrOnLCPElement"] = 0] = "LazyAttrOnLCPElement";
3
5
  ImagePerformanceIssueType2[ImagePerformanceIssueType2["ImgFormat"] = 1] = "ImgFormat";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/hints",
3
- "version": "1.0.0-alpha.9",
3
+ "version": "1.0.1",
4
4
  "description": "Nuxt module that shows hints for aspects of your application such as Performance, Security, and more!",
5
5
  "repository": "https://github.com/nuxt/hints",
6
6
  "homepage": "https://github.com/nuxt/hints",
@@ -21,44 +21,48 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@nuxt/devtools-kit": "^3.2.1",
24
+ "@nuxt/devtools-kit": "^3.2.3",
25
25
  "@nuxt/kit": "^4.3.1",
26
26
  "consola": "^3.4.2",
27
- "h3": "^1.15.5",
27
+ "defu": "^6.1.4",
28
+ "devalue": "^5.6.4",
29
+ "h3": "^1.15.6",
30
+ "html-validate": "^10.11.2",
28
31
  "knitwork": "^1.3.0",
29
32
  "magic-string": "^0.30.21",
30
33
  "nitropack": "^2.13.1",
31
- "oxc-parser": "^0.115.0",
34
+ "oxc-parser": "^0.120.0",
35
+ "prettier": "^3.8.1",
32
36
  "sirv": "^3.0.2",
33
37
  "unplugin": "^3.0.0",
34
38
  "unstorage": "^1.17.4",
35
39
  "valibot": "^1.2.0",
36
- "vite-plugin-vue-tracer": "^1.2.0",
40
+ "vite-plugin-vue-tracer": "^1.3.0",
37
41
  "web-vitals": "^5.1.0"
38
42
  },
39
43
  "devDependencies": {
40
- "@nuxt/devtools": "^3.2.1",
41
- "@nuxt/devtools-ui-kit": "^3.2.1",
42
- "@nuxt/eslint": "^1.15.1",
44
+ "@nuxt/devtools": "^3.2.3",
45
+ "@nuxt/devtools-ui-kit": "^3.2.3",
46
+ "@nuxt/eslint": "^1.15.2",
43
47
  "@nuxt/icon": "^2.2.1",
44
48
  "@nuxt/module-builder": "^1.0.2",
45
49
  "@nuxt/schema": "^4.3.1",
46
50
  "@nuxt/test-utils": "^4.0.0",
47
- "@shikijs/transformers": "^3.22.0",
48
- "@types/node": "^24.10.13",
51
+ "@shikijs/transformers": "^3.23.0",
52
+ "@types/node": "^24.12.0",
49
53
  "@vue/test-utils": "^2.4.6",
50
54
  "changelogen": "^0.6.2",
51
55
  "diff": "^8.0.3",
52
- "eslint": "^10.0.1",
56
+ "eslint": "^10.0.3",
53
57
  "get-port-please": "^3.2.0",
54
- "happy-dom": "^20.7.0",
55
- "pkg-pr-new": "0.0.63",
58
+ "happy-dom": "^20.8.4",
59
+ "pkg-pr-new": "0.0.66",
56
60
  "rimraf": "^6.1.3",
57
- "sass-embedded": "^1.97.3",
58
- "shiki": "^3.22.0",
61
+ "sass-embedded": "^1.98.0",
62
+ "shiki": "^3.23.0",
59
63
  "shiki-transformer-fold": "^0.2.0",
60
- "vitest": "^4.0.18",
61
- "@nuxt/hints": "^1.0.0-alpha.9"
64
+ "vitest": "^4.1.0",
65
+ "@nuxt/hints": "^1.0.1"
62
66
  },
63
67
  "scripts": {
64
68
  "client:build": "nuxi generate client",
@@ -1 +0,0 @@
1
- import{_ as g}from"./CTf7BuVz.js";import L from"./GiOWC8es.js";import{_ as w}from"./BZWgH84o.js";import{_ as z}from"./BFRyJUvr.js";import{g as N,e as v,o as n,c as a,b as c,w as i,k as _,F as p,x,d as u,a as t,l as $,t as r,n as C,L as B}from"./BOWvZIQC.js";import"./BKRej55Q.js";import"./D7xuZOu8.js";const A={grid:"","gap-4":"","p-4":""},E={class:"flex items-center justify-between"},I={class:"text-sm font-semibold"},S={class:"w-full text-sm"},R={class:"py-2"},T={class:"text-xs bg-neutral-100 dark:bg-neutral-800 px-1.5 py-0.5 rounded"},D={class:"text-xs text-neutral-400 ml-1"},H={class:"py-2 text-xs text-neutral-500 dark:text-neutral-400 truncate max-w-48"},V={class:"py-2 text-xs text-neutral-500 dark:text-neutral-400 truncate max-w-48"},F={key:1,class:"text-neutral-500 dark:text-neutral-400"},K=N({__name:"component-lazy-load",setup(O){const d=v(),m=C(()=>d.$lazyLoadHints.value.filter(s=>s.state.directImports.some(e=>!e.rendered)));async function f(s){d.$lazyLoadHints.value=d.$lazyLoadHints.value.filter(e=>e.id!==s),$fetch(new URL(`${B}/${s}`,window.location.origin).href,{method:"DELETE"})}return(s,e)=>{const y=g,b=L,h=w,k=z;return n(),a("div",A,[c(y,{type:"info"},{default:i(()=>[...e[0]||(e[0]=[u(" These components are statically imported but were not rendered during SSR or initial hydration. Consider using the ",-1),t("code",null,"Lazy",-1),u(" prefix or ",-1),t("code",null,"defineAsyncComponent",-1),u(" to reduce the initial bundle size. ",-1)])]),_:1}),_(m).length>0?(n(!0),a(p,{key:0},x(_(m),l=>(n(),$(k,{key:l.id,class:"p4"},{default:i(()=>[t("header",E,[t("span",I,r(l.route),1),c(h,{title:"Remove",size:"small",quaternary:"",onClick:o=>f(l.id)},{default:i(()=>[c(b,{name:"material-symbols:delete-outline",class:"text-lg"})]),_:1},8,["onClick"])]),t("table",S,[e[1]||(e[1]=t("thead",null,[t("tr",{class:"border-b border-neutral-200 dark:border-neutral-700 text-left text-neutral-500 dark:text-neutral-400"},[t("th",{class:"pb-2 font-medium"}," Component "),t("th",{class:"pb-2 font-medium"}," Import Source "),t("th",{class:"pb-2 font-medium"}," Imported By ")])],-1)),t("tbody",null,[(n(!0),a(p,null,x(l.state.directImports.filter(o=>!o.rendered),o=>(n(),a("tr",{key:o.componentName,class:"border-b border-neutral-100 dark:border-neutral-800 last:border-b-0"},[t("td",R,[t("code",T,r(o.componentName),1),t("span",D,"→ Lazy"+r(o.componentName),1)]),t("td",H,r(o.importSource),1),t("td",V,r(o.importedBy),1)]))),128))])])]),_:2},1024))),128)):(n(),a("div",F," No lazy-load suggestions found. Navigate pages in your app to collect data. "))])}}});export{K as default};