Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vite,webpack): tree-shakable import.meta.* build flags #22428

Merged
merged 15 commits into from Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/1.getting-started/7.state-management.md
Expand Up @@ -74,12 +74,12 @@ export const useLocale = () => useState<string>('locale', () => useDefaultLocale

export const useDefaultLocale = (fallback = 'en-US') => {
const locale = ref(fallback)
if (process.server) {
if (import.meta.server) {
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
if (reqLocale) {
locale.value = reqLocale
}
} else if (process.client) {
} else if (import.meta.client) {
const navLang = navigator.language
if (navLang) {
locale.value = navLang
Expand Down
6 changes: 3 additions & 3 deletions docs/2.guide/2.directory-structure/1.middleware.md
Expand Up @@ -125,12 +125,12 @@ However, if you want to avoid this behaviour you can do so:
```js
export default defineNuxtRouteMiddleware(to => {
// skip middleware on server
if (process.server) return
if (import.meta.server) return
// skip middleware on client side entirely
if (process.client) return
if (import.meta.client) return
// or only skip middleware on initial client load
const nuxtApp = useNuxtApp()
if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
```

Expand Down
2 changes: 1 addition & 1 deletion docs/2.guide/2.directory-structure/1.plugins.md
Expand Up @@ -62,7 +62,7 @@ export default defineNuxtPlugin({
```

::alert
If you are using an object-syntax plugin, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
If you are using an object-syntax plugin, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
::

## Plugin Registration Order
Expand Down
2 changes: 1 addition & 1 deletion docs/2.guide/3.going-further/10.runtime-config.md
Expand Up @@ -94,7 +94,7 @@ The entire runtime config is available on the server-side, but it is read-only t
<script setup lang="ts">
const config = useRuntimeConfig()
console.log('Runtime config:', config)
if (process.server) {
if (import.meta.server) {
console.log('API secret:', config.apiSecret)
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion docs/2.guide/3.going-further/8.custom-routing.md
Expand Up @@ -138,6 +138,6 @@ import { createMemoryHistory } from 'vue-router'

// https://router.vuejs.org/api/interfaces/routeroptions.html
export default <RouterConfig> {
history: base => process.client ? createMemoryHistory(base) : null /* default */
history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
}
```
6 changes: 3 additions & 3 deletions docs/3.api/1.composables/use-nuxt-app.md
Expand Up @@ -45,7 +45,7 @@ export default defineNuxtPlugin((nuxtApp) => {
})
nuxtApp.hook('vue:error', (..._args) => {
console.log('vue:error')
// if (process.client) {
// if (import.meta.client) {
// console.log(..._args)
// }
})
Expand Down Expand Up @@ -105,7 +105,7 @@ When accessing the same `payload.data` from [ssrcontext](#ssrcontext), you can a
export const useColor = () => useState<string>('color', () => 'pink')

export default defineNuxtPlugin((nuxtApp) => {
if (process.server) {
if (import.meta.server) {
const color = useColor()
}
})
Expand Down Expand Up @@ -137,7 +137,7 @@ export default defineComponent({
setup (_props, { slots, emit }) {
const nuxtApp = useNuxtApp()
onErrorCaptured((err) => {
if (process.client && !nuxtApp.isHydrating) {
if (import.meta.client && !nuxtApp.isHydrating) {
// ...
}
})
Expand Down
1 change: 0 additions & 1 deletion packages/kit/src/template.ts
Expand Up @@ -128,7 +128,6 @@ export async function writeTypes (nuxt: Nuxt) {
noEmit: true,
resolveJsonModule: true,
allowSyntheticDefaultImports: true,
types: ['node'],
paths: {}
},
include: [
Expand Down
3 changes: 3 additions & 0 deletions packages/nuxt/package.json
Expand Up @@ -122,6 +122,9 @@
"peerDependenciesMeta": {
"@parcel/watcher": {
"optional": true
},
"@types/node": {
"optional": true
}
},
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/compat/idle-callback.ts
@@ -1,6 +1,6 @@
// Polyfills for Safari support
// https://caniuse.com/requestidlecallback
export const requestIdleCallback: Window['requestIdleCallback'] = process.server
export const requestIdleCallback: Window['requestIdleCallback'] = import.meta.server
? (() => {}) as any
: (globalThis.requestIdleCallback || ((cb) => {
const start = Date.now()
Expand All @@ -11,6 +11,6 @@ export const requestIdleCallback: Window['requestIdleCallback'] = process.server
return setTimeout(() => { cb(idleDeadline) }, 1)
}))

export const cancelIdleCallback: Window['cancelIdleCallback'] = process.server
export const cancelIdleCallback: Window['cancelIdleCallback'] = import.meta.server
? (() => {}) as any
: (globalThis.cancelIdleCallback || ((id) => { clearTimeout(id) }))
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/components/dev-only.ts
Expand Up @@ -3,7 +3,7 @@ import { defineComponent } from 'vue'
export default defineComponent({
name: 'DevOnly',
setup (_, props) {
if (process.dev) {
if (import.meta.dev) {
return () => props.slots.default?.()
}
return () => props.slots.fallback?.()
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/components/nuxt-error-boundary.ts
Expand Up @@ -12,7 +12,7 @@ export default defineComponent({
const nuxtApp = useNuxtApp()

onErrorCaptured((err, target, info) => {
if (process.client && !nuxtApp.isHydrating) {
if (import.meta.client && !nuxtApp.isHydrating) {
emit('error', err)
nuxtApp.hooks.callHook('vue:error', err, target, info)
error.value = err
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/components/nuxt-error-page.vue
Expand Up @@ -36,11 +36,11 @@ const is404 = statusCode === 404

const statusMessage = _error.statusMessage ?? (is404 ? 'Page Not Found' : 'Internal Server Error')
const description = _error.message || _error.toString()
const stack = process.dev && !is404 ? _error.description || `<pre>${stacktrace}</pre>` : undefined
const stack = import.meta.dev && !is404 ? _error.description || `<pre>${stacktrace}</pre>` : undefined

// TODO: Investigate side-effect issue with imports
const _Error404 = defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-404.vue').then(r => r.default || r))
const _Error = process.dev
const _Error = import.meta.dev
? defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-dev.vue').then(r => r.default || r))
: defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-500.vue').then(r => r.default || r))

Expand Down
28 changes: 14 additions & 14 deletions packages/nuxt/src/app/components/nuxt-island.ts
Expand Up @@ -23,7 +23,7 @@ const SLOTNAME_RE = /nuxt-ssr-slot-name="([^"]*)"/g
const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g

let id = 0
const getId = process.client ? () => (id++).toString() : randomUUID
const getId = import.meta.client ? () => (id++).toString() : randomUUID

export default defineComponent({
name: 'NuxtIsland',
Expand Down Expand Up @@ -54,15 +54,15 @@ export default defineComponent({
const instance = getCurrentInstance()!
const event = useRequestEvent()
// TODO: remove use of `$fetch.raw` when nitro 503 issues on windows dev server are resolved
const eventFetch = process.server ? event.fetch : process.dev ? $fetch.raw : globalThis.fetch
const eventFetch = import.meta.server ? event.fetch : import.meta.dev ? $fetch.raw : globalThis.fetch
const mounted = ref(false)
onMounted(() => { mounted.value = true })

function setPayload (key: string, result: NuxtIslandResponse) {
nuxtApp.payload.data[key] = {
__nuxt_island: {
key,
...(process.server && process.env.prerender)
...(import.meta.server && import.meta.prerender)
? {}
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } }
},
Expand All @@ -71,7 +71,7 @@ export default defineComponent({
}

const ssrHTML = ref<string>('')
if (process.client) {
if (import.meta.client) {
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
if (renderedHTML && nuxtApp.isHydrating) {
setPayload(`${props.name}_${hashId.value}`, {
Expand Down Expand Up @@ -111,19 +111,19 @@ export default defineComponent({

const url = remoteComponentIslands && props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}`

if (process.server && process.env.prerender) {
if (import.meta.server && import.meta.prerender) {
// Hint to Nitro to prerender the island component
appendResponseHeader(event, 'x-nitro-prerender', url)
}
// TODO: Validate response
// $fetch handles the app.baseURL in dev
const r = await eventFetch(withQuery(process.dev && process.client ? url : joinURL(config.app.baseURL ?? '', url), {
const r = await eventFetch(withQuery(import.meta.dev && import.meta.client ? url : joinURL(config.app.baseURL ?? '', url), {
...props.context,
props: props.props ? JSON.stringify(props.props) : undefined
}))
const result = process.server || !process.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
// TODO: support passing on more headers
if (process.server && process.env.prerender) {
if (import.meta.server && import.meta.prerender) {
const hints = r.headers.get('x-nitro-prerender')
if (hints) {
appendResponseHeader(event, 'x-nitro-prerender', hints)
Expand All @@ -149,7 +149,7 @@ export default defineComponent({
})
key.value++
error.value = null
if (process.client) {
if (import.meta.client) {
// must await next tick for Teleport to work correctly with static node re-rendering
await nextTick()
}
Expand All @@ -165,13 +165,13 @@ export default defineComponent({
})
}

if (process.client) {
if (import.meta.client) {
watch(props, debounce(() => fetchComponent(), 100))
}

if (process.client && !nuxtApp.isHydrating && props.lazy) {
if (import.meta.client && !nuxtApp.isHydrating && props.lazy) {
fetchComponent()
} else if (process.server || !nuxtApp.isHydrating) {
} else if (import.meta.server || !nuxtApp.isHydrating) {
await fetchComponent()
}

Expand All @@ -182,10 +182,10 @@ export default defineComponent({
const nodes = [createVNode(Fragment, {
key: key.value
}, [h(createStaticVNode(html.value || '<div></div>', 1))])]
if (uid.value && (mounted.value || nuxtApp.isHydrating || process.server)) {
if (uid.value && (mounted.value || nuxtApp.isHydrating || import.meta.server)) {
for (const slot in slots) {
if (availableSlots.value.includes(slot)) {
nodes.push(createVNode(Teleport, { to: process.client ? `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, {
nodes.push(createVNode(Teleport, { to: import.meta.client ? `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, {
default: () => (slotProps.value[slot] ?? [undefined]).map((data: any) => slots[slot]?.(data))
}))
}
Expand Down
8 changes: 4 additions & 4 deletions packages/nuxt/src/app/components/nuxt-layout.ts
Expand Up @@ -57,7 +57,7 @@ export default defineComponent({

return () => {
const hasLayout = layout.value && layout.value in layouts
if (process.dev && layout.value && !hasLayout && layout.value !== 'default') {
if (import.meta.dev && layout.value && !hasLayout && layout.value !== 'default') {
console.warn(`Invalid layout \`${layout.value}\` selected.`)
}

Expand Down Expand Up @@ -112,7 +112,7 @@ const LayoutProvider = defineComponent({
}

let vnode: VNode | undefined
if (process.dev && process.client) {
if (import.meta.dev && import.meta.client) {
onMounted(() => {
nextTick(() => {
if (['#comment', '#text'].includes(vnode?.el?.nodeName)) {
Expand All @@ -128,14 +128,14 @@ const LayoutProvider = defineComponent({

return () => {
if (!name || (typeof name === 'string' && !(name in layouts))) {
if (process.dev && process.client && props.hasTransition) {
if (import.meta.dev && import.meta.client && props.hasTransition) {
vnode = context.slots.default?.() as VNode | undefined
return vnode
}
return context.slots.default?.()
}

if (process.dev && process.client && props.hasTransition) {
if (import.meta.dev && import.meta.client && props.hasTransition) {
vnode = h(
// @ts-expect-error seems to be an issue in vue types
LayoutLoader,
Expand Down
12 changes: 6 additions & 6 deletions packages/nuxt/src/app/components/nuxt-link.ts
Expand Up @@ -51,7 +51,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
const componentName = options.componentName || 'NuxtLink'

const checkPropConflicts = (props: NuxtLinkProps, main: keyof NuxtLinkProps, sub: keyof NuxtLinkProps): void => {
if (process.dev && props[main] !== undefined && props[sub] !== undefined) {
if (import.meta.dev && props[main] !== undefined && props[sub] !== undefined) {
console.warn(`[${componentName}] \`${main}\` and \`${sub}\` cannot be used together. \`${sub}\` will be ignored.`)
}
}
Expand Down Expand Up @@ -198,10 +198,10 @@ export function defineNuxtLink (options: NuxtLinkOptions) {

// Prefetching
const prefetched = ref(false)
const el = process.server ? undefined : ref<HTMLElement | null>(null)
const elRef = process.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }
const el = import.meta.server ? undefined : ref<HTMLElement | null>(null)
const elRef = import.meta.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }

if (process.client) {
if (import.meta.client) {
checkPropConflicts(props, 'prefetch', 'noPrefetch')
const shouldPrefetch = props.prefetch !== false && props.noPrefetch !== true && props.target !== '_blank' && !isSlowConnection()
if (shouldPrefetch) {
Expand Down Expand Up @@ -329,7 +329,7 @@ type CallbackFn = () => void
type ObserveFn = (element: Element, callback: CallbackFn) => () => void

function useObserver (): { observe: ObserveFn } | undefined {
if (process.server) { return }
if (import.meta.server) { return }

const nuxtApp = useNuxtApp()
if (nuxtApp._observer) {
Expand Down Expand Up @@ -370,7 +370,7 @@ function useObserver (): { observe: ObserveFn } | undefined {
}

function isSlowConnection () {
if (process.server) { return }
if (import.meta.server) { return }

// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
const cn = (navigator as any).connection as { saveData: boolean, effectiveType: string } | null
Expand Down
6 changes: 3 additions & 3 deletions packages/nuxt/src/app/components/nuxt-loading-indicator.ts
Expand Up @@ -101,7 +101,7 @@ function useLoadingIndicator (opts: {
function start () {
clear()
progress.value = 0
if (opts.throttle && process.client) {
if (opts.throttle && import.meta.client) {
_throttle = setTimeout(() => {
isLoading.value = true
_startTimer()
Expand Down Expand Up @@ -129,7 +129,7 @@ function useLoadingIndicator (opts: {

function _hide () {
clear()
if (process.client) {
if (import.meta.client) {
setTimeout(() => {
isLoading.value = false
setTimeout(() => { progress.value = 0 }, 400)
Expand All @@ -138,7 +138,7 @@ function useLoadingIndicator (opts: {
}

function _startTimer () {
if (process.client) {
if (import.meta.client) {
_timer = setInterval(() => { _increase(step.value) }, 100)
}
}
Expand Down
14 changes: 7 additions & 7 deletions packages/nuxt/src/app/components/nuxt-root.vue
Expand Up @@ -16,37 +16,37 @@
import AppComponent from '#build/app-component.mjs'
import ErrorComponent from '#build/error-component.mjs'

const IslandRenderer = process.server
const IslandRenderer = import.meta.server
? defineAsyncComponent(() => import('./island-renderer').then(r => r.default || r))
: () => null

const nuxtApp = useNuxtApp()
const onResolve = nuxtApp.deferHydration()

const url = process.server ? nuxtApp.ssrContext.url : window.location.pathname
const SingleRenderer = process.test && process.dev && process.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')
.then(r => r.default(process.server ? url : window.location.href)))
const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname
const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')
.then(r => r.default(import.meta.server ? url : window.location.href)))

Check warning

Code scanning / CodeQL

Client-side cross-site scripting (experimental) Medium Experimental

(Experimental) This may be a cross-site scripting vulnerability due to
a user-provided value
. Identified using machine learning.

// Inject default route (outside of pages) as active route
provide(PageRouteSymbol, useRoute())

// vue:setup hook
const results = nuxtApp.hooks.callHookWith(hooks => hooks.map(hook => hook()), 'vue:setup')
if (process.dev && results && results.some(i => i && 'then' in i)) {
if (import.meta.dev && results && results.some(i => i && 'then' in i)) {
console.error('[nuxt] Error in `vue:setup`. Callbacks must be synchronous.')
}

// error handling
const error = useError()
onErrorCaptured((err, target, info) => {
nuxtApp.hooks.callHook('vue:error', err, target, info).catch(hookError => console.error('[nuxt] Error in `vue:error` hook', hookError))
if (process.server || (isNuxtError(err) && (err.fatal || err.unhandled))) {
if (import.meta.server || (isNuxtError(err) && (err.fatal || err.unhandled))) {
const p = nuxtApp.runWithContext(() => showError(err))
onServerPrefetch(() => p)
return false // suppress error from breaking render
}
})

// Component islands context
const { islandContext } = process.server && nuxtApp.ssrContext
const islandContext = import.meta.server && nuxtApp.ssrContext.islandContext
</script>