refactor(schema): introduce future and features namespace (#24880)

This commit is contained in:
Daniel Roe 2023-12-25 14:03:29 +00:00 committed by GitHub
parent e780bdb757
commit 32d2c99c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 77 deletions

View File

@ -124,31 +124,6 @@ Read more in `defineRouteRules` utility.
:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal-duotone"}
## inlineSSRStyles
Inlines styles when rendering HTML. This is currently available only when using Vite.
You can also pass a function that receives the path of a Vue component and returns a boolean indicating whether to inline the styles for that component.
```ts [nuxt.config.ts]
export defineNuxtConfig({
experimental: {
inlineSSRStyles: true // or a function to determine inlining
}
})
```
## noScripts
Disables rendering of Nuxt scripts and JS resource hints. Can also be configured granularly within `routeRules`.
```ts [nuxt.config.ts]
export defineNuxtConfig({
experimental: {
noScripts: true
}
})
```
## renderJsonPayloads
Allows rendering of JSON payloads with support for revivifying complex types.

View File

@ -0,0 +1,55 @@
---
title: "Features"
description: "Enable or disable optional Nuxt features to unlock new possibilities."
---
Some features of Nuxt are available on an opt-in basis, or can be disabled based on your needs.
## `features`
### inlineStyles
Inlines styles when rendering HTML. This is currently available only when using Vite.
You can also pass a function that receives the path of a Vue component and returns a boolean indicating whether to inline the styles for that component.
```ts [nuxt.config.ts]
export defineNuxtConfig({
features: {
inlineStyles: true // or a function to determine inlining
}
})
```
### noScripts
Disables rendering of Nuxt scripts and JS resource hints. Can also be configured granularly within `routeRules`.
```ts [nuxt.config.ts]
export defineNuxtConfig({
features: {
noScripts: true
}
})
```
## `future`
There is also a `future` namespace for behavior that will likely become default in a early opting-in to new features that will become default in a future (possibly major) version of the framework.
### typescriptBundlerResolution
This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting
for frameworks like Nuxt and [Vite](https://vitejs.dev/guide/performance.html#reduce-resolve-operations).
It improves type support when using modern libraries with `exports`.
See [the original TypeScript pull request](https://github.com/microsoft/TypeScript/pull/51669).
```ts [nuxt.config.ts]
export defineNuxtConfig({
future: {
typescriptBundlerResolution: true
}
})
```

View File

@ -128,7 +128,7 @@ export async function writeTypes (nuxt: Nuxt) {
jsxImportSource: 'vue',
target: 'ESNext',
module: 'ESNext',
moduleResolution: nuxt.options.experimental?.typescriptBundlerResolution ? 'Bundler' : 'Node',
moduleResolution: nuxt.options.future?.typescriptBundlerResolution || (nuxt.options.experimental as any)?.typescriptBundlerResolution ? 'Bundler' : 'Node',
skipLibCheck: true,
isolatedModules: true,
useDefineForClassFields: true,

View File

@ -51,7 +51,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
buildDir: nuxt.options.buildDir,
experimental: {
asyncContext: nuxt.options.experimental.asyncContext,
typescriptBundlerResolution: nuxt.options.experimental.typescriptBundlerResolution || nuxt.options.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler' || _nitroConfig.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler'
typescriptBundlerResolution: nuxt.options.future.typescriptBundlerResolution || nuxt.options.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler' || _nitroConfig.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler'
},
framework: {
name: 'nuxt',
@ -117,7 +117,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
// TODO: address upstream issue with defu types...?
...nuxt.options.runtimeConfig.nitro satisfies RuntimeConfig['nitro'] as any
}
} ,
},
appConfig: nuxt.options.appConfig,
appConfigFiles: nuxt.options._layers.map(
layer => resolve(layer.config.srcDir, 'app.config')
@ -207,8 +207,8 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
replace: {
'process.env.NUXT_NO_SSR': nuxt.options.ssr === false,
'process.env.NUXT_EARLY_HINTS': nuxt.options.experimental.writeEarlyHints !== false,
'process.env.NUXT_NO_SCRIPTS': !!nuxt.options.experimental.noScripts && !nuxt.options.dev,
'process.env.NUXT_INLINE_STYLES': !!nuxt.options.experimental.inlineSSRStyles,
'process.env.NUXT_NO_SCRIPTS': !!nuxt.options.features.noScripts && !nuxt.options.dev,
'process.env.NUXT_INLINE_STYLES': !!nuxt.options.features.inlineStyles,
'process.env.NUXT_JSON_PAYLOADS': !!nuxt.options.experimental.renderJsonPayloads,
'process.env.NUXT_COMPONENT_ISLANDS': !!nuxt.options.experimental.componentIslands,
'process.env.NUXT_ASYNC_CONTEXT': !!nuxt.options.experimental.asyncContext,

View File

@ -164,7 +164,7 @@ async function initNuxt (nuxt: Nuxt) {
}
// TODO: [Experimental] Avoid emitting assets when flag is enabled
if (nuxt.options.experimental.noScripts && !nuxt.options.dev) {
if (nuxt.options.features.noScripts && !nuxt.options.dev) {
nuxt.hook('build:manifest', async (manifest) => {
for (const file in manifest) {
if (manifest[file].resourceType === 'script') {

View File

@ -1,6 +1,63 @@
import { defineUntypedSchema } from 'untyped'
export default defineUntypedSchema({
future: {
/**
* This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting
* for frameworks like Nuxt and Vite.
*
* It improves type support when using modern libraries with `exports`.
*
* See https://github.com/microsoft/TypeScript/pull/51669
*/
typescriptBundlerResolution: {
async $resolve (val, get) {
// TODO: remove in v3.10
val = val ?? await get('experimental').then((e: Record<string, any>) => e?.typescriptBundlerResolution)
if (typeof val === 'boolean') { return val }
const setting = await get('typescript.tsConfig.compilerOptions.moduleResolution')
if (setting) {
return setting.toLowerCase() === 'bundler'
}
return false
}
},
},
/**
* `future` is for early opting-in to new features that will become default in a future
* (possibly major) version of the framework.
*/
features: {
/**
* Inline styles when rendering HTML (currently vite only).
*
* You can also pass a function that receives the path of a Vue component
* and returns a boolean indicating whether to inline the styles for that component.
* @type {boolean | ((id?: string) => boolean)}
*/
inlineStyles: {
async $resolve (val, get) {
// TODO: remove in v3.10
val = val ?? await get('experimental').then((e: Record<string, any>) => e?.inlineSSRStyles)
if (val === false || (await get('dev')) || (await get('ssr')) === false || (await get('builder')) === '@nuxt/webpack-builder') {
return false
}
// Enabled by default for vite prod with ssr
return val ?? true
}
},
/**
* Turn off rendering of Nuxt scripts and JS resource hints.
* You can also disable scripts more granularly within `routeRules`.
*/
noScripts: {
async $resolve (val, get) {
// TODO: remove in v3.10
return val ?? await get('experimental').then((e: Record<string, any>) => e?.noScripts) ?? false
}
},
},
experimental: {
/**
* Set to true to generate an async entry point for the Vue bundle (for module federation support).
@ -72,29 +129,6 @@ export default defineUntypedSchema({
*/
restoreState: false,
/**
* Inline styles when rendering HTML (currently vite only).
*
* You can also pass a function that receives the path of a Vue component
* and returns a boolean indicating whether to inline the styles for that component.
* @type {boolean | ((id?: string) => boolean)}
*/
inlineSSRStyles: {
async $resolve (val, get) {
if (val === false || (await get('dev')) || (await get('ssr')) === false || (await get('builder')) === '@nuxt/webpack-builder') {
return false
}
// Enabled by default for vite prod with ssr
return val ?? true
}
},
/**
* Turn off rendering of Nuxt scripts and JS resource hints.
* You can also disable scripts more granularly within `routeRules`.
*/
noScripts: false,
/** Render JSON payloads with support for revivifying complex types. */
renderJsonPayloads: true,
@ -152,27 +186,6 @@ export default defineUntypedSchema({
*/
configSchema: true,
/**
* This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting
* for frameworks like Nuxt and Vite.
*
* It improves type support when using modern libraries with `exports`.
*
* This is only not enabled by default because it could be a breaking change for some projects.
*
* See https://github.com/microsoft/TypeScript/pull/51669
*/
typescriptBundlerResolution: {
async $resolve (val, get) {
if (typeof val === 'boolean') { return val }
const setting = await get('typescript.tsConfig.compilerOptions.moduleResolution')
if (setting) {
return setting.toLowerCase() === 'bundler'
}
return false
}
},
/**
* Whether or not to add a compatibility layer for modules, plugins or user code relying on the old
* `@vueuse/head` API.

View File

@ -166,7 +166,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
srcDir: ctx.nuxt.options.srcDir,
clientCSSMap,
chunksWithInlinedCSS,
shouldInline: ctx.nuxt.options.experimental.inlineSSRStyles,
shouldInline: ctx.nuxt.options.features.inlineStyles,
components: ctx.nuxt.apps.default.components,
globalCSS: ctx.nuxt.options.css,
mode: isServer ? 'server' : 'client',

View File

@ -4,6 +4,8 @@ export default defineNuxtConfig({
experimental: {
typedPages: true,
appManifest: true,
},
future: {
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler'
},
buildDir: process.env.NITRO_BUILD_DIR,

View File

@ -191,13 +191,15 @@ export default defineNuxtConfig({
}
}
},
features: {
inlineStyles: id => !!id && !id.includes('assets.vue'),
},
experimental: {
typedPages: true,
polyfillVueUseHead: true,
respectNoSSRHeader: true,
clientFallback: true,
restoreState: true,
inlineSSRStyles: id => !!id && !id.includes('assets.vue'),
componentIslands: {
selectiveClient: true
},