v2.0.0-beta.14: trigger, consent, validation, and docs bugs
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 25/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript
- Bereich
- backend, developer-experience
Rechercherichtung
The issue reports 12 independent problems across packages/script/src/module.ts, packages/script/src/runtime/utils.ts, packages/script/src/runtime/composables/useScript.ts, packages/script/src/runtime/types.ts, packages/cli/src/cli.ts, and documentation. Start by choosing one item and reproducing it with the issue’s stated Nuxt Scripts version and command or minimal app; compare the result with the linked docs and cited code. Done means a focused fix or documentation correction with a regression test for that item.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
🤖 An agent (Claude Code) filed this issue while writing the @nuxt/scripts package Skill with skilld's generate-package-skill. It reproduced each item against @nuxt/scripts 2.0.0-beta.14.
Environment: @nuxt/scripts 2.0.0-beta.14, Nuxt 4.6.0, unhead and @unhead/vue 3.4.2, Node.js 24.18.0, pnpm 12.4.2, headless Chromium. Each repro is a fresh Nuxt 4 app with modules: ['@nuxt/scripts']. Production results come from nuxt build and node .output/server/index.mjs.
Items are ordered by impact: silent wrong results, then type failures, then doc mismatches, then cleanups.
Silent wrong results
1. trigger: false on a registry entry blocks every composable call
Expected (per docs): the v0 to v1 guide says to set trigger: false when you load the script from a composable. It keeps the infrastructure and lets the composable load the script (1.v0-to-v1.md#L46). The build warning also offers trigger: false.
Observed: a composable call with no trigger never loads. Its status stays awaitingLoad, and the browser makes no request. The module copies trigger: false into runtime config (module.ts#L487), and useRegistryScript merges it into the call (utils.ts#L94).
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/scripts'],
scripts: { registry: { metaPixel: { id: '123456', trigger: false } } },
})
<!-- app/pages/index.vue -->
<script setup lang="ts">
const { status } = useScriptMetaPixel()
</script>
<template>
<p>{{ status }}</p>
</template>
Output after 6 seconds, in dev and production: awaitingLoad. { id: '123456' } with no trigger key loads.
Suggestion: drop an inherited trigger: false in composable calls, or document that trigger: false blocks them.
2. A later call without a trigger loads a consent-gated script
Expected (per docs): "Later composable calls return that script instance and do not need the options again" (1.registry-scripts.md#L158).
Observed: the later call returns the shared instance, but it also adds its own default onNuxtReady trigger. The script loads before consent.
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/scripts'],
scripts: { registry: { metaPixel: { id: '123456' } } },
})
// app/utils/consent.ts
export const scriptsConsent = useScriptTriggerConsent()
<!-- app/pages/index.vue: first call, gated -->
<script setup lang="ts">
const { status } = useScriptMetaPixel({ scriptOptions: { trigger: scriptsConsent } })
</script>
<template>
<PixelEvent />
<p>{{ scriptsConsent.consented }} {{ status }}</p>
</template>
<!-- app/components/PixelEvent.vue: second call, no options -->
<script setup lang="ts">
const { proxy } = useScriptMetaPixel()
proxy.fbq('track', 'ViewContent')
</script>
<template>
<span />
</template>
Output after 3 seconds, with no accept: consented is false and status is loaded.
Suggestion: make a later call reuse the first call's trigger, or say in the consent guide that every call needs the consent trigger.
3. Dev option validation never runs for bundled scripts
Expected (per docs): useScriptCloudflareWebAnalytics({ token: '123' }) is "skipped in development because the token is too short" (1.registry-scripts.md#L46).
Observed: in nuxt dev the script loads and sends beacons. The bundle transform rewrites the call to useScriptCloudflareWebAnalytics({ scriptInput: { src: '/_scripts/assets/78f1a00939270893.js' }, token: "123" }). Validation is skipped when scriptInput.src is set (utils.ts#L211).
<!-- app/pages/index.vue -->
<script setup lang="ts">
const { status } = useScriptCloudflareWebAnalytics({ token: '123' })
</script>
<template>
<p>{{ status }}</p>
</template>
Output in nuxt dev: loaded. With scriptOptions: { bundle: false }, the browser console logs "Skipping script cloudflareWebAnalytics due to invalid options: Invalid length: Expected >=32 but received 3", and the status stays awaitingLoad.
Suggestion: validate before the bundle transform adds scriptInput.src, or skip validation only for a user-supplied src.
4. warmupStrategy: false still preloads with the client trigger
Expected (per docs): "false disables warmup entirely" (5.nuxt-config.md#L179).
Observed: Nuxt Scripts passes false through (useScript.ts#L321-L325), but SSR still writes a preload for a client trigger. onNuxtReady with false writes none.
<!-- app/pages/index.vue -->
<script setup lang="ts">
useScript('https://example.com/warm-client.js', { trigger: 'client', warmupStrategy: false })
useScript('https://example.com/warm-ready.js', { trigger: 'onNuxtReady', warmupStrategy: false })
</script>
<template>
<p>warmup</p>
</template>
Output in the SSR HTML: <link href="https://example.com/warm-client.js" rel="preload" ... fetchpriority="low" as="script">, and no link for warm-ready.js.
Suggestion: honour false on the client path, or document the exception.
Type failures
5. The consent guide's consent.update() fails strict typecheck
Expected (per docs): the consent guide calls consent.update({ ... }) on the composable result (3.consent.md#L105).
Observed: consent is optional in UseScriptContext (types.ts#L134). At runtime it exists only on the client.
<!-- app/app.vue -->
<script setup lang="ts">
const { consent } = useScriptGoogleAnalytics({ defaultConsent: { analytics_storage: 'denied' } })
function accept() {
consent.update({ analytics_storage: 'granted' })
}
</script>
<template>
<button @click="accept">
Accept
</button>
</template>
Command: nuxt typecheck. Output: app/app.vue(4,3): error TS18048: 'consent' is possibly 'undefined'.
Suggestion: use consent?.update(...) in the guide, or type consent as present and make it a no-op on the server.
6. trigger: 'manual' in a globals tuple works but fails typecheck
Expected (per docs): the second tuple item takes useScript options (4.global.md). 'manual' is a useScript trigger, and the registry 'mock' entry uses it internally.
Observed: at runtime the global stays awaitingLoad, as expected. Typecheck rejects it, because NuxtUseScriptOptionsSerializable has no 'manual' (types.ts#L220).
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/scripts'],
scripts: { globals: { manualGlobal: [{ src: '/manual-global.js' }, { trigger: 'manual' }] } },
})
Command: nuxt typecheck. Output: Type '"manual"' is not assignable to type '"server" | "client" | "onNuxtReady" | { idleTimeout: number; } | { interaction: string[]; } | { serviceWorker: true; } | undefined'.
Suggestion: add 'manual' to the serializable trigger type.
Doc mismatches
7. The @nuxt/scripts-devtools install line cannot install
Expected (per docs): pnpm add -D @nuxt/[email protected] (2.installation.md#L34). The v1 to v2 guide names the same package (2.v1-to-v2.md#L42).
Observed: npm view @nuxt/scripts-devtools versions returns npm error code E404. No version is published.
Suggestion: publish the package at the core version, or remove the install line until it exists.
8. The missing-trigger warning is silent for env-backed fields
Expected (per docs): "A build warning fires when you supply config values without a trigger" (1.v0-to-v1.md#L35).
Observed: the warning skips fields that have an environment variable (module.ts#L676-L680). The guide's own example gets no warning.
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/scripts'],
scripts: { registry: { googleAnalytics: { id: 'G-XXXXXX' } } },
})
Command: nuxt prepare. Output: no warning. { id: 'G-XXXXXX', l: 'dl' } prints "registry.googleAnalytics: config provided without a trigger. The script will not auto-load."
Suggestion: warn for any user-supplied field, or reword the guide.
9. The install and migration commands fetch other versions
Expected (per docs): the v2 installation page and the v1 to v2 guide install and migrate to v2 (2.installation.md#L19, 2.v1-to-v2.md#L30-L31).
Observed: npm latest for @nuxt/scripts is 1.3.12, and npm latest for @nuxt/scripts-cli is 2.0.0-beta.1.
pnpm dlx [email protected] module add scripts
# ● Installing @nuxt/[email protected] as a dependency
npm view @nuxt/scripts-cli dist-tags --json
# { "latest": "2.0.0-beta.1", "beta": "2.0.0-beta.14" }
pnpm dlx [email protected] module add @nuxt/[email protected] installs beta.14 and the unhead and @unhead/vue peers.
Suggestion: pin @beta or the exact version in the v2 docs while v2 is in beta, and move the CLI latest tag to the current beta.
Cleanups
10. The migration CLI misses renamed APIs on a renamed proxy
Expected (per docs): the CLI handles "mechanical API renames" (2.v1-to-v2.md#L34).
Observed: the rename regex matches only the literal name proxy (cli.ts#L273).
<!-- app/components/Track.vue -->
<script setup lang="ts">
const { proxy: rybbit } = useScriptRybbitAnalytics()
rybbit.rybbit.pageview()
</script>
Command: pnpm dlx @nuxt/[email protected] migrate v2. Output: the file is unchanged, and no manual follow-up is listed. proxy.ttq('track', ...) in the same project was rewritten.
Suggestion: list unmatched .rybbit.pageview and ttq( calls as manual follow-ups.
11. The migration CLI drops the final newline
Observed: after pnpm dlx @nuxt/[email protected] migrate v2, the rewritten nuxt.config.ts ends without a newline (\ No newline at end of file in diff). The CLI writes generateCode(module).code as is (cli.ts#L250).
Suggestion: keep the original final newline.
12. v2 ignores a leftover scripts.security block silently
Expected (per docs): the v1 to v2 guide does not mention security, but v2 removed URL signing and the option.
Observed: scripts: { security: { autoGenerateSecret: false } } gives no warning in nuxt prepare. The migration CLI keeps the block and lists no follow-up for it.
Suggestion: warn once when scripts.security is set, and list it in the guide and as a CLI follow-up.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 585
- Forks
- 95
- Ø Merge
- 1 T. 4 Std.
- Gemergte PRs (30 T.)
- 26
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus nuxt/scripts
-
harlan-agent-wait-to-implement
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 58/100
nuxt/scripts#887 · 7 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
Loading 3rd party scripts for unused widgetEvtl. wieder frei Ein Pull Request dazu wurde ohne Merge geschlossen. Offenharlan-agent-wait-to-implement
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 55/100
nuxt/scripts#882 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
harlan-agent-wait-to-implement
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 25/100
nuxt/scripts#881 · 1 Kommentar · 1 Reaktion ·
Maintainer antworten meist innerhalb von 1 Tag
-
Dependency DashboardOffen
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 10/100
Maintainer antworten meist innerhalb von 1 Tag
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
paperclipai/paperclip#17151 ·
Maintainer antworten meist innerhalb von 1 Tag
-
needs-triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 83/100
AgoraIO-Extensions/agent-infra#3159 ·
Maintainer antworten meist innerhalb von 1 Tag
-
blocklist addition
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 66/100
MetaMask/eth-phishing-detect#304596 ·
Maintainer antworten meist innerhalb von 1 Tag
-
friction
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
kentcdodds/kody#4142 ·
-
[Bug] Statistics | Task statistics are always empty on MikroORM with MySQL or SQLiteEvtl. vergeben @NdekoCode hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
ever-co/ever-gauzy#11214 ·
Maintainer antworten meist innerhalb von 1 Tag