rsnext/packages/next/server/config-schema.ts

647 lines
14 KiB
TypeScript
Raw Normal View History

import { NextConfig } from './config'
import type { JSONSchemaType } from 'ajv'
import { VALID_LOADERS } from '../shared/lib/image-config'
const configSchema = {
type: 'object',
additionalProperties: false,
properties: {
amp: {
additionalProperties: false,
properties: {
canonicalBase: {
minLength: 1,
type: 'string',
},
},
type: 'object',
},
analyticsId: {
type: 'string',
},
assetPrefix: {
minLength: 1,
type: 'string',
},
basePath: {
type: 'string',
},
cleanDistDir: {
type: 'boolean',
},
compiler: {
additionalProperties: false,
properties: {
emotion: {
oneOf: [
{
type: 'boolean',
},
{
type: 'object',
additionalProperties: false,
properties: {
sourceMap: {
type: 'boolean',
},
autoLabel: {
type: 'string',
enum: ['always', 'dev-only', 'never'],
},
labelFormat: {
type: 'string',
minLength: 1,
},
},
},
] as any,
},
reactRemoveProperties: {
oneOf: [
{
type: 'boolean',
},
{
type: 'object',
additionalProperties: false,
properties: {
properties: {
type: 'array',
items: {
type: 'string',
},
},
},
},
] as any,
},
relay: {
type: 'object',
},
removeConsole: {
oneOf: [
{
type: 'boolean',
},
{
type: 'object',
additionalProperties: false,
properties: {
exclude: {
type: 'array',
items: {
type: 'string',
minLength: 1,
},
},
},
},
] as any,
},
styledComponents: {
oneOf: [
{
type: 'boolean',
},
{
type: 'object',
additionalProperties: false,
properties: {
displayName: {
type: 'boolean',
},
topLevelImportPaths: {
oneOf: [
{ type: 'boolean' },
{
type: 'array',
items: {
type: 'string',
minLength: 1,
},
},
],
},
ssr: {
type: 'boolean',
},
fileName: {
type: 'boolean',
},
meaninglessFileNames: {
oneOf: [
{ type: 'boolean' },
{
type: 'array',
items: {
type: 'string',
minLength: 1,
},
},
],
},
minify: {
type: 'boolean',
},
transpileTemplateLiterals: {
type: 'boolean',
},
namespace: {
type: 'string',
minLength: 1,
},
pure: {
type: 'boolean',
},
cssProp: {
type: 'boolean',
},
},
},
] as any,
},
},
type: 'object',
},
compress: {
type: 'boolean',
},
crossOrigin: {
oneOf: [
false,
{
enum: ['anonymous', 'use-credentials'],
type: 'string',
},
], // automatic typing does not like enum
} as any,
devIndicators: {
additionalProperties: false,
properties: {
buildActivity: {
type: 'boolean',
},
buildActivityPosition: {
// automatic typing does not like enum
enum: ['bottom-left', 'bottom-right', 'top-left', 'top-right'] as any,
type: 'string',
},
},
type: 'object',
},
distDir: {
minLength: 1,
type: 'string',
nullable: true,
},
env: {
type: 'object',
},
eslint: {
additionalProperties: false,
properties: {
dirs: {
items: {
minLength: 1,
type: 'string',
},
type: 'array',
},
ignoreDuringBuilds: {
type: 'boolean',
},
},
type: 'object',
},
excludeDefaultMomentLocales: {
type: 'boolean',
},
experimental: {
additionalProperties: false,
properties: {
adjustFontFallbacks: {
type: 'boolean',
},
amp: {
additionalProperties: false,
properties: {
optimizer: {
type: 'object',
},
skipValidation: {
type: 'boolean',
},
validator: {
type: 'string',
},
},
type: 'object',
},
appDir: {
type: 'boolean',
},
browsersListForSwc: {
type: 'boolean',
},
cpus: {
type: 'number',
},
craCompat: {
type: 'boolean',
},
disableOptimizedLoading: {
type: 'boolean',
},
disablePostcssPresetEnv: {
type: 'boolean',
},
esmExternals: {
oneOf: [
{
type: 'boolean',
},
{
const: 'loose',
},
] as any,
},
externalDir: {
type: 'boolean',
},
feat: add `experimental.fallbackNodePolyfills` flag (#39248) For historical reasons, Next.js has been falling back to polyfill certain Node.js APIs in the browser. `webpack` itself stopped doing it, and so should Next.js. This might unexpectedly break some packages in the ecosystem though, so it is being introduced as an experimental flag. These imports will now throw a `Module not found` error and the package maintainer should make sure that the library isn't relying on these Node.js APIs when the package is meant for browser usage. Let's take a look at a common example, the `crypto` API, which can be imported as `import crypto from "crypto"` but [should already be available in browsers](https://caniuse.com/cryptography). Until now, Next.js has fallen back to use a polyfilled version for the import, which resulted in a bundle-size increase. ```js import crypto from 'crypto' import { useEffect } from 'react' export default function Page() { useEffect(() => { console.log(crypto) }, []) } ``` it imports `crypto`, which currently resolves to [`crypto-browserify`](https://www.npmjs.com/package/crypto-browserify). So the bundle will include `crypto-browserify` as well: ```sh Page Size First Load JS ┌ ○ / 131 kB 213 kB # <-- └ ○ /404 194 B 82.2 kB + First Load JS shared by all 82 kB ├ chunks/framework-bcc2dc0ea27ab0c6.js 45.1 kB ├ chunks/main-dc2421aef72299b4.js 35.4 kB ├ chunks/pages/_app-a85935458980c5c2.js 708 B └ chunks/webpack-9b312e20a4e32339.js 836 B ``` Here, we can just remove the import, as we are [safely accessing](https://nextjs.org/docs/migrating/from-create-react-app#safely-accessing-web-apis) the [Crypto Web API](https://caniuse.com/cryptography): ```diff - import crypto from 'crypto' import { useEffect } from 'react' export default function Page() { useEffect(() => { console.log(crypto) }, []) } ``` Which will reduce the bundle size: ```sh Page Size First Load JS ┌ ○ / 269 B 82.2 kB # <-- └ ○ /404 194 B 82.1 kB + First Load JS shared by all 81.9 kB ├ chunks/framework-bcc2dc0ea27ab0c6.js 45.1 kB ├ chunks/main-dc2421aef72299b4.js 35.4 kB ├ chunks/pages/_app-a85935458980c5c2.js 708 B └ chunks/webpack-fd82975a6094609f.js 727 B ``` This is harder to detect if the `crypto` import is in a third-party package though. By setting `experimental: { fallbackNodePolyfills: false }`, Next.js will now fail at build-time and should show where the unnecessary import comes from, so the developer can reach out to the package maintainer to fix this issue. Note: There might be differences between the living standard and some of these older polyfills, so you have to make sure your code works well without the polyfilled version. Related feedback: https://twitter.com/lfredolo/status/1539608666026000384
2022-08-27 01:11:57 +02:00
fallbackNodePolyfills: {
type: 'boolean',
},
forceSwcTransforms: {
type: 'boolean',
},
fullySpecified: {
type: 'boolean',
},
gzipSize: {
type: 'boolean',
},
incrementalCacheHandlerPath: {
type: 'string',
},
isrFlushToDisk: {
type: 'boolean',
},
isrMemoryCacheSize: {
type: 'number',
},
largePageDataBytes: {
type: 'number',
},
legacyBrowsers: {
type: 'boolean',
},
manualClientBasePath: {
type: 'boolean',
},
modularizeImports: {
type: 'object',
},
newNextLinkBehavior: {
type: 'boolean',
},
nextScriptWorkers: {
type: 'boolean',
},
optimizeCss: {
oneOf: [
{
type: 'boolean',
},
{
type: 'object',
},
] as any,
},
optimisticClientCache: {
type: 'boolean',
},
outputFileTracingRoot: {
minLength: 1,
type: 'string',
},
pageEnv: {
type: 'boolean',
},
profiling: {
type: 'boolean',
},
proxyTimeout: {
minimum: 0,
type: 'number',
},
runtime: {
// automatic typing doesn't like enum
enum: ['experimental-edge', 'nodejs'] as any,
type: 'string',
},
scrollRestoration: {
type: 'boolean',
},
serverComponents: {
type: 'boolean',
},
sharedPool: {
type: 'boolean',
},
Subresource Integrity for App Directory (#39729) <!-- Thanks for opening a PR! Your contribution is much appreciated. In order to make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change that you're making: --> This serves to add support for [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) hashes for scripts added from the new app directory. This also has support for utilizing nonce values passed from request headers (expected to be generated per request in middleware) in the bootstrapping scripts via the `Content-Security-Policy` header as such: ``` Content-Security-Policy: script-src 'nonce-2726c7f26c' ``` Which results in the inline scripts having a new `nonce` attribute hash added. These features combined support for setting an aggressive Content Security Policy on scripts loaded. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [x] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [x] Make sure the linting passes by running `pnpm lint` - [x] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples) Co-authored-by: Steven <steven@ceriously.com>
2022-09-09 00:17:15 +02:00
sri: {
properties: {
algorithm: {
enum: ['sha256', 'sha384', 'sha512'] as any,
type: 'string',
},
},
type: 'object',
},
swcFileReading: {
type: 'boolean',
},
swcMinify: {
type: 'boolean',
},
swcMinifyDebugOptions: {
additionalProperties: false,
properties: {
compress: {
type: 'object',
},
mangle: {
type: 'object',
},
},
type: 'object',
},
swcPlugins: {
type: 'array',
},
swcTraceProfiling: {
type: 'boolean',
},
urlImports: {
items: {
type: 'string',
},
type: 'array',
},
workerThreads: {
type: 'boolean',
},
},
type: 'object',
},
exportPathMap: {
isFunction: true,
errorMessage: 'must be a function that returns a Promise',
} as any,
future: {
additionalProperties: false,
properties: {},
type: 'object',
},
generateBuildId: {
isFunction: true,
errorMessage: 'must be a function that returns a Promise',
} as any,
generateEtags: {
type: 'boolean',
},
headers: {
isFunction: true,
errorMessage: 'must be a function that returns a Promise',
} as any,
httpAgentOptions: {
additionalProperties: false,
properties: {
keepAlive: {
type: 'boolean',
},
},
type: 'object',
},
i18n: {
additionalProperties: false,
properties: {
defaultLocale: {
minLength: 1,
type: 'string',
},
domains: {
items: {
additionalProperties: false,
properties: {
defaultLocale: {
minLength: 1,
type: 'string',
},
domain: {
minLength: 1,
type: 'string',
},
http: {
type: 'boolean',
},
locales: {
items: {
minLength: 1,
type: 'string',
},
type: 'array',
},
},
type: 'object',
},
type: 'array',
},
localeDetection: {
type: 'boolean',
},
locales: {
items: {
minLength: 1,
type: 'string',
},
type: 'array',
},
},
type: 'object',
},
images: {
additionalProperties: false,
properties: {
remotePatterns: {
items: {
additionalProperties: false,
properties: {
hostname: {
minLength: 1,
type: 'string',
},
pathname: {
minLength: 1,
type: 'string',
},
port: {
minLength: 1,
type: 'string',
},
protocol: {
// automatic typing doesn't like enum
enum: ['http', 'https'] as any,
type: 'string',
},
},
type: 'object',
},
type: 'array',
},
unoptimized: {
type: 'boolean',
},
contentSecurityPolicy: {
minLength: 1,
type: 'string',
},
dangerouslyAllowSVG: {
type: 'boolean',
},
deviceSizes: {
items: {
type: 'number',
},
minItems: 1,
type: 'array',
},
disableStaticImages: {
type: 'boolean',
},
domains: {
items: {
type: 'string',
},
type: 'array',
},
formats: {
items: {
enum: ['image/avif', 'image/webp'], // automatic typing does not like enum
type: 'string',
} as any,
type: 'array',
},
imageSizes: {
items: {
type: 'number',
},
minItems: 1,
type: 'array',
},
loader: {
// automatic typing does not like enum
enum: VALID_LOADERS as any,
type: 'string',
},
minimumCacheTTL: {
type: 'number',
},
path: {
minLength: 1,
type: 'string',
},
},
type: 'object',
},
onDemandEntries: {
additionalProperties: false,
properties: {
maxInactiveAge: {
type: 'number',
},
pagesBufferLength: {
type: 'number',
},
},
type: 'object',
},
optimizeFonts: {
type: 'boolean',
},
output: {
// automatic typing doesn't like enum
enum: ['standalone'] as any,
type: 'string',
},
outputFileTracing: {
type: 'boolean',
},
pageExtensions: {
minItems: 1,
type: 'array',
},
poweredByHeader: {
type: 'boolean',
},
productionBrowserSourceMaps: {
type: 'boolean',
},
publicRuntimeConfig: {
type: 'object',
},
reactStrictMode: {
type: 'boolean',
},
redirects: {
isFunction: true,
errorMessage: 'must be a function that returns a Promise',
} as any,
rewrites: {
isFunction: true,
errorMessage: 'must be a function that returns a Promise',
} as any,
sassOptions: {
type: 'object',
},
serverRuntimeConfig: {
type: 'object',
},
staticPageGenerationTimeout: {
type: 'number',
},
swcMinify: {
type: 'boolean',
},
trailingSlash: {
type: 'boolean',
},
typescript: {
additionalProperties: false,
properties: {
ignoreBuildErrors: {
type: 'boolean',
},
tsconfigPath: {
minLength: 1,
type: 'string',
},
},
type: 'object',
},
useFileSystemPublicRoutes: {
type: 'boolean',
},
webpack: {
isFunction: true,
errorMessage:
'must be a function that returns a webpack configuration object',
} as any,
},
} as JSONSchemaType<NextConfig>
// module.exports is used to get around an export bug with TypeScript
// and the Ajv automatic typing
module.exports = {
configSchema,
}