mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(nuxt): prompt to install nuxt/scripts
on usage (#27010)
Co-authored-by: Harlan Wilton <harlan@harlanzw.com>
This commit is contained in:
parent
7e3b613421
commit
589b4037c1
102
packages/nuxt/src/app/composables/script-stubs.ts
Normal file
102
packages/nuxt/src/app/composables/script-stubs.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import type { UseScriptInput } from '@unhead/vue'
|
||||||
|
import { createError } from './error'
|
||||||
|
|
||||||
|
function renderStubMessage (name: string) {
|
||||||
|
const message = `\`${name}\` is provided by @nuxt/scripts. Check your console to install it or run 'npx nuxi@latest module add @nuxt/scripts' to install it.`
|
||||||
|
if (import.meta.client) {
|
||||||
|
throw createError({
|
||||||
|
fatal: true,
|
||||||
|
statusCode: 500,
|
||||||
|
statusMessage: message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScript<T extends Record<string | symbol, any>> (input: UseScriptInput, options?: Record<string, unknown>) {
|
||||||
|
renderStubMessage('useScript')
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useElementScriptTrigger (...args: unknown[]) {
|
||||||
|
renderStubMessage('useElementScriptTrigger')
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useConsentScriptTrigger (...args: unknown[]) {
|
||||||
|
renderStubMessage('useConsentScriptTrigger')
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useAnalyticsPageEvent (...args: unknown[]) {
|
||||||
|
renderStubMessage('useAnalyticsPageEvent')
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptGoogleAnalytics (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptGoogleAnalytics')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptPlausibleAnalytics (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptPlausibleAnalytics')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptCloudflareWebAnalytics (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptCloudflareWebAnalytics')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptFathomAnalytics (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptFathomAnalytics')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptMatomoAnalytics (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptMatomoAnalytics')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptGoogleTagManager (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptGoogleTagManager')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptSegment (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptSegment')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptFacebookPixel (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptFacebookPixel')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptXPixel (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptXPixel')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptIntercom (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptIntercom')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptHotjar (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptHotjar')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptStripe (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptStripe')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptLemonSqueezy (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptLemonSqueezy')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptVimeoPlayer (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptVimeoPlayer')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptYouTubeIframe (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptYouTubeIframe')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptGoogleMaps (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptGoogleMaps')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptNpm (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptNpm')
|
||||||
|
}
|
@ -20,6 +20,7 @@ import importsModule from '../imports/module'
|
|||||||
|
|
||||||
import { distDir, pkgDir } from '../dirs'
|
import { distDir, pkgDir } from '../dirs'
|
||||||
import { version } from '../../package.json'
|
import { version } from '../../package.json'
|
||||||
|
import { scriptsStubsPreset } from '../imports/presets'
|
||||||
import { ImportProtectionPlugin, nuxtImportProtections } from './plugins/import-protection'
|
import { ImportProtectionPlugin, nuxtImportProtections } from './plugins/import-protection'
|
||||||
import type { UnctxTransformPluginOptions } from './plugins/unctx'
|
import type { UnctxTransformPluginOptions } from './plugins/unctx'
|
||||||
import { UnctxTransformPlugin } from './plugins/unctx'
|
import { UnctxTransformPlugin } from './plugins/unctx'
|
||||||
@ -125,6 +126,14 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Prompt to install `@nuxt/scripts` if user has configured it
|
||||||
|
// @ts-expect-error scripts types are not present as the module is not installed
|
||||||
|
if (nuxt.options.scripts) {
|
||||||
|
if (!nuxt.options._modules.some(m => m === '@nuxt/scripts' || m === '@nuxt/scripts-nightly')) {
|
||||||
|
await import('../core/features').then(({ installNuxtModule }) => installNuxtModule('@nuxt/scripts'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add plugin normalization plugin
|
// Add plugin normalization plugin
|
||||||
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
addBuildPlugin(RemovePluginMetadataPlugin(nuxt))
|
||||||
|
|
||||||
@ -550,6 +559,12 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options._modules.some(m => m === '@nuxt/scripts' || m === '@nuxt/scripts-nightly')) {
|
||||||
|
options.imports = defu(options.imports, {
|
||||||
|
presets: [scriptsStubsPreset],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Nuxt Webpack Builder is currently opt-in
|
// Nuxt Webpack Builder is currently opt-in
|
||||||
if (options.builder === '@nuxt/webpack-builder') {
|
if (options.builder === '@nuxt/webpack-builder') {
|
||||||
if (!await import('./features').then(r => r.ensurePackageInstalled('@nuxt/webpack-builder', {
|
if (!await import('./features').then(r => r.ensurePackageInstalled('@nuxt/webpack-builder', {
|
||||||
|
@ -111,6 +111,33 @@ const granularAppPresets: InlinePreset[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const scriptsStubsPreset = {
|
||||||
|
imports: [
|
||||||
|
'useConsentScriptTrigger',
|
||||||
|
'useAnalyticsPageEvent',
|
||||||
|
'useElementScriptTrigger',
|
||||||
|
'useScript',
|
||||||
|
'useScriptGoogleAnalytics',
|
||||||
|
'useScriptPlausibleAnalytics',
|
||||||
|
'useScriptCloudflareWebAnalytics',
|
||||||
|
'useScriptFathomAnalytics',
|
||||||
|
'useScriptMatomoAnalytics',
|
||||||
|
'useScriptGoogleTagManager',
|
||||||
|
'useScriptSegment',
|
||||||
|
'useScriptFacebookPixel',
|
||||||
|
'useScriptXPixel',
|
||||||
|
'useScriptIntercom',
|
||||||
|
'useScriptHotjar',
|
||||||
|
'useScriptStripe',
|
||||||
|
'useScriptLemonSqueezy',
|
||||||
|
'useScriptVimeoPlayer',
|
||||||
|
'useScriptYouTubeIframe',
|
||||||
|
'useScriptGoogleMaps',
|
||||||
|
'useScriptNpm',
|
||||||
|
],
|
||||||
|
from: '#app/composables/script-stubs',
|
||||||
|
} satisfies InlinePreset
|
||||||
|
|
||||||
// This is a separate preset as we'll swap these out for import from `vue-router` itself in `pages` module
|
// This is a separate preset as we'll swap these out for import from `vue-router` itself in `pages` module
|
||||||
const routerPreset = defineUnimportPreset({
|
const routerPreset = defineUnimportPreset({
|
||||||
imports: ['onBeforeRouteLeave', 'onBeforeRouteUpdate'],
|
imports: ['onBeforeRouteLeave', 'onBeforeRouteUpdate'],
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createUnplugin } from 'unplugin'
|
import { createUnplugin } from 'unplugin'
|
||||||
import type { Unimport } from 'unimport'
|
import type { Unimport } from 'unimport'
|
||||||
import { normalize } from 'pathe'
|
import { normalize } from 'pathe'
|
||||||
|
import { tryUseNuxt } from '@nuxt/kit'
|
||||||
import type { ImportsOptions } from 'nuxt/schema'
|
import type { ImportsOptions } from 'nuxt/schema'
|
||||||
import { isJS, isVue } from '../core/utils'
|
import { isJS, isVue } from '../core/utils'
|
||||||
|
|
||||||
@ -37,7 +38,11 @@ export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ct
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { s } = await ctx.injectImports(code, id, { autoImport: options.autoImport && !isNodeModule })
|
const { s, imports } = await ctx.injectImports(code, id, { autoImport: options.autoImport && !isNodeModule })
|
||||||
|
if (imports.some(i => i.from === '#app/composables/script-stubs') && tryUseNuxt()?.options.test === false) {
|
||||||
|
import('../core/features').then(({ installNuxtModule }) => installNuxtModule('@nuxt/scripts'))
|
||||||
|
}
|
||||||
|
|
||||||
if (s.hasChanged()) {
|
if (s.hasChanged()) {
|
||||||
return {
|
return {
|
||||||
code: s.toString(),
|
code: s.toString(),
|
||||||
|
Loading…
Reference in New Issue
Block a user