diff --git a/docs/content/7.bridge/1.intro.md b/docs/content/7.bridge/1.intro.md index 828fe6e7a0..ab15fbc38c 100644 --- a/docs/content/7.bridge/1.intro.md +++ b/docs/content/7.bridge/1.intro.md @@ -28,8 +28,8 @@ ESM support | 🌙 Partial | 👍 Better | ✅ Typescript | ☑️ Opt-in | 🚧 Faster | ✅ Composition API | ⚠️ Deprecated | ✅ | ✅ Components Auto Import | ✅ | ✅ | ✅ -Auto Imports | ❌ | 🚧 | ✅ -Webpack | 4 | 4 | 5 +Auto Imports | ❌ | ✅ | ✅ +Webpack | 4 | 4 | 5 Vite | ⚠️ Partial | 🚧 Partial | 🚧 Experimental Nuxi CLI | ❌ Old | ✅ | ✅ diff --git a/packages/bridge/src/global-imports.ts b/packages/bridge/src/global-imports.ts new file mode 100644 index 0000000000..37bf3e0c2e --- /dev/null +++ b/packages/bridge/src/global-imports.ts @@ -0,0 +1,77 @@ +import { installModule, useNuxt } from '@nuxt/kit' +import globalImports from 'nuxt3/src/global-imports/module' + +// TODO: implement these: https://github.com/nuxt/framework/issues/549 +const disabled = [ + 'useMeta', + 'useAsyncData', + 'asyncData' +] + +const identifiers = { + '#app': [ + 'defineNuxtComponent', + 'useNuxtApp', + 'defineNuxtPlugin', + 'useRoute', + 'useRouter' + ], + '@vue/composition-api': [ + // lifecycle + 'onActivated', + 'onBeforeMount', + 'onBeforeUnmount', + 'onBeforeUpdate', + 'onDeactivated', + 'onErrorCaptured', + 'onMounted', + 'onServerPrefetch', + 'onUnmounted', + 'onUpdated', + + // reactivity, + 'computed', + 'customRef', + 'isReadonly', + 'isRef', + 'markRaw', + 'reactive', + 'readonly', + 'ref', + 'shallowReactive', + 'shallowReadonly', + 'shallowRef', + 'toRaw', + 'toRef', + 'toRefs', + 'triggerRef', + 'unref', + 'watch', + 'watchEffect', + + // component + 'defineComponent', + 'defineAsyncComponent', + 'getCurrentInstance', + 'h', + 'inject', + 'nextTick', + 'provide', + 'useCssModule' + ] +} + +const defaultIdentifiers = {} +for (const pkg in identifiers) { + for (const id of identifiers[pkg]) { + defaultIdentifiers[id] = pkg + } +} + +export async function setupGlobalImports () { + const nuxt = useNuxt() + nuxt.options.globalImports = nuxt.options.globalImports || {} + nuxt.options.globalImports.disabled = nuxt.options.globalImports.disabled || disabled + nuxt.options.globalImports.identifiers = Object.assign({}, defaultIdentifiers, nuxt.options.globalImports.identifiers) + await installModule(nuxt, globalImports) +} diff --git a/packages/bridge/src/module.ts b/packages/bridge/src/module.ts index 5485075e3e..d45a4f585c 100644 --- a/packages/bridge/src/module.ts +++ b/packages/bridge/src/module.ts @@ -4,6 +4,7 @@ import { setupNitroBridge } from './nitro' import { setupAppBridge } from './app' import { setupCAPIBridge } from './capi' import { setupBetterResolve } from './resolve' +import { setupGlobalImports } from './global-imports' export default defineNuxtModule({ name: 'nuxt-bridge', @@ -13,12 +14,15 @@ export default defineNuxtModule({ vite: false, app: {}, capi: {}, + globalImports: true, // TODO: Remove from 2.16 postcss8: true, swc: true, resolve: true }, async setup (opts, nuxt) { + const _require = createRequire(import.meta.url) + if (opts.nitro) { await setupNitroBridge() } @@ -31,7 +35,9 @@ export default defineNuxtModule({ } await setupCAPIBridge(opts.capi) } - const _require = createRequire(import.meta.url) + if (opts.globalImports) { + await setupGlobalImports() + } if (opts.vite) { await installModule(nuxt, _require.resolve('nuxt-vite')) } diff --git a/packages/nuxt3/src/global-imports/module.ts b/packages/nuxt3/src/global-imports/module.ts index 5e0b4a77ad..fefb75c012 100644 --- a/packages/nuxt3/src/global-imports/module.ts +++ b/packages/nuxt3/src/global-imports/module.ts @@ -8,7 +8,10 @@ export default defineNuxtModule({ name: 'global-imports', configKey: 'globalImports', defaults: { identifiers: defaultIdentifiers }, - setup ({ identifiers }, nuxt) { + setup ({ disabled = [], identifiers }, nuxt) { + for (const key of disabled) { + delete identifiers[key] + } if (nuxt.options.dev) { // Add all imports to globalThis in development mode addPluginTemplate({ diff --git a/packages/nuxt3/src/global-imports/transform.ts b/packages/nuxt3/src/global-imports/transform.ts index a195aa8a72..d9e0ca7417 100644 --- a/packages/nuxt3/src/global-imports/transform.ts +++ b/packages/nuxt3/src/global-imports/transform.ts @@ -8,11 +8,11 @@ const excludeRE = [ // defined as function /\bfunction\s*([\s\S]+?)\s*\(/g, // defined as local variable - /\b(?:const|let|var)\s*([\w\d_$]+?)\b/g + /\b(?:const|let|var)\s*(\{([\s\S]*?)\}|[\w\d_$]+?\b)/g ] const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//gm -const singlelineCommentsRE = /\/\/.*/g +const singlelineCommentsRE = /^\s*\/\/.*$/gm function stripeComments (code: string) { return code @@ -73,10 +73,17 @@ export const TransformPlugin = createUnplugin((map: IdentifierMap) => { modules[moduleName].push(name) }) + // Needed for webpack4/bridge support + const isCJSContext = code.includes('require(') + // stringify import - const imports = Object.entries(modules) - .map(([moduleName, names]) => `import { ${names.join(',')} } from '${moduleName}';`) - .join('') + const imports = !isCJSContext + ? Object.entries(modules) + .map(([moduleName, names]) => `import { ${names.join(',')} } from '${moduleName}';`) + .join('') + : Object.entries(modules) + .map(([moduleName, names]) => `const { ${names.join(',')} } = require('${moduleName}');`) + .join('') return imports + code } diff --git a/packages/nuxt3/src/global-imports/types.ts b/packages/nuxt3/src/global-imports/types.ts index 1eb9a984ec..4b4138edfc 100644 --- a/packages/nuxt3/src/global-imports/types.ts +++ b/packages/nuxt3/src/global-imports/types.ts @@ -3,4 +3,5 @@ export type Identifiers = [string, string][] export interface GlobalImportsOptions { identifiers?: IdentifierMap + disabled?: string[] } diff --git a/test/fixtures/bridge/layouts/default.vue b/test/fixtures/bridge/layouts/default.vue index 1f3e121ad5..408c4943b3 100644 --- a/test/fixtures/bridge/layouts/default.vue +++ b/test/fixtures/bridge/layouts/default.vue @@ -6,7 +6,6 @@