Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

v2.0.0-beta.14: trigger, consent, validation, and docs bugs

Đang mở
#949 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
25/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
typescript

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

harlan-agent-ready-to-spec

🤖 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.

Ngôn ngữ chính
TypeScript
Star
585
Fork
95
Merge trung bình
1 ngày 3 giờ
Pull request đã merge (30 ngày)
42

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của nuxt/scripts

Tất cả issue của nuxt/scripts

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.