2022-01-17 16:17:22 +01:00
import ReactRefreshWebpackPlugin from 'next/dist/compiled/@next/react-refresh-utils/ReactRefreshWebpackPlugin'
2021-12-21 16:13:45 +01:00
import chalk from 'next/dist/compiled/chalk'
2019-09-11 22:41:29 +02:00
import crypto from 'crypto'
2021-10-06 17:40:01 +02:00
import { webpack } from 'next/dist/compiled/webpack/webpack'
2021-10-24 23:04:26 +02:00
import type { webpack5 } from 'next/dist/compiled/webpack/webpack'
2021-04-22 21:03:13 +02:00
import path , { join as pathJoin , relative as relativePath } from 'path'
2022-01-03 18:41:50 +01:00
import { escapeStringRegexp } from '../shared/lib/escape-regexp'
2019-04-26 17:23:32 +02:00
import {
2019-04-26 18:12:40 +02:00
DOT_NEXT_ALIAS ,
2019-04-26 17:23:32 +02:00
NEXT_PROJECT_ROOT ,
NEXT_PROJECT_ROOT_DIST_CLIENT ,
PAGES_DIR_ALIAS ,
2022-05-19 17:46:21 +02:00
ROOT_DIR_ALIAS ,
2022-05-25 11:46:26 +02:00
APP_DIR_ALIAS ,
2019-04-26 17:23:32 +02:00
} from '../lib/constants'
2019-07-17 08:01:21 +02:00
import { fileExists } from '../lib/file-exists'
2021-04-22 21:03:13 +02:00
import { CustomRoutes } from '../lib/load-custom-routes.js'
2019-09-11 22:41:29 +02:00
import {
2021-04-22 21:03:13 +02:00
CLIENT_STATIC_FILES_RUNTIME_AMP ,
2019-09-11 22:41:29 +02:00
CLIENT_STATIC_FILES_RUNTIME_MAIN ,
2022-05-03 12:37:23 +02:00
CLIENT_STATIC_FILES_RUNTIME_MAIN_ROOT ,
2021-08-14 00:40:45 +02:00
CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL ,
2021-04-22 21:03:13 +02:00
CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH ,
2019-09-11 22:41:29 +02:00
CLIENT_STATIC_FILES_RUNTIME_WEBPACK ,
2021-10-26 18:50:56 +02:00
MIDDLEWARE_REACT_LOADABLE_MANIFEST ,
2019-09-11 22:41:29 +02:00
REACT_LOADABLE_MANIFEST ,
SERVERLESS_DIRECTORY ,
2019-12-09 21:08:15 +01:00
SERVER_DIRECTORY ,
2022-05-17 17:09:34 +02:00
MODERN_BROWSERSLIST_TARGET ,
2021-06-30 11:43:31 +02:00
} from '../shared/lib/constants'
import { execOnce } from '../shared/lib/utils'
2021-07-12 23:38:57 +02:00
import { NextConfigComplete } from '../server/config-shared'
2021-09-21 19:17:16 +02:00
import { finalizeEntrypoint } from './entries'
2020-08-04 23:24:56 +02:00
import * as Log from './output/log'
2019-12-09 21:08:15 +01:00
import { build as buildConfiguration } from './webpack/config'
2021-10-20 19:52:11 +02:00
import MiddlewarePlugin from './webpack/plugins/middleware-plugin'
2019-04-26 18:12:40 +02:00
import BuildManifestPlugin from './webpack/plugins/build-manifest-plugin'
2020-04-15 20:20:25 +02:00
import { JsConfigPathsPlugin } from './webpack/plugins/jsconfig-paths-plugin'
2019-05-08 03:11:56 +02:00
import { DropClientPage } from './webpack/plugins/next-drop-client-page-plugin'
2021-08-16 21:29:11 +02:00
import { TraceEntryPointsPlugin } from './webpack/plugins/next-trace-entrypoints-plugin'
2019-04-26 18:12:40 +02:00
import PagesManifestPlugin from './webpack/plugins/pages-manifest-plugin'
2019-09-11 22:41:29 +02:00
import { ProfilingPlugin } from './webpack/plugins/profiling-plugin'
2019-04-26 18:12:40 +02:00
import { ReactLoadablePlugin } from './webpack/plugins/react-loadable-plugin'
import { ServerlessPlugin } from './webpack/plugins/serverless-plugin'
2020-05-13 17:43:41 +02:00
import { WellKnownErrorsPlugin } from './webpack/plugins/wellknown-errors-plugin'
2021-06-07 14:43:14 +02:00
import { regexLikeCss } from './webpack/config/blocks/css'
2021-08-14 00:40:45 +02:00
import { CopyFilePlugin } from './webpack/plugins/copy-file-plugin'
2021-10-26 18:50:56 +02:00
import { FlightManifestPlugin } from './webpack/plugins/flight-manifest-plugin'
2022-05-24 16:54:26 +02:00
import { ClientEntryPlugin } from './webpack/plugins/client-entry-plugin'
2022-03-22 01:09:03 +01:00
import {
Feature ,
SWC_TARGET_TRIPLE ,
TelemetryPlugin ,
} from './webpack/plugins/telemetry-plugin'
2021-09-13 15:49:29 +02:00
import type { Span } from '../trace'
2022-04-27 11:50:29 +02:00
import { withoutRSCExtensions } from './utils'
2021-12-21 16:13:45 +01:00
import browserslist from 'next/dist/compiled/browserslist'
2021-11-11 01:16:15 +01:00
import loadJsConfig from './load-jsconfig'
2022-02-24 16:56:40 +01:00
import { getMiddlewareSourceMapPlugins } from './webpack/plugins/middleware-source-maps-plugin'
2022-05-12 11:15:27 +02:00
import { loadBindings } from './swc'
2021-11-03 19:38:04 +01:00
2021-11-25 09:31:20 +01:00
const watchOptions = Object . freeze ( {
aggregateTimeout : 5 ,
2022-03-08 15:12:50 +01:00
ignored : [ '**/.git/**' , '**/.next/**' ] ,
2021-11-25 09:31:20 +01:00
} )
2021-11-03 19:38:04 +01:00
function getSupportedBrowsers (
dir : string ,
2022-05-17 17:09:34 +02:00
isDevelopment : boolean ,
config : NextConfigComplete
2021-11-03 19:38:04 +01:00
) : string [ ] | undefined {
let browsers : any
try {
2022-05-17 17:09:34 +02:00
const browsersListConfig = browserslist . loadConfig ( {
2021-11-03 19:38:04 +01:00
path : dir ,
env : isDevelopment ? 'development' : 'production' ,
} )
2022-05-17 17:09:34 +02:00
// Running `browserslist` resolves `extends` and other config features into a list of browsers
if ( browsersListConfig && browsersListConfig . length > 0 ) {
browsers = browserslist ( browsersListConfig )
}
2021-11-03 19:38:04 +01:00
} catch { }
2022-05-17 17:09:34 +02:00
// When user has browserslist use that target
if ( browsers && browsers . length > 0 ) {
return browsers
}
// When user does not have browserslist use the default target
// When `experimental.legacyBrowsers: false` the modern default is used
return config . experimental . legacyBrowsers
? undefined
: MODERN_BROWSERSLIST_TARGET
2021-11-03 19:38:04 +01:00
}
2020-09-01 17:29:25 +02:00
2019-02-20 20:24:02 +01:00
type ExcludesFalse = < T > ( x : T | false ) = > x is T
2016-12-28 00:28:19 +01:00
2021-01-14 02:59:08 +01:00
const devtoolRevertWarning = execOnce (
( devtool : webpack.Configuration [ 'devtool' ] ) = > {
console . warn (
chalk . yellow . bold ( 'Warning: ' ) +
chalk . bold ( ` Reverting webpack devtool to ' ${ devtool } '. \ n ` ) +
'Changing the webpack devtool in development mode will cause severe performance regressions.\n' +
2021-03-29 10:25:00 +02:00
'Read more: https://nextjs.org/docs/messages/improper-devtool'
2021-01-14 02:59:08 +01:00
)
}
)
2020-06-24 06:15:57 +02:00
2021-10-23 10:21:44 +02:00
let loggedSwcDisabled = false
2022-02-10 02:54:28 +01:00
let loggedIgnoredCompilerOptions = false
2021-10-23 10:21:44 +02:00
2021-10-26 18:50:56 +02:00
function getOptimizedAliases ( ) : { [ pkg : string ] : string } {
2019-11-15 07:47:08 +01:00
const stubWindowFetch = path . join ( __dirname , 'polyfills' , 'fetch' , 'index.js' )
2019-11-11 05:48:11 +01:00
const stubObjectAssign = path . join ( __dirname , 'polyfills' , 'object-assign.js' )
const shimAssign = path . join ( __dirname , 'polyfills' , 'object.assign' )
2020-01-30 07:04:29 +01:00
return Object . assign (
{ } ,
{
unfetch$ : stubWindowFetch ,
'isomorphic-unfetch$' : stubWindowFetch ,
'whatwg-fetch$' : path . join (
__dirname ,
'polyfills' ,
'fetch' ,
'whatwg-fetch.js'
) ,
} ,
{
'object-assign$' : stubObjectAssign ,
// Stub Package: object.assign
'object.assign/auto' : path . join ( shimAssign , 'auto.js' ) ,
'object.assign/implementation' : path . join (
shimAssign ,
'implementation.js'
) ,
'object.assign$' : path . join ( shimAssign , 'index.js' ) ,
'object.assign/polyfill' : path . join ( shimAssign , 'polyfill.js' ) ,
'object.assign/shim' : path . join ( shimAssign , 'shim.js' ) ,
2020-02-28 04:08:58 +01:00
// Replace: full URL polyfill with platform-based polyfill
2021-10-18 17:46:39 +02:00
url : require.resolve ( 'next/dist/compiled/native-url' ) ,
2020-01-30 07:04:29 +01:00
}
)
2019-11-02 02:00:56 +01:00
}
2020-02-17 22:16:19 +01:00
type ClientEntries = {
2020-07-17 10:38:06 +02:00
[ key : string ] : string | string [ ]
2020-02-17 22:16:19 +01:00
}
2020-08-04 23:24:56 +02:00
export function attachReactRefresh (
webpackConfig : webpack.Configuration ,
targetLoader : webpack.RuleSetUseItem
) {
let injections = 0
2022-01-17 16:17:22 +01:00
const reactRefreshLoaderName =
'next/dist/compiled/@next/react-refresh-utils/loader'
2020-08-04 23:24:56 +02:00
const reactRefreshLoader = require . resolve ( reactRefreshLoaderName )
webpackConfig . module ? . rules . forEach ( ( rule ) = > {
const curr = rule . use
// When the user has configured `defaultLoaders.babel` for a input file:
if ( curr === targetLoader ) {
++ injections
rule . use = [ reactRefreshLoader , curr as webpack . RuleSetUseItem ]
} else if (
Array . isArray ( curr ) &&
curr . some ( ( r ) = > r === targetLoader ) &&
// Check if loader already exists:
! curr . some (
( r ) = > r === reactRefreshLoader || r === reactRefreshLoaderName
)
) {
++ injections
const idx = curr . findIndex ( ( r ) = > r === targetLoader )
// Clone to not mutate user input
rule . use = [ . . . curr ]
// inject / input: [other, babel] output: [other, refresh, babel]:
rule . use . splice ( idx , 0 , reactRefreshLoader )
}
} )
if ( injections ) {
Log . info (
` automatically enabled Fast Refresh for ${ injections } custom loader ${
injections > 1 ? 's' : ''
} `
)
}
}
2021-09-24 15:39:48 +02:00
export const NODE_RESOLVE_OPTIONS = {
2021-05-07 18:32:33 +02:00
dependencyType : 'commonjs' ,
modules : [ 'node_modules' ] ,
fallback : false ,
exportsFields : [ 'exports' ] ,
importsFields : [ 'imports' ] ,
2021-08-31 10:32:33 +02:00
conditionNames : [ 'node' , 'require' ] ,
2021-05-07 18:32:33 +02:00
descriptionFiles : [ 'package.json' ] ,
extensions : [ '.js' , '.json' , '.node' ] ,
enforceExtensions : false ,
symlinks : true ,
mainFields : [ 'main' ] ,
mainFiles : [ 'index' ] ,
roots : [ ] ,
fullySpecified : false ,
preferRelative : false ,
preferAbsolute : false ,
restrictions : [ ] ,
}
2021-10-05 01:57:27 +02:00
export const NODE_BASE_RESOLVE_OPTIONS = {
. . . NODE_RESOLVE_OPTIONS ,
alias : false ,
}
2021-09-24 15:39:48 +02:00
export const NODE_ESM_RESOLVE_OPTIONS = {
2021-07-10 18:49:02 +02:00
. . . NODE_RESOLVE_OPTIONS ,
2021-10-05 01:57:27 +02:00
alias : false ,
2021-07-10 18:49:02 +02:00
dependencyType : 'esm' ,
2021-08-31 10:32:33 +02:00
conditionNames : [ 'node' , 'import' ] ,
2021-07-10 18:49:02 +02:00
fullySpecified : true ,
}
2021-10-05 01:57:27 +02:00
export const NODE_BASE_ESM_RESOLVE_OPTIONS = {
. . . NODE_ESM_RESOLVE_OPTIONS ,
alias : false ,
}
2021-10-18 19:01:02 +02:00
export const nextImageLoaderRegex =
/\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$/i
2021-10-28 10:14:09 +02:00
export async function resolveExternal (
appDir : string ,
esmExternalsConfig : NextConfigComplete [ 'experimental' ] [ 'esmExternals' ] ,
context : string ,
request : string ,
isEsmRequested : boolean ,
getResolve : (
options : any
) = > (
resolveContext : string ,
resolveRequest : string
) = > Promise < [ string | null , boolean ] > ,
isLocalCallback ? : ( res : string ) = > any ,
baseResolveCheck = true ,
esmResolveOptions : any = NODE_ESM_RESOLVE_OPTIONS ,
nodeResolveOptions : any = NODE_RESOLVE_OPTIONS ,
baseEsmResolveOptions : any = NODE_BASE_ESM_RESOLVE_OPTIONS ,
baseResolveOptions : any = NODE_BASE_RESOLVE_OPTIONS
) {
const esmExternals = ! ! esmExternalsConfig
const looseEsmExternals = esmExternalsConfig === 'loose'
let res : string | null = null
let isEsm : boolean = false
let preferEsmOptions =
esmExternals && isEsmRequested ? [ true , false ] : [ false ]
for ( const preferEsm of preferEsmOptions ) {
const resolve = getResolve (
preferEsm ? esmResolveOptions : nodeResolveOptions
)
// Resolve the import with the webpack provided context, this
// ensures we're resolving the correct version when multiple
// exist.
try {
; [ res , isEsm ] = await resolve ( context , request )
} catch ( err ) {
res = null
}
if ( ! res ) {
continue
}
// ESM externals can only be imported (and not required).
// Make an exception in loose mode.
if ( ! isEsmRequested && isEsm && ! looseEsmExternals ) {
continue
}
if ( isLocalCallback ) {
return { localRes : isLocalCallback ( res ) }
}
// Bundled Node.js code is relocated without its node_modules tree.
// This means we need to make sure its request resolves to the same
// package that'll be available at runtime. If it's not identical,
// we need to bundle the code (even if it _should_ be external).
if ( baseResolveCheck ) {
let baseRes : string | null
let baseIsEsm : boolean
try {
const baseResolve = getResolve (
isEsm ? baseEsmResolveOptions : baseResolveOptions
)
; [ baseRes , baseIsEsm ] = await baseResolve ( appDir , request )
} catch ( err ) {
baseRes = null
baseIsEsm = false
}
// Same as above: if the package, when required from the root,
// would be different from what the real resolution would use, we
// cannot externalize it.
// if request is pointing to a symlink it could point to the the same file,
// the resolver will resolve symlinks so this is handled
if ( baseRes !== res || isEsm !== baseIsEsm ) {
res = null
continue
}
}
break
}
return { res , isEsm }
}
2019-04-26 17:23:32 +02:00
export default async function getBaseWebpackConfig (
dir : string ,
{
buildId ,
config ,
2022-04-27 11:50:29 +02:00
compilerType ,
2019-09-24 17:15:14 +02:00
dev = false ,
2022-04-27 11:50:29 +02:00
entrypoints ,
hasReactRoot ,
isDevFallback = false ,
2019-09-24 17:15:14 +02:00
pagesDir ,
2020-07-09 13:39:12 +02:00
reactProductionProfiling = false ,
2020-08-13 14:39:36 +02:00
rewrites ,
2021-08-17 09:18:47 +02:00
runWebpackSpan ,
2022-04-27 11:50:29 +02:00
target = 'server' ,
2022-05-25 11:46:26 +02:00
appDir ,
2019-04-26 17:23:32 +02:00
} : {
buildId : string
2021-07-12 23:38:57 +02:00
config : NextConfigComplete
2022-04-27 11:50:29 +02:00
compilerType : 'client' | 'server' | 'edge-server'
2019-09-24 17:15:14 +02:00
dev? : boolean
2022-04-27 11:50:29 +02:00
entrypoints : webpack5.EntryObject
hasReactRoot : boolean
isDevFallback? : boolean
2019-09-24 17:15:14 +02:00
pagesDir : string
2020-07-09 13:39:12 +02:00
reactProductionProfiling? : boolean
2021-03-26 16:19:48 +01:00
rewrites : CustomRoutes [ 'rewrites' ]
2021-08-25 10:47:16 +02:00
runWebpackSpan : Span
2022-04-27 11:50:29 +02:00
target? : string
2022-05-25 11:46:26 +02:00
appDir? : string
2019-04-26 17:23:32 +02:00
}
) : Promise < webpack.Configuration > {
2022-04-27 11:50:29 +02:00
const isClient = compilerType === 'client'
const isEdgeServer = compilerType === 'edge-server'
const isNodeServer = compilerType === 'server'
2021-11-12 21:51:43 +01:00
const { useTypeScript , jsConfig , resolvedBaseUrl } = await loadJsConfig (
dir ,
config
)
2022-05-17 17:09:34 +02:00
const supportedBrowsers = await getSupportedBrowsers ( dir , dev , config )
2021-03-26 16:19:48 +01:00
const hasRewrites =
rewrites . beforeFiles . length > 0 ||
rewrites . afterFiles . length > 0 ||
rewrites . fallback . length > 0
2022-02-08 14:16:46 +01:00
2022-03-26 00:05:35 +01:00
// Make sure `reactRoot` is enabled when React 18 or experimental is detected.
2021-12-20 14:43:42 +01:00
if ( hasReactRoot ) {
config . experimental . reactRoot = true
}
2021-10-30 23:35:31 +02:00
// Only inform during one of the builds
2022-04-27 11:50:29 +02:00
if ( isClient && config . experimental . reactRoot && ! hasReactRoot ) {
2021-10-29 17:59:27 +02:00
// It's fine to only mention React 18 here as we don't recommend people to try experimental.
Log . warn ( 'You have to use React 18 to use `experimental.reactRoot`.' )
}
2022-04-27 11:50:29 +02:00
if ( isClient && config . experimental . runtime && ! hasReactRoot ) {
2021-10-29 17:59:27 +02:00
throw new Error (
2022-02-08 14:16:46 +01:00
'`experimental.runtime` requires `experimental.reactRoot` to be enabled along with React 18.'
2021-10-29 17:59:27 +02:00
)
}
2022-03-26 00:05:35 +01:00
if ( config . experimental . serverComponents && ! hasReactRoot ) {
2021-10-26 18:50:56 +02:00
throw new Error (
2022-03-26 00:05:35 +01:00
'`experimental.serverComponents` requires React 18 to be installed.'
2021-10-26 18:50:56 +02:00
)
}
2022-02-08 14:16:46 +01:00
2022-03-26 00:05:35 +01:00
const hasConcurrentFeatures = hasReactRoot
2021-10-26 18:50:56 +02:00
const hasServerComponents =
hasConcurrentFeatures && ! ! config . experimental . serverComponents
2022-02-08 14:16:46 +01:00
const disableOptimizedLoading = hasConcurrentFeatures
? true
: config . experimental . disableOptimizedLoading
2021-10-26 18:50:56 +02:00
2022-04-27 11:50:29 +02:00
if ( isClient ) {
if ( config . experimental . runtime === 'edge' ) {
2022-02-08 14:16:46 +01:00
Log . warn (
'You are using the experimental Edge Runtime with `experimental.runtime`.'
)
}
2022-04-27 11:50:29 +02:00
if ( config . experimental . runtime === 'nodejs' ) {
2022-02-08 14:16:46 +01:00
Log . warn (
'You are using the experimental Node.js Runtime with `experimental.runtime`.'
)
}
2021-10-26 18:50:56 +02:00
if ( hasServerComponents ) {
2021-11-01 12:40:21 +01:00
Log . warn (
'You have experimental React Server Components enabled. Continue at your own risk.'
)
2021-10-26 18:50:56 +02:00
}
}
2021-04-28 11:51:57 +02:00
const babelConfigFile = await [
2021-04-20 10:45:57 +02:00
'.babelrc' ,
'.babelrc.json' ,
'.babelrc.js' ,
'.babelrc.mjs' ,
'.babelrc.cjs' ,
'babel.config.js' ,
'babel.config.json' ,
'babel.config.mjs' ,
'babel.config.cjs' ,
2021-04-28 11:51:57 +02:00
] . reduce ( async ( memo : Promise < string | undefined > , filename ) = > {
const configFilePath = path . join ( dir , filename )
return (
( await memo ) ||
( ( await fileExists ( configFilePath ) ) ? configFilePath : undefined )
)
} , Promise . resolve ( undefined ) )
2021-04-20 10:45:57 +02:00
2019-04-22 18:16:42 +02:00
const distDir = path . join ( dir , config . distDir )
2021-04-08 14:03:02 +02:00
2022-05-10 12:33:31 +02:00
let useSWCLoader = ! babelConfigFile || config . experimental . forceSwcTransforms
2022-03-22 01:09:03 +01:00
let SWCBinaryTarget : [ Feature , boolean ] | undefined = undefined
if ( useSWCLoader ) {
// TODO: we do not collect wasm target yet
const binaryTarget = require ( './swc' ) ? . getBinaryMetadata ? . ( )
? . target as SWC_TARGET_TRIPLE
SWCBinaryTarget = binaryTarget
? [ ` swc/target/ ${ binaryTarget } ` as const , true ]
: undefined
}
2021-10-26 18:50:56 +02:00
2021-10-23 10:21:44 +02:00
if ( ! loggedSwcDisabled && ! useSWCLoader && babelConfigFile ) {
2021-11-06 19:37:24 +01:00
Log . info (
2021-10-26 19:59:37 +02:00
` Disabled SWC as replacement for Babel because of custom Babel configuration " ${ path . relative (
2021-10-23 10:21:44 +02:00
dir ,
babelConfigFile
) } " https : //nextjs.org/docs/messages/swc-disabled`
2021-08-06 16:07:36 +02:00
)
2021-10-23 10:21:44 +02:00
loggedSwcDisabled = true
2021-08-06 16:07:36 +02:00
}
2021-10-24 15:26:36 +02:00
2022-05-12 11:15:27 +02:00
// eagerly load swc bindings instead of waiting for transform calls
if ( ! babelConfigFile && isClient ) {
await loadBindings ( )
}
2022-02-10 02:54:28 +01:00
if ( ! loggedIgnoredCompilerOptions && ! useSWCLoader && config . compiler ) {
Log . info (
2022-03-20 23:50:33 +01:00
'`compiler` options in `next.config.js` will be ignored while using Babel https://nextjs.org/docs/messages/ignored-compiler-options'
2022-02-10 02:54:28 +01:00
)
loggedIgnoredCompilerOptions = true
}
2022-04-27 11:50:29 +02:00
const getBabelOrSwcLoader = ( ) = > {
2022-05-03 00:20:59 +02:00
if ( useSWCLoader && config ? . experimental ? . swcTraceProfiling ) {
// This will init subscribers once only in a single process lifecycle,
// even though it can be called multiple times.
// Subscriber need to be initialized _before_ any actual swc's call (transform, etcs)
// to collect correct trace spans when they are called.
require ( './swc' ) ? . initCustomTraceSubscriber ? . (
path . join ( distDir , ` swc-trace-profile- ${ Date . now ( ) } .json ` )
)
}
2021-10-24 15:26:36 +02:00
return useSWCLoader
2021-08-06 16:07:36 +02:00
? {
loader : 'next-swc-loader' ,
options : {
2022-04-27 11:50:29 +02:00
isServer : isNodeServer || isEdgeServer ,
2021-09-13 12:20:38 +02:00
pagesDir ,
2022-04-27 11:50:29 +02:00
hasReactRefresh : dev && isClient ,
2021-12-02 05:16:15 +01:00
fileReading : config.experimental.swcFileReading ,
2021-11-13 18:26:13 +01:00
nextConfig : config ,
jsConfig ,
2022-05-17 17:09:34 +02:00
supportedBrowsers : config.experimental.browsersListForSwc
? supportedBrowsers
: undefined ,
2021-08-06 16:07:36 +02:00
} ,
}
: {
2021-10-06 17:40:01 +02:00
loader : require.resolve ( './babel/loader/index' ) ,
2021-08-06 16:07:36 +02:00
options : {
configFile : babelConfigFile ,
2022-04-27 11:50:29 +02:00
isServer : isNodeServer || isEdgeServer ,
2021-08-06 16:07:36 +02:00
distDir ,
pagesDir ,
cwd : dir ,
development : dev ,
2022-04-27 11:50:29 +02:00
hasReactRefresh : dev && isClient ,
2021-08-06 16:07:36 +02:00
hasJsxRuntime : true ,
} ,
2021-10-24 15:26:36 +02:00
}
}
const defaultLoaders = {
2022-04-27 11:50:29 +02:00
babel : getBabelOrSwcLoader ( ) ,
2018-01-30 16:40:52 +01:00
}
2021-10-26 18:50:56 +02:00
const rawPageExtensions = hasServerComponents
2022-04-27 11:50:29 +02:00
? withoutRSCExtensions ( config . pageExtensions )
2021-10-26 18:50:56 +02:00
: config . pageExtensions
const serverComponentsRegex = new RegExp (
` \\ .server \\ .( ${ rawPageExtensions . join ( '|' ) } ) $ `
)
2019-11-01 20:13:13 +01:00
const babelIncludeRegexes : RegExp [ ] = [
2021-06-30 11:43:31 +02:00
/next[\\/]dist[\\/]shared[\\/]lib/ ,
2019-11-01 20:13:13 +01:00
/next[\\/]dist[\\/]client/ ,
/next[\\/]dist[\\/]pages/ ,
2021-05-16 14:05:58 +02:00
/[\\/](strip-ansi|ansi-regex)[\\/]/ ,
2019-11-01 20:13:13 +01:00
]
2018-02-01 16:21:18 +01:00
// Support for NODE_PATH
const nodePathList = ( process . env . NODE_PATH || '' )
. split ( process . platform === 'win32' ? ';' : ':' )
2020-05-18 21:24:37 +02:00
. filter ( ( p ) = > ! ! p )
2018-02-01 16:21:18 +01:00
2019-08-06 00:26:20 +02:00
// Intentionally not using isTargetLikeServerless helper
2022-04-27 11:50:29 +02:00
const isLikeServerless =
target === 'serverless' || target === 'experimental-serverless-trace'
const outputPath =
isNodeServer || isEdgeServer
? path . join (
distDir ,
isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY
)
: distDir
2019-08-06 00:26:20 +02:00
2022-04-27 11:50:29 +02:00
const clientEntries = isClient
2020-02-17 22:16:19 +01:00
? ( {
2019-04-26 17:23:32 +02:00
// Backwards compatibility
'main.js' : [ ] ,
2021-02-19 11:10:19 +01:00
. . . ( dev
? {
[ CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH ] : require . resolve (
2022-01-17 16:17:22 +01:00
` next/dist/compiled/@next/react-refresh-utils/runtime `
2021-02-19 11:10:19 +01:00
) ,
[ CLIENT_STATIC_FILES_RUNTIME_AMP ] :
` ./ ` +
relativePath (
dir ,
pathJoin ( NEXT_PROJECT_ROOT_DIST_CLIENT , 'dev' , 'amp-dev' )
) . replace ( /\\/g , '/' ) ,
}
: { } ) ,
2019-04-26 17:23:32 +02:00
[ CLIENT_STATIC_FILES_RUNTIME_MAIN ] :
2020-07-09 14:31:06 +02:00
` ./ ` +
path
. relative (
dir ,
path . join (
NEXT_PROJECT_ROOT_DIST_CLIENT ,
dev ? ` next-dev.js ` : 'next.js'
)
2019-04-26 17:23:32 +02:00
)
2020-07-09 14:31:06 +02:00
. replace ( /\\/g , '/' ) ,
2022-05-25 11:46:26 +02:00
. . . ( config . experimental . appDir
2022-05-03 12:37:23 +02:00
? {
[ CLIENT_STATIC_FILES_RUNTIME_MAIN_ROOT ] :
` ./ ` +
path
. relative (
dir ,
2022-05-25 11:46:26 +02:00
path . join ( NEXT_PROJECT_ROOT_DIST_CLIENT , 'app-next.js' )
2022-05-03 12:37:23 +02:00
)
. replace ( /\\/g , '/' ) ,
}
: { } ) ,
2020-02-17 22:16:19 +01:00
} as ClientEntries )
2019-04-26 17:23:32 +02:00
: undefined
2016-10-19 14:41:45 +02:00
2020-06-28 13:23:29 +02:00
function getReactProfilingInProduction() {
2020-07-09 13:39:12 +02:00
if ( reactProductionProfiling ) {
2020-06-28 13:23:29 +02:00
return {
'react-dom$' : 'react-dom/profiling' ,
'scheduler/tracing' : 'scheduler/tracing-profiling' ,
}
}
}
2021-08-19 10:12:12 +02:00
// tell webpack where to look for _app and _document
// using aliases to allow falling back to the default
// version when removed or not present
2020-08-13 14:39:36 +02:00
const clientResolveRewrites = require . resolve (
2021-06-30 11:43:31 +02:00
'../shared/lib/router/utils/resolve-rewrites'
2020-08-13 14:39:36 +02:00
)
2021-08-19 10:12:12 +02:00
const customAppAliases : { [ key : string ] : string [ ] } = { }
const customErrorAlias : { [ key : string ] : string [ ] } = { }
const customDocumentAliases : { [ key : string ] : string [ ] } = { }
2022-05-03 12:37:23 +02:00
const customRootAliases : { [ key : string ] : string [ ] } = { }
2021-08-19 10:12:12 +02:00
2021-10-06 17:40:01 +02:00
if ( dev ) {
2021-08-19 10:12:12 +02:00
customAppAliases [ ` ${ PAGES_DIR_ALIAS } /_app ` ] = [
2022-05-20 20:07:20 +02:00
. . . config . pageExtensions . reduce ( ( prev , ext ) = > {
2021-08-19 10:12:12 +02:00
prev . push ( path . join ( pagesDir , ` _app. ${ ext } ` ) )
return prev
} , [ ] as string [ ] ) ,
'next/dist/pages/_app.js' ,
]
customAppAliases [ ` ${ PAGES_DIR_ALIAS } /_error ` ] = [
. . . config . pageExtensions . reduce ( ( prev , ext ) = > {
prev . push ( path . join ( pagesDir , ` _error. ${ ext } ` ) )
return prev
} , [ ] as string [ ] ) ,
'next/dist/pages/_error.js' ,
]
customDocumentAliases [ ` ${ PAGES_DIR_ALIAS } /_document ` ] = [
. . . config . pageExtensions . reduce ( ( prev , ext ) = > {
prev . push ( path . join ( pagesDir , ` _document. ${ ext } ` ) )
return prev
} , [ ] as string [ ] ) ,
2022-03-11 21:38:09 +01:00
` next/dist/pages/_document.js ` ,
2021-08-19 10:12:12 +02:00
]
}
2018-08-14 00:09:05 +02:00
const resolveConfig = {
2018-11-20 12:13:31 +01:00
// Disable .mjs for node_modules bundling
2022-04-27 11:50:29 +02:00
extensions : isNodeServer
2019-04-26 18:12:40 +02:00
? [
'.js' ,
'.mjs' ,
2020-04-19 07:12:36 +02:00
. . . ( useTypeScript ? [ '.tsx' , '.ts' ] : [ ] ) ,
2019-04-26 18:12:40 +02:00
'.jsx' ,
'.json' ,
'.wasm' ,
]
: [
'.mjs' ,
'.js' ,
2020-04-19 07:12:36 +02:00
. . . ( useTypeScript ? [ '.tsx' , '.ts' ] : [ ] ) ,
2019-04-26 18:12:40 +02:00
'.jsx' ,
'.json' ,
'.wasm' ,
] ,
2018-08-14 00:09:05 +02:00
modules : [
'node_modules' ,
2019-04-26 17:23:32 +02:00
. . . nodePathList , // Support for NODE_PATH environment variable
2018-08-14 00:09:05 +02:00
] ,
alias : {
2020-08-21 20:50:24 +02:00
next : NEXT_PROJECT_ROOT ,
2021-08-18 13:01:02 +02:00
2021-08-19 10:12:12 +02:00
. . . customAppAliases ,
. . . customErrorAlias ,
. . . customDocumentAliases ,
2022-05-03 12:37:23 +02:00
. . . customRootAliases ,
2021-08-18 13:01:02 +02:00
2019-09-24 17:15:14 +02:00
[ PAGES_DIR_ALIAS ] : pagesDir ,
2022-05-25 11:46:26 +02:00
. . . ( appDir
2022-05-03 12:37:23 +02:00
? {
2022-05-25 11:46:26 +02:00
[ APP_DIR_ALIAS ] : appDir ,
2022-05-03 12:37:23 +02:00
}
: { } ) ,
2022-05-19 17:46:21 +02:00
[ ROOT_DIR_ALIAS ] : dir ,
2019-04-15 11:26:23 +02:00
[ DOT_NEXT_ALIAS ] : distDir ,
2022-04-27 11:50:29 +02:00
. . . ( isClient || isEdgeServer ? getOptimizedAliases ( ) : { } ) ,
2020-06-28 13:23:29 +02:00
. . . getReactProfilingInProduction ( ) ,
2021-10-06 19:16:01 +02:00
2022-04-27 11:50:29 +02:00
. . . ( isClient || isEdgeServer
2021-10-06 19:16:01 +02:00
? {
[ clientResolveRewrites ] : hasRewrites
? clientResolveRewrites
: // With webpack 5 an alias can be pointed to false to noop
false ,
}
: { } ) ,
2021-11-05 22:51:10 +01:00
2022-01-03 20:31:23 +01:00
setimmediate : 'next/dist/compiled/setimmediate' ,
2018-12-04 10:59:12 +01:00
} ,
2022-04-27 11:50:29 +02:00
. . . ( isClient || isEdgeServer
2021-02-24 17:25:57 +01:00
? {
fallback : {
2022-01-10 19:45:00 +01:00
process : require.resolve ( './polyfills/process' ) ,
2021-02-24 17:25:57 +01:00
} ,
}
: undefined ) ,
2022-04-27 11:50:29 +02:00
mainFields : isClient
? [ 'browser' , 'module' , 'main' ]
: isEdgeServer
? [ 'module' , 'main' ]
2022-03-16 16:14:49 +01:00
: [ 'main' , 'module' ] ,
2021-10-06 17:40:01 +02:00
plugins : [ ] ,
2018-08-14 00:09:05 +02:00
}
2020-04-26 21:16:43 +02:00
const terserOptions : any = {
2019-06-11 19:34:45 +02:00
parse : {
ecma : 8 ,
} ,
compress : {
ecma : 5 ,
warnings : false ,
// The following two options are known to break valid JavaScript code
comparisons : false ,
2020-05-27 23:51:11 +02:00
inline : 2 , // https://github.com/vercel/next.js/issues/7178#issuecomment-493048965
2019-06-11 19:34:45 +02:00
} ,
mangle : { safari10 : true } ,
output : {
ecma : 5 ,
safari10 : true ,
comments : false ,
// Fixes usage of Emoji and certain Regex
ascii_only : true ,
} ,
}
2020-02-04 20:22:26 +01:00
const isModuleCSS = ( module : { type : string } ) : boolean = > {
return (
// mini-css-extract-plugin
module . type === ` css/mini-extract ` ||
// extract-css-chunks-webpack-plugin (old)
module . type === ` css/extract-chunks ` ||
// extract-css-chunks-webpack-plugin (new)
module . type === ` css/extract-css-chunks `
)
}
2021-11-09 14:42:23 +01:00
// Packages which will be split into the 'framework' chunk.
// Only top-level packages are included, e.g. nested copies like
// 'node_modules/meow/node_modules/object-assign' are not included.
2022-02-06 23:38:42 +01:00
const topLevelFrameworkPaths : string [ ] = [ ]
const visitedFrameworkPackages = new Set < string > ( )
// Adds package-paths of dependencies recursively
const addPackagePath = ( packageName : string , relativeToPath : string ) = > {
try {
if ( visitedFrameworkPackages . has ( packageName ) ) {
return
}
visitedFrameworkPackages . add ( packageName )
const packageJsonPath = require . resolve ( ` ${ packageName } /package.json ` , {
paths : [ relativeToPath ] ,
} )
// Include a trailing slash so that a `.startsWith(packagePath)` check avoids false positives
// when one package name starts with the full name of a different package.
// For example:
// "node_modules/react-slider".startsWith("node_modules/react") // true
// "node_modules/react-slider".startsWith("node_modules/react/") // false
const directory = path . join ( packageJsonPath , '../' )
// Returning from the function in case the directory has already been added and traversed
if ( topLevelFrameworkPaths . includes ( directory ) ) return
topLevelFrameworkPaths . push ( directory )
const dependencies = require ( packageJsonPath ) . dependencies || { }
for ( const name of Object . keys ( dependencies ) ) {
addPackagePath ( name , directory )
}
} catch ( _ ) {
// don't error on failing to resolve framework packages
}
}
for ( const packageName of [ 'react' , 'react-dom' ] ) {
addPackagePath ( packageName , dir )
}
2021-11-09 14:42:23 +01:00
2020-11-18 19:30:00 +01:00
const crossOrigin = config . crossOrigin
2021-07-10 18:49:02 +02:00
const looseEsmExternals = config . experimental ? . esmExternals === 'loose'
2021-01-17 20:02:20 +01:00
async function handleExternals (
context : string ,
request : string ,
2021-07-10 18:49:02 +02:00
dependencyType : string ,
2021-05-07 18:32:33 +02:00
getResolve : (
options : any
2021-07-10 18:49:02 +02:00
) = > (
resolveContext : string ,
resolveRequest : string
) = > Promise < [ string | null , boolean ] >
2021-01-17 20:02:20 +01:00
) {
2020-08-03 14:26:23 +02:00
// We need to externalize internal requests for files intended to
// not be bundled.
const isLocal : boolean =
request . startsWith ( '.' ) ||
// Always check for unix-style path, as webpack sometimes
// normalizes as posix.
path . posix . isAbsolute ( request ) ||
// When on Windows, we also want to check for Windows-specific
// absolute paths.
( process . platform === 'win32' && path . win32 . isAbsolute ( request ) )
2022-04-05 17:57:45 +02:00
// make sure import "next" shows a warning when imported
// in pages/components
if ( request === 'next' ) {
return ` commonjs next/dist/lib/import-next-warning `
}
2020-08-03 14:26:23 +02:00
// Relative requires don't need custom resolution, because they
// are relative to requests we've already resolved here.
// Absolute requires (require('/foo')) are extremely uncommon, but
// also have no need for customization as they're already resolved.
2021-06-30 11:43:31 +02:00
if ( ! isLocal ) {
2021-05-07 18:32:33 +02:00
if ( /^(?:next$|react(?:$|\/))/ . test ( request ) ) {
return ` commonjs ${ request } `
}
2021-08-17 09:18:08 +02:00
const notExternalModules =
2022-05-18 20:36:11 +02:00
/^(?:private-next-pages\/|next\/(?:dist\/pages\/|(?:app|document|link|image|constants|dynamic|script)$)|string-hash$)/
2021-05-07 18:32:33 +02:00
if ( notExternalModules . test ( request ) ) {
return
}
2020-08-03 14:26:23 +02:00
}
2019-03-07 17:40:08 +01:00
2021-07-10 18:49:02 +02:00
// When in esm externals mode, and using import, we resolve with
// ESM resolving options.
const isEsmRequested = dependencyType === 'esm'
2021-10-28 10:14:09 +02:00
const isLocalCallback = ( localRes : string ) = > {
// Makes sure dist/shared and dist/server are not bundled
// we need to process shared `router/router` and `dynamic`,
// so that the DefinePlugin can inject process.env values
const isNextExternal =
/next[/\\]dist[/\\](shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic))/ . test (
localRes
)
2021-10-27 15:53:44 +02:00
2021-10-28 10:14:09 +02:00
if ( isNextExternal ) {
// Generate Next.js external import
const externalRequest = path . posix . join (
'next' ,
'dist' ,
path
. relative (
// Root of Next.js package:
path . join ( __dirname , '..' ) ,
localRes
)
// Windows path normalization
. replace ( /\\/g , '/' )
2021-10-27 15:53:44 +02:00
)
2021-10-28 10:14:09 +02:00
return ` commonjs ${ externalRequest } `
} else {
// We don't want to retry local requests
// with other preferEsm options
return
2021-10-27 15:53:44 +02:00
}
2021-10-28 10:14:09 +02:00
}
2021-10-27 15:53:44 +02:00
2021-10-28 10:14:09 +02:00
const resolveResult = await resolveExternal (
dir ,
config . experimental . esmExternals ,
context ,
request ,
isEsmRequested ,
getResolve ,
isLocal ? isLocalCallback : undefined
)
2021-10-27 15:53:44 +02:00
2021-10-28 10:14:09 +02:00
if ( 'localRes' in resolveResult ) {
return resolveResult . localRes
2021-07-10 18:49:02 +02:00
}
2021-10-28 10:14:09 +02:00
const { res , isEsm } = resolveResult
2021-07-10 18:49:02 +02:00
// If the request cannot be resolved we need to have
2020-08-03 14:26:23 +02:00
// webpack "bundle" it so it surfaces the not found error.
if ( ! res ) {
2021-01-17 20:02:20 +01:00
return
2020-08-03 14:26:23 +02:00
}
2020-04-14 09:50:39 +02:00
2021-07-10 18:49:02 +02:00
// ESM externals can only be imported (and not required).
// Make an exception in loose mode.
if ( ! isEsmRequested && isEsm && ! looseEsmExternals ) {
throw new Error (
` ESM packages ( ${ request } ) need to be imported. Use 'import' to reference the package instead. https://nextjs.org/docs/messages/import-esm-externals `
)
}
const externalType = isEsm ? 'module' : 'commonjs'
2021-05-28 13:17:08 +02:00
if (
2022-01-17 16:17:22 +01:00
res . match ( /next[/\\]dist[/\\]shared[/\\](?!lib[/\\]router[/\\]router)/ ) ||
res . match ( /next[/\\]dist[/\\]compiled[/\\].*\.[mc]?js$/ )
2021-05-28 13:17:08 +02:00
) {
2021-07-10 18:49:02 +02:00
return ` ${ externalType } ${ request } `
2021-05-28 13:17:08 +02:00
}
2020-08-03 14:26:23 +02:00
// Default pages have to be transpiled
if (
2021-05-07 18:32:33 +02:00
res . match ( /[/\\]next[/\\]dist[/\\]/ ) ||
// This is the @babel/plugin-transform-runtime "helpers: true" option
res . match ( /node_modules[/\\]@babel[/\\]runtime[/\\]/ )
2020-08-03 14:26:23 +02:00
) {
2021-01-17 20:02:20 +01:00
return
2020-08-03 14:26:23 +02:00
}
2019-03-07 17:40:08 +01:00
2020-08-03 14:26:23 +02:00
// Webpack itself has to be compiled because it doesn't always use module relative paths
if (
res . match ( /node_modules[/\\]webpack/ ) ||
res . match ( /node_modules[/\\]css-loader/ )
) {
2021-01-17 20:02:20 +01:00
return
2020-08-03 14:26:23 +02:00
}
2020-04-11 12:36:06 +02:00
2020-08-03 14:26:23 +02:00
// Anything else that is standard JavaScript within `node_modules`
// can be externalized.
2021-10-27 15:53:44 +02:00
if ( /node_modules[/\\].*\.[mc]?js$/ . test ( res ) ) {
2021-07-10 18:49:02 +02:00
return ` ${ externalType } ${ request } `
2020-08-03 14:26:23 +02:00
}
// Default behavior: bundle the code!
}
2021-09-17 21:20:09 +02:00
const codeCondition = {
test : /\.(tsx|ts|js|cjs|mjs|jsx)$/ ,
. . . ( config . experimental . externalDir
? // Allowing importing TS/TSX files from outside of the root dir.
{ }
: { include : [ dir , . . . babelIncludeRegexes ] } ) ,
exclude : ( excludePath : string ) = > {
if ( babelIncludeRegexes . some ( ( r ) = > r . test ( excludePath ) ) ) {
return false
}
return /node_modules/ . test ( excludePath )
} ,
}
2022-05-10 21:20:13 +02:00
const serverComponentCodeCondition = {
2022-04-07 21:45:33 +02:00
test : serverComponentsRegex ,
include : [ dir , /next[\\/]dist[\\/]pages/ ] ,
}
2020-08-03 14:26:23 +02:00
let webpackConfig : webpack.Configuration = {
2021-08-18 14:22:53 +02:00
parallelism : Number ( process . env . NEXT_WEBPACK_PARALLELISM ) || undefined ,
2022-05-13 19:48:53 +02:00
// @ts-ignore
2022-04-27 11:50:29 +02:00
externals :
isClient || isEdgeServer
? // make sure importing "next" is handled gracefully for client
// bundles in case a user imported types and it wasn't removed
// TODO: should we warn/error for this instead?
[
'next' ,
. . . ( isEdgeServer
? [
{
'@builder.io/partytown' : '{}' ,
'next/dist/compiled/etag' : '{}' ,
'next/dist/compiled/chalk' : '{}' ,
'react-dom' : '{}' ,
} ,
]
: [ ] ) ,
]
: target !== 'serverless'
? [
( {
context ,
request ,
dependencyType ,
getResolve ,
} : {
context : string
request : string
dependencyType : string
getResolve : (
options : any
) = > (
resolveContext : string ,
resolveRequest : string ,
callback : (
err? : Error ,
result? : string ,
resolveData ? : { descriptionFileData ? : { type ? : any } }
) = > void
2021-10-06 17:40:01 +02:00
) = > void
2022-04-27 11:50:29 +02:00
} ) = >
handleExternals ( context , request , dependencyType , ( options ) = > {
const resolveFunction = getResolve ( options )
return ( resolveContext : string , requestToResolve : string ) = >
new Promise ( ( resolve , reject ) = > {
resolveFunction (
resolveContext ,
requestToResolve ,
( err , result , resolveData ) = > {
if ( err ) return reject ( err )
if ( ! result ) return resolve ( [ null , false ] )
const isEsm = /\.js$/i . test ( result )
? resolveData ? . descriptionFileData ? . type === 'module'
: /\.mjs$/i . test ( result )
resolve ( [ result , isEsm ] )
}
)
} )
} ) ,
]
: [
// When the 'serverless' target is used all node_modules will be compiled into the output bundles
// So that the 'serverless' bundles have 0 runtime dependencies
'next/dist/compiled/@ampproject/toolbox-optimizer' , // except this one
// Mark this as external if not enabled so it doesn't cause a
// webpack error from being missing
. . . ( config . experimental . optimizeCss ? [ ] : [ 'critters' ] ) ,
] ,
2019-08-20 17:07:57 +02:00
optimization : {
2021-10-06 17:40:01 +02:00
// @ts-ignore: TODO remove ts-ignore when webpack 4 is removed
emitOnErrors : ! dev ,
2019-08-20 17:07:57 +02:00
checkWasmTypes : false ,
nodeEnv : false ,
2021-10-26 18:50:56 +02:00
. . . ( hasServerComponents
? {
2022-05-13 19:48:53 +02:00
// We have to use the names here instead of hashes to ensure the consistency between compilers.
2022-05-27 19:43:42 +02:00
moduleIds : isClient ? 'deterministic' : 'named' ,
2021-10-26 18:50:56 +02:00
}
: { } ) ,
2022-04-27 11:50:29 +02:00
splitChunks : ( ( ) : webpack . Options . SplitChunksOptions | false = > {
2022-05-13 19:48:53 +02:00
// For the edge runtime, we have to bundle all dependencies inside without dynamic `require`s.
// To make some dependencies like `react` to be shared between entrypoints, we use a special
// cache group here even under dev mode.
const edgeRSCCacheGroups = hasServerComponents
? {
rscDeps : {
enforce : true ,
name : 'rsc-runtime-deps' ,
filename : 'rsc-runtime-deps.js' ,
2022-05-19 18:44:43 +02:00
test : /(node_modules\/react\/|\/shared\/lib\/head-manager-context\.js|node_modules\/styled-jsx\/)/ ,
2022-05-13 19:48:53 +02:00
} ,
}
: undefined
if ( isEdgeServer && edgeRSCCacheGroups ) {
return {
cacheGroups : edgeRSCCacheGroups ,
}
}
2022-04-27 11:50:29 +02:00
if ( dev ) {
return false
}
if ( isNodeServer ) {
return {
// @ts-ignore
filename : '[name].js' ,
chunks : 'all' ,
minSize : 1000 ,
}
}
if ( isEdgeServer ) {
return {
// @ts-ignore
filename : 'edge-chunks/[name].js' ,
chunks : 'all' ,
minChunks : 2 ,
2022-05-13 19:48:53 +02:00
cacheGroups : edgeRSCCacheGroups ,
2022-04-27 11:50:29 +02:00
}
}
return {
// Keep main and _app chunks unsplitted in webpack 5
// as we don't need a separate vendor chunk from that
// and all other chunk depend on them so there is no
// duplication that need to be pulled out.
chunks : ( chunk ) = > ! /^(polyfills|main|pages\/_app)$/ . test ( chunk . name ) ,
cacheGroups : {
framework : {
chunks : 'all' ,
name : 'framework' ,
test ( module ) {
const resource = module . nameForCondition ? . ( )
return resource
? topLevelFrameworkPaths . some ( ( pkgPath ) = >
resource . startsWith ( pkgPath )
)
: false
} ,
priority : 40 ,
// Don't let webpack eliminate this chunk (prevents this chunk from
// becoming a part of the commons chunk)
enforce : true ,
} ,
lib : {
test ( module : {
size : Function
nameForCondition : Function
} ) : boolean {
return (
module . size ( ) > 160000 &&
/node_modules[/\\]/ . test ( module . nameForCondition ( ) || '' )
)
} ,
name ( module : {
type : string
libIdent? : Function
updateHash : ( hash : crypto.Hash ) = > void
} ) : string {
const hash = crypto . createHash ( 'sha1' )
if ( isModuleCSS ( module ) ) {
module . updateHash ( hash )
} else {
if ( ! module . libIdent ) {
throw new Error (
` Encountered unknown module type: ${ module . type } . Please open an issue. `
)
}
hash . update ( module . libIdent ( { context : dir } ) )
}
return hash . digest ( 'hex' ) . substring ( 0 , 8 )
} ,
priority : 30 ,
minChunks : 1 ,
reuseExistingChunk : true ,
} ,
} ,
maxInitialRequests : 25 ,
minSize : 20000 ,
}
} ) ( ) ,
runtimeChunk : isClient
? { name : CLIENT_STATIC_FILES_RUNTIME_WEBPACK }
: undefined ,
minimize : ! dev && isClient ,
2019-08-20 17:07:57 +02:00
minimizer : [
2019-09-17 22:05:20 +02:00
// Minify JavaScript
2021-04-18 12:28:09 +02:00
( compiler : webpack.Compiler ) = > {
// @ts-ignore No typings yet
const {
TerserPlugin ,
} = require ( './webpack/plugins/terser-webpack-plugin/src/index.js' )
new TerserPlugin ( {
cacheDir : path.join ( distDir , 'cache' , 'next-minifier' ) ,
parallel : config.experimental.cpus ,
2021-10-25 13:49:11 +02:00
swcMinify : config.swcMinify ,
2022-05-29 05:53:57 +02:00
terserOptions : {
. . . terserOptions ,
compress : {
. . . terserOptions . compress ,
. . . ( config . experimental . swcMinifyDebugOptions ? . compress ? ? { } ) ,
} ,
mangle : {
. . . terserOptions . mangle ,
. . . ( config . experimental . swcMinifyDebugOptions ? . mangle ? ? { } ) ,
} ,
} ,
2021-04-18 12:28:09 +02:00
} ) . apply ( compiler )
} ,
2019-09-17 22:05:20 +02:00
// Minify CSS
2021-04-18 12:28:09 +02:00
( compiler : webpack.Compiler ) = > {
const {
CssMinimizerPlugin ,
} = require ( './webpack/plugins/css-minimizer-plugin' )
new CssMinimizerPlugin ( {
postcssOptions : {
map : {
// `inline: false` generates the source map in a separate file.
// Otherwise, the CSS file is needlessly large.
inline : false ,
// `annotation: false` skips appending the `sourceMappingURL`
// to the end of the CSS file. Webpack already handles this.
annotation : false ,
} ,
2019-09-17 22:05:20 +02:00
} ,
2021-04-18 12:28:09 +02:00
} ) . apply ( compiler )
} ,
2020-04-25 21:00:41 +02:00
] ,
2019-08-20 17:07:57 +02:00
} ,
2016-10-14 17:05:08 +02:00
context : dir ,
2018-03-31 14:00:56 +02:00
// Kept as function to be backwards compatible
2021-05-03 12:25:44 +02:00
// @ts-ignore TODO webpack 5 typings needed
2018-01-30 16:40:52 +01:00
entry : async ( ) = > {
return {
2019-04-26 17:23:32 +02:00
. . . ( clientEntries ? clientEntries : { } ) ,
. . . entrypoints ,
2018-01-30 16:40:52 +01:00
}
} ,
2021-11-25 09:31:20 +01:00
watchOptions ,
2016-10-14 17:05:08 +02:00
output : {
2021-05-29 14:15:26 +02:00
// we must set publicPath to an empty value to override the default of
// auto which doesn't work in IE11
2021-06-18 19:12:20 +02:00
publicPath : ` ${ config . assetPrefix || '' } /_next/ ` ,
2022-04-27 11:50:29 +02:00
path : ! dev && isNodeServer ? path . join ( outputPath , 'chunks' ) : outputPath ,
2021-05-12 18:33:51 +02:00
// On the server we don't use hashes
2022-04-27 11:50:29 +02:00
filename :
isNodeServer || isEdgeServer
? dev || isEdgeServer
? ` [name].js `
: ` ../[name].js `
: ` static/chunks/ ${ isDevFallback ? 'fallback/' : '' } [name] ${
2022-05-25 11:46:26 +02:00
dev ? '' : appDir ? '-[chunkhash]' : '-[contenthash]'
2022-04-27 11:50:29 +02:00
} . js ` ,
library : isClient || isEdgeServer ? '_N_E' : undefined ,
libraryTarget : isClient || isEdgeServer ? 'assign' : 'commonjs2' ,
2021-10-06 17:40:01 +02:00
hotUpdateChunkFilename : 'static/webpack/[id].[fullhash].hot-update.js' ,
hotUpdateMainFilename :
'static/webpack/[fullhash].[runtime].hot-update.json' ,
2018-07-24 11:24:40 +02:00
// This saves chunks with the name given via `import()`
2022-04-27 11:50:29 +02:00
chunkFilename :
isNodeServer || isEdgeServer
? '[name].js'
: ` static/chunks/ ${ isDevFallback ? 'fallback/' : '' } ${
dev ? '[name]' : '[name].[contenthash]'
} . js ` ,
2018-10-02 13:10:07 +02:00
strictModuleExceptionHandling : true ,
2019-07-25 04:16:32 +02:00
crossOriginLoading : crossOrigin ,
2019-04-26 17:23:32 +02:00
webassemblyModuleFilename : 'static/wasm/[modulehash].wasm' ,
2021-10-20 23:39:55 +02:00
hashFunction : 'xxhash64' ,
hashDigestLength : 16 ,
2016-10-14 17:05:08 +02:00
} ,
2019-04-09 19:43:24 +02:00
performance : false ,
2018-08-14 00:09:05 +02:00
resolve : resolveConfig ,
2016-10-14 17:05:08 +02:00
resolveLoader : {
2019-08-27 22:37:47 +02:00
// The loaders Next.js provides
alias : [
2019-10-04 17:55:18 +02:00
'error-loader' ,
2021-08-06 16:07:36 +02:00
'next-swc-loader' ,
2019-08-27 22:37:47 +02:00
'next-client-pages-loader' ,
2021-06-04 10:06:00 +02:00
'next-image-loader' ,
2019-08-27 22:37:47 +02:00
'next-serverless-loader' ,
2021-01-20 06:25:46 +01:00
'next-style-loader' ,
2021-10-26 18:50:56 +02:00
'next-flight-client-loader' ,
'next-flight-server-loader' ,
2022-05-13 19:48:53 +02:00
'next-flight-client-entry-loader' ,
2021-10-07 01:46:46 +02:00
'noop-loader' ,
2021-10-20 19:52:11 +02:00
'next-middleware-loader' ,
2021-10-26 18:50:56 +02:00
'next-middleware-ssr-loader' ,
2022-03-02 16:09:36 +01:00
'next-middleware-wasm-loader' ,
2022-05-25 11:46:26 +02:00
'next-app-loader' ,
2019-11-11 04:24:53 +01:00
] . reduce ( ( alias , loader ) = > {
// using multiple aliases to replace `resolveLoader.modules`
alias [ loader ] = path . join ( __dirname , 'webpack' , 'loaders' , loader )
2019-08-27 22:37:47 +02:00
2019-11-11 04:24:53 +01:00
return alias
} , { } as Record < string , string > ) ,
2016-12-28 19:16:52 +01:00
modules : [
2019-04-08 14:57:21 +02:00
'node_modules' ,
2019-04-26 17:23:32 +02:00
. . . nodePathList , // Support for NODE_PATH environment variable
] ,
2021-10-06 17:40:01 +02:00
plugins : [ ] ,
2016-10-14 17:05:08 +02:00
} ,
module : {
2018-01-03 13:43:48 +01:00
rules : [
2021-10-06 17:40:01 +02:00
// TODO: FIXME: do NOT webpack 5 support with this
// x-ref: https://github.com/webpack/webpack/issues/11467
2021-10-13 17:23:50 +02:00
. . . ( ! config . experimental . fullySpecified
? [
{
test : /\.m?js/ ,
resolve : {
fullySpecified : false ,
} ,
} as any ,
]
: [ ] ) ,
2022-03-08 21:55:14 +01:00
. . . ( hasServerComponents
2022-04-27 11:50:29 +02:00
? isNodeServer || isEdgeServer
2022-03-08 21:55:14 +01:00
? [
// RSC server compilation loaders
{
2022-05-10 21:20:13 +02:00
. . . serverComponentCodeCondition ,
2022-05-13 19:48:53 +02:00
issuerLayer : 'sc_server' ,
2022-03-08 21:55:14 +01:00
use : {
loader : 'next-flight-server-loader' ,
2022-02-28 16:00:28 +01:00
} ,
2021-10-26 18:50:56 +02:00
} ,
2022-03-08 21:55:14 +01:00
{
2022-05-13 19:48:53 +02:00
test : /(\.client\.(js|cjs|mjs))$|\/next\/(link|image|head|script)/ ,
issuerLayer : 'sc_server' ,
2022-03-08 21:55:14 +01:00
use : {
2022-05-13 19:48:53 +02:00
loader : 'next-flight-client-loader' ,
2022-03-08 21:55:14 +01:00
} ,
2021-10-26 18:50:56 +02:00
} ,
2022-03-08 21:55:14 +01:00
]
2022-05-13 19:48:53 +02:00
: [ ]
: [ ] ) ,
. . . ( hasServerComponents && isEdgeServer
? [
// Move shared dependencies from sc_server and sc_client into the
// same layer.
{
2022-05-19 18:44:43 +02:00
test : /(node_modules\/react\/|\/shared\/lib\/head-manager-context\.js|node_modules\/styled-jsx\/)/ ,
2022-05-13 19:48:53 +02:00
layer : 'rsc_shared_deps' ,
} ,
]
2021-10-26 18:50:56 +02:00
: [ ] ) ,
2021-10-06 17:40:01 +02:00
{
test : /\.(js|cjs|mjs)$/ ,
issuerLayer : 'api' ,
parser : {
// Switch back to normal URL handling
url : true ,
} ,
} ,
{
oneOf : [
{
. . . codeCondition ,
issuerLayer : 'api' ,
parser : {
// Switch back to normal URL handling
url : true ,
} ,
use : defaultLoaders.babel ,
} ,
2021-10-20 19:52:11 +02:00
{
. . . codeCondition ,
issuerLayer : 'middleware' ,
2022-04-27 11:50:29 +02:00
use : getBabelOrSwcLoader ( ) ,
2021-10-20 19:52:11 +02:00
} ,
2021-10-06 17:40:01 +02:00
{
. . . codeCondition ,
2022-04-27 11:50:29 +02:00
use :
dev && isClient
? [
require . resolve (
'next/dist/compiled/@next/react-refresh-utils/loader'
) ,
defaultLoaders . babel ,
]
: defaultLoaders . babel ,
2021-10-06 17:40:01 +02:00
} ,
] ,
2019-04-21 23:25:17 +02:00
} ,
2021-10-06 17:40:01 +02:00
. . . ( ! config . images . disableStaticImages
2021-06-24 00:56:18 +02:00
? [
{
2021-10-18 19:01:02 +02:00
test : nextImageLoaderRegex ,
2021-06-24 00:56:18 +02:00
loader : 'next-image-loader' ,
issuer : { not : regexLikeCss } ,
dependency : { not : [ 'url' ] } ,
2021-07-02 13:27:32 +02:00
options : {
2022-04-27 11:50:29 +02:00
isServer : isNodeServer || isEdgeServer ,
2021-07-10 22:27:14 +02:00
isDev : dev ,
2021-09-27 23:13:23 +02:00
basePath : config.basePath ,
2021-07-10 22:27:14 +02:00
assetPrefix : config.assetPrefix ,
2021-07-02 13:27:32 +02:00
} ,
2021-06-24 00:56:18 +02:00
} ,
]
: [ ] ) ,
2022-04-27 11:50:29 +02:00
. . . ( isEdgeServer || isClient
2022-04-25 11:25:27 +02:00
? [
{
oneOf : [
{
issuerLayer : 'middleware' ,
resolve : {
fallback : {
process : require.resolve ( './polyfills/process' ) ,
} ,
} ,
} ,
{
resolve : {
// Full list of old polyfills is accessible here:
// https://github.com/webpack/webpack/blob/2a0536cf510768111a3a6dceeb14cb79b9f59273/lib/ModuleNotFoundError.js#L13-L42
fallback : {
assert : require.resolve ( 'next/dist/compiled/assert' ) ,
buffer : require.resolve ( 'next/dist/compiled/buffer/' ) ,
constants : require.resolve (
'next/dist/compiled/constants-browserify'
) ,
crypto : require.resolve (
'next/dist/compiled/crypto-browserify'
) ,
domain : require.resolve (
'next/dist/compiled/domain-browser'
) ,
http : require.resolve ( 'next/dist/compiled/stream-http' ) ,
https : require.resolve (
'next/dist/compiled/https-browserify'
) ,
os : require.resolve ( 'next/dist/compiled/os-browserify' ) ,
path : require.resolve (
'next/dist/compiled/path-browserify'
) ,
punycode : require.resolve (
'next/dist/compiled/punycode'
) ,
process : require.resolve ( './polyfills/process' ) ,
// Handled in separate alias
querystring : require.resolve (
'next/dist/compiled/querystring-es3'
) ,
stream : require.resolve (
'next/dist/compiled/stream-browserify'
) ,
string_decoder : require.resolve (
'next/dist/compiled/string_decoder'
) ,
sys : require.resolve ( 'next/dist/compiled/util/' ) ,
timers : require.resolve (
'next/dist/compiled/timers-browserify'
) ,
tty : require.resolve (
'next/dist/compiled/tty-browserify'
) ,
// Handled in separate alias
// url: require.resolve('url/'),
util : require.resolve ( 'next/dist/compiled/util/' ) ,
vm : require.resolve ( 'next/dist/compiled/vm-browserify' ) ,
zlib : require.resolve (
'next/dist/compiled/browserify-zlib'
) ,
events : require.resolve ( 'next/dist/compiled/events/' ) ,
setImmediate : require.resolve (
'next/dist/compiled/setimmediate'
) ,
} ,
} ,
} ,
] ,
} ,
]
: [ ] ) ,
2019-04-26 17:23:32 +02:00
] . filter ( Boolean ) ,
2016-10-16 06:01:17 +02:00
} ,
2018-01-30 16:40:52 +01:00
plugins : [
2022-02-24 16:56:40 +01:00
. . . ( ! dev &&
2022-04-27 11:50:29 +02:00
isEdgeServer &&
2022-02-24 16:56:40 +01:00
! ! config . experimental . middlewareSourceMaps &&
! config . productionBrowserSourceMaps
? getMiddlewareSourceMapPlugins ( )
: [ ] ) ,
2022-04-27 11:50:29 +02:00
dev && isClient && new ReactRefreshWebpackPlugin ( webpack ) ,
2021-10-26 18:50:56 +02:00
// Makes sure `Buffer` and `process` are polyfilled in client and flight bundles (same behavior as webpack 4)
2022-04-27 11:50:29 +02:00
( isClient || isEdgeServer ) &&
2021-01-11 13:31:31 +01:00
new webpack . ProvidePlugin ( {
2021-11-10 19:57:27 +01:00
// Buffer is used by getInlineScriptSource
2021-01-11 13:31:31 +01:00
Buffer : [ require . resolve ( 'buffer' ) , 'Buffer' ] ,
2021-11-10 19:57:27 +01:00
// Avoid process being overridden when in web run time
2022-04-27 11:50:29 +02:00
. . . ( isClient && { process : [ require . resolve ( 'process' ) ] } ) ,
2021-01-11 13:31:31 +01:00
} ) ,
2019-02-15 17:49:40 +01:00
new webpack . DefinePlugin ( {
2020-04-17 16:28:17 +02:00
. . . Object . keys ( process . env ) . reduce (
( prev : { [ key : string ] : string } , key : string ) = > {
if ( key . startsWith ( 'NEXT_PUBLIC_' ) ) {
prev [ ` process.env. ${ key } ` ] = JSON . stringify ( process . env [ key ] ! )
}
return prev
} ,
{ }
) ,
2019-04-26 17:23:32 +02:00
. . . Object . keys ( config . env ) . reduce ( ( acc , key ) = > {
2022-04-26 19:54:28 +02:00
errorIfEnvConflicted ( config , key )
2019-02-15 17:49:40 +01:00
return {
2019-02-08 14:38:18 +01:00
. . . acc ,
2019-04-26 17:23:32 +02:00
[ ` process.env. ${ key } ` ] : JSON . stringify ( config . env [ key ] ) ,
2019-02-15 17:49:40 +01:00
}
2019-04-26 17:23:32 +02:00
} , { } ) ,
2021-01-02 01:36:16 +01:00
// TODO: enforce `NODE_ENV` on `process.env`, and add a test:
'process.env.NODE_ENV' : JSON . stringify (
dev ? 'development' : 'production'
) ,
2022-04-27 11:50:29 +02:00
. . . ( ( isNodeServer || isEdgeServer ) && {
2022-04-26 19:54:28 +02:00
'process.env.NEXT_RUNTIME' : JSON . stringify (
2022-04-27 11:50:29 +02:00
isEdgeServer ? 'edge' : 'nodejs'
2022-04-26 19:54:28 +02:00
) ,
} ) ,
2022-05-12 18:47:34 +02:00
'process.env.__NEXT_MANUAL_CLIENT_BASE_PATH' : JSON . stringify (
config . experimental . manualClientBasePath
) ,
2022-04-26 00:01:30 +02:00
'process.env.__NEXT_NEW_LINK_BEHAVIOR' : JSON . stringify (
config . experimental . newNextLinkBehavior
) ,
2020-06-07 01:00:03 +02:00
'process.env.__NEXT_CROSS_ORIGIN' : JSON . stringify ( crossOrigin ) ,
2022-04-27 11:50:29 +02:00
'process.browser' : JSON . stringify ( isClient ) ,
2019-08-22 22:34:24 +02:00
'process.env.__NEXT_TEST_MODE' : JSON . stringify (
process . env . __NEXT_TEST_MODE
) ,
2019-03-10 05:27:33 +01:00
// This is used in client/dev-error-overlay/hot-dev-client.js to replace the dist directory
2022-04-27 11:50:29 +02:00
. . . ( dev && ( isClient || isEdgeServer )
2019-04-26 17:23:32 +02:00
? {
'process.env.__NEXT_DIST_DIR' : JSON . stringify ( distDir ) ,
}
: { } ) ,
2020-06-23 13:38:49 +02:00
'process.env.__NEXT_TRAILING_SLASH' : JSON . stringify (
2020-07-20 18:16:59 +02:00
config . trailingSlash
2020-06-23 13:38:49 +02:00
) ,
2019-09-15 23:18:11 +02:00
'process.env.__NEXT_BUILD_INDICATOR' : JSON . stringify (
config . devIndicators . buildActivity
) ,
2021-11-03 22:17:36 +01:00
'process.env.__NEXT_BUILD_INDICATOR_POSITION' : JSON . stringify (
config . devIndicators . buildActivityPosition
) ,
2019-11-01 20:13:13 +01:00
'process.env.__NEXT_PLUGINS' : JSON . stringify (
config . experimental . plugins
) ,
2019-10-26 00:20:38 +02:00
'process.env.__NEXT_STRICT_MODE' : JSON . stringify (
config . reactStrictMode
) ,
2021-06-18 01:59:28 +02:00
'process.env.__NEXT_REACT_ROOT' : JSON . stringify ( hasReactRoot ) ,
2021-10-26 18:50:56 +02:00
'process.env.__NEXT_RSC' : JSON . stringify ( hasServerComponents ) ,
2020-12-21 20:26:00 +01:00
'process.env.__NEXT_OPTIMIZE_FONTS' : JSON . stringify (
2021-04-05 19:47:03 +02:00
config . optimizeFonts && ! dev
2020-12-21 20:26:00 +01:00
) ,
2020-12-01 19:02:07 +01:00
'process.env.__NEXT_OPTIMIZE_CSS' : JSON . stringify (
2021-01-29 14:53:07 +01:00
config . experimental . optimizeCss && ! dev
2020-12-01 19:02:07 +01:00
) ,
2022-03-11 23:26:46 +01:00
'process.env.__NEXT_SCRIPT_WORKERS' : JSON . stringify (
config . experimental . nextScriptWorkers && ! dev
) ,
2020-07-06 16:27:45 +02:00
'process.env.__NEXT_SCROLL_RESTORATION' : JSON . stringify (
config . experimental . scrollRestoration
) ,
2020-10-20 18:43:24 +02:00
'process.env.__NEXT_IMAGE_OPTS' : JSON . stringify ( {
2020-10-26 21:07:52 +01:00
deviceSizes : config.images.deviceSizes ,
2020-10-27 14:19:23 +01:00
imageSizes : config.images.imageSizes ,
2020-10-20 18:43:24 +02:00
path : config.images.path ,
loader : config.images.loader ,
2022-03-14 15:25:23 +01:00
experimentalLayoutRaw : config.experimental?.images?.layoutRaw ,
2020-10-25 06:22:47 +01:00
. . . ( dev
? {
// pass domains in development to allow validating on the client
domains : config.images.domains ,
2022-05-05 04:19:16 +02:00
experimentalRemotePatterns :
config . experimental ? . images ? . remotePatterns ,
2020-10-25 06:22:47 +01:00
}
: { } ) ,
2020-10-20 18:43:24 +02:00
} ) ,
2020-06-18 12:10:20 +02:00
'process.env.__NEXT_ROUTER_BASEPATH' : JSON . stringify ( config . basePath ) ,
2020-08-13 14:39:36 +02:00
'process.env.__NEXT_HAS_REWRITES' : JSON . stringify ( hasRewrites ) ,
2020-10-27 16:30:34 +01:00
'process.env.__NEXT_I18N_SUPPORT' : JSON . stringify ( ! ! config . i18n ) ,
2020-12-04 11:14:55 +01:00
'process.env.__NEXT_I18N_DOMAINS' : JSON . stringify ( config . i18n ? . domains ) ,
2020-10-27 04:36:31 +01:00
'process.env.__NEXT_ANALYTICS_ID' : JSON . stringify ( config . analyticsId ) ,
2022-04-27 11:50:29 +02:00
. . . ( isNodeServer || isEdgeServer
2019-07-11 19:02:43 +02:00
? {
// Fix bad-actors in the npm ecosystem (e.g. `node-formidable`)
// This is typically found in unmaintained modules from the
// pre-webpack era (common in server-side code)
'global.GENTLY' : JSON . stringify ( false ) ,
}
2019-08-14 04:02:53 +02:00
: undefined ) ,
2020-04-15 08:42:37 +02:00
// stub process.env with proxy to warn a missing value is
2020-04-20 20:25:36 +02:00
// being accessed in development mode
2021-01-02 01:36:16 +01:00
. . . ( config . experimental . pageEnv && dev
2020-04-15 08:42:37 +02:00
? {
2020-04-20 20:25:36 +02:00
'process.env' : `
2022-04-27 11:50:29 +02:00
new Proxy ( $ { isNodeServer ? 'process.env' : '{}' } , {
2020-04-15 08:42:37 +02:00
get ( target , prop ) {
if ( typeof target [ prop ] === 'undefined' ) {
2021-03-29 10:25:00 +02:00
console . warn ( \ ` An environment variable ( \ ${ prop } ) that was not provided in the environment was accessed. \ nSee more info here: https://nextjs.org/docs/messages/missing-env-value \` )
2020-04-15 08:42:37 +02:00
}
return target [ prop ]
}
} )
` ,
}
: { } ) ,
2019-04-24 11:04:36 +02:00
} ) ,
2022-04-27 11:50:29 +02:00
isClient &&
2019-04-26 17:23:32 +02:00
new ReactLoadablePlugin ( {
filename : REACT_LOADABLE_MANIFEST ,
2021-04-21 13:18:05 +02:00
pagesDir ,
2021-10-26 18:50:56 +02:00
runtimeAsset : hasConcurrentFeatures
? ` server/ ${ MIDDLEWARE_REACT_LOADABLE_MANIFEST } .js `
: undefined ,
2021-12-14 11:33:04 +01:00
dev ,
2019-04-26 17:23:32 +02:00
} ) ,
2022-04-27 11:50:29 +02:00
( isClient || isEdgeServer ) && new DropClientPage ( ) ,
2021-10-26 06:22:45 +02:00
config . outputFileTracing &&
2021-08-16 21:29:11 +02:00
! isLikeServerless &&
2022-04-27 11:50:29 +02:00
( isNodeServer || isEdgeServer ) &&
2021-08-16 21:29:11 +02:00
! dev &&
2021-09-24 15:39:48 +02:00
new TraceEntryPointsPlugin ( {
appDir : dir ,
2021-10-18 19:01:02 +02:00
esmExternals : config.experimental.esmExternals ,
staticImageImports : ! config . images . disableStaticImages ,
2021-11-04 10:23:28 +01:00
outputFileTracingRoot : config.experimental.outputFileTracingRoot ,
2021-09-24 15:39:48 +02:00
} ) ,
2019-08-20 21:19:45 +02:00
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
2021-06-14 16:20:34 +02:00
config . excludeDefaultMomentLocales &&
2020-06-17 17:00:29 +02:00
new webpack . IgnorePlugin ( {
resourceRegExp : /^\.\/locale$/ ,
contextRegExp : /moment$/ ,
} ) ,
2019-04-26 17:23:32 +02:00
. . . ( dev
? ( ( ) = > {
// Even though require.cache is server only we have to clear assets from both compilations
// This is because the client compilation generates the build manifest that's used on the server side
const {
NextJsRequireCacheHotReloader ,
} = require ( './webpack/plugins/nextjs-require-cache-hot-reloader' )
2020-06-26 06:26:09 +02:00
const devPlugins = [ new NextJsRequireCacheHotReloader ( ) ]
2019-03-10 05:27:33 +01:00
2022-04-27 11:50:29 +02:00
if ( isClient || isEdgeServer ) {
2019-04-26 17:23:32 +02:00
devPlugins . push ( new webpack . HotModuleReplacementPlugin ( ) )
}
2019-03-10 05:27:33 +01:00
2019-04-26 17:23:32 +02:00
return devPlugins
} ) ( )
: [ ] ) ,
! dev &&
new webpack . IgnorePlugin ( {
2020-04-15 20:25:02 +02:00
resourceRegExp : /react-is/ ,
2021-06-30 11:43:31 +02:00
contextRegExp : /next[\\/]dist[\\/]/ ,
2019-04-26 17:23:32 +02:00
} ) ,
2022-04-27 11:50:29 +02:00
target === 'serverless' &&
( isNodeServer || isEdgeServer ) &&
new ServerlessPlugin ( ) ,
( isNodeServer || isEdgeServer ) &&
2022-03-11 14:33:40 +01:00
new PagesManifestPlugin ( {
serverless : isLikeServerless ,
dev ,
2022-04-27 11:50:29 +02:00
isEdgeRuntime : isEdgeServer ,
2022-05-25 11:46:26 +02:00
appDirEnabled : ! ! config . experimental . appDir ,
2022-03-11 14:33:40 +01:00
} ) ,
2021-10-20 19:52:11 +02:00
// MiddlewarePlugin should be after DefinePlugin so NEXT_PUBLIC_*
// replacement is done before its process.env.* handling
2022-04-27 11:50:29 +02:00
isEdgeServer && new MiddlewarePlugin ( { dev } ) ,
isClient &&
2019-08-08 19:14:33 +02:00
new BuildManifestPlugin ( {
buildId ,
2020-08-13 14:39:36 +02:00
rewrites ,
2021-04-22 13:08:47 +02:00
isDevFallback ,
2021-10-27 01:17:55 +02:00
exportRuntime : hasConcurrentFeatures ,
2022-05-25 11:46:26 +02:00
appDirEnabled : ! ! config . experimental . appDir ,
2019-08-08 19:14:33 +02:00
} ) ,
2021-08-17 09:18:47 +02:00
new ProfilingPlugin ( { runWebpackSpan } ) ,
2021-04-05 19:47:03 +02:00
config . optimizeFonts &&
2020-12-21 20:26:00 +01:00
! dev &&
2022-04-27 11:50:29 +02:00
isNodeServer &&
2020-07-30 01:19:32 +02:00
( function ( ) {
2021-08-17 09:18:08 +02:00
const { FontStylesheetGatheringPlugin } =
require ( './webpack/plugins/font-stylesheet-gathering-plugin' ) as {
FontStylesheetGatheringPlugin : typeof import ( './webpack/plugins/font-stylesheet-gathering-plugin' ) . FontStylesheetGatheringPlugin
}
2021-03-03 10:37:24 +01:00
return new FontStylesheetGatheringPlugin ( {
isLikeServerless ,
} )
2020-07-30 01:19:32 +02:00
} ) ( ) ,
2022-05-02 17:21:40 +02:00
new WellKnownErrorsPlugin ( { config } ) ,
2022-04-27 11:50:29 +02:00
isClient &&
2021-08-14 00:40:45 +02:00
new CopyFilePlugin ( {
filePath : require.resolve ( './polyfills/polyfill-nomodule' ) ,
cacheKey : process.env.__NEXT_VERSION as string ,
name : ` static/chunks/polyfills ${ dev ? '' : '-[hash]' } .js ` ,
minimize : false ,
info : {
[ CLIENT_STATIC_FILES_RUNTIME_POLYFILLS_SYMBOL ] : 1 ,
// This file is already minified
minimized : true ,
} ,
} ) ,
2021-10-26 18:50:56 +02:00
hasServerComponents &&
2022-05-24 16:54:26 +02:00
( isClient
? new FlightManifestPlugin ( {
dev ,
2022-05-25 11:46:26 +02:00
appDir : ! ! config . experimental . appDir ,
2022-05-24 16:54:26 +02:00
pageExtensions : rawPageExtensions ,
} )
: new ClientEntryPlugin ( {
dev ,
isEdgeServer ,
} ) ) ,
2021-10-26 09:37:38 +02:00
! dev &&
2022-04-27 11:50:29 +02:00
isClient &&
2021-10-26 09:37:38 +02:00
new TelemetryPlugin (
2022-03-22 01:09:03 +01:00
new Map (
2022-02-10 02:54:28 +01:00
[
2022-03-22 01:09:03 +01:00
[ 'swcLoader' , useSWCLoader ] ,
[ 'swcMinify' , config . swcMinify ] ,
[ 'swcRelay' , ! ! config . compiler ? . relay ] ,
[ 'swcStyledComponents' , ! ! config . compiler ? . styledComponents ] ,
[
'swcReactRemoveProperties' ,
! ! config . compiler ? . reactRemoveProperties ,
] ,
[
'swcExperimentalDecorators' ,
! ! jsConfig ? . compilerOptions ? . experimentalDecorators ,
] ,
[ 'swcRemoveConsole' , ! ! config . compiler ? . removeConsole ] ,
[ 'swcImportSource' , ! ! jsConfig ? . compilerOptions ? . jsxImportSource ] ,
2022-05-21 06:09:30 +02:00
[ 'swcEmotion' , ! ! config . compiler ? . emotion ] ,
2022-03-22 01:09:03 +01:00
SWCBinaryTarget ,
] . filter < [ Feature , boolean ] > ( Boolean as any )
)
2021-10-26 09:37:38 +02:00
) ,
2021-08-17 09:18:08 +02:00
] . filter ( Boolean as any as ExcludesFalse ) ,
2016-12-17 19:38:11 +01:00
}
2016-12-22 02:36:00 +01:00
2020-03-19 17:34:24 +01:00
// Support tsconfig and jsconfig baseUrl
if ( resolvedBaseUrl ) {
webpackConfig . resolve ? . modules ? . push ( resolvedBaseUrl )
}
2020-04-17 16:28:17 +02:00
if ( jsConfig ? . compilerOptions ? . paths && resolvedBaseUrl ) {
2020-04-24 15:50:36 +02:00
webpackConfig . resolve ? . plugins ? . unshift (
2020-03-23 15:45:51 +01:00
new JsConfigPathsPlugin ( jsConfig . compilerOptions . paths , resolvedBaseUrl )
)
}
2021-10-06 17:40:01 +02:00
const webpack5Config = webpackConfig as webpack5 . Configuration
2021-02-19 11:10:19 +01:00
2022-03-02 16:09:36 +01:00
webpack5Config . module ? . rules ? . unshift ( {
test : /\.wasm$/ ,
issuerLayer : 'middleware' ,
loader : 'next-middleware-wasm-loader' ,
type : 'javascript/auto' ,
resourceQuery : /module/i ,
} )
2021-10-06 17:40:01 +02:00
webpack5Config . experiments = {
layers : true ,
cacheUnaffected : true ,
2021-10-21 13:14:57 +02:00
buildHttp : Array.isArray ( config . experimental . urlImports )
? {
allowedUris : config.experimental.urlImports ,
cacheLocation : path.join ( dir , 'next.lock/data' ) ,
lockfileLocation : path.join ( dir , 'next.lock/lock.json' ) ,
}
: config . experimental . urlImports
? {
cacheLocation : path.join ( dir , 'next.lock/data' ) ,
lockfileLocation : path.join ( dir , 'next.lock/lock.json' ) ,
. . . config . experimental . urlImports ,
}
: undefined ,
2021-10-06 17:40:01 +02:00
}
2021-09-21 19:17:16 +02:00
2021-10-06 17:40:01 +02:00
webpack5Config . module ! . parser = {
javascript : {
url : 'relative' ,
} ,
}
webpack5Config . module ! . generator = {
asset : {
filename : 'static/media/[name].[hash:8][ext]' ,
} ,
}
2021-09-21 19:17:16 +02:00
2022-05-22 06:25:26 +02:00
if ( ! webpack5Config . output ) {
webpack5Config . output = { }
}
if ( isClient ) {
webpack5Config . output . trustedTypes = 'nextjs#bundler'
}
2022-04-27 11:50:29 +02:00
if ( isClient || isEdgeServer ) {
2022-05-22 06:25:26 +02:00
webpack5Config . output . enabledLibraryTypes = [ 'assign' ]
2021-10-20 19:52:11 +02:00
}
2021-10-06 17:40:01 +02:00
if ( dev ) {
// @ts-ignore unsafeCache exists
webpack5Config . module . unsafeCache = ( module ) = >
! /[\\/]pages[\\/][^\\/]+(?:$|\?|#)/ . test ( module . resource )
}
2021-09-17 21:20:09 +02:00
2021-10-21 03:25:45 +02:00
// This enables managedPaths for all node_modules
// and also for the unplugged folder when using yarn pnp
// It also add the yarn cache to the immutable paths
2021-10-06 17:40:01 +02:00
webpack5Config . snapshot = { }
if ( process . versions . pnp === '3' ) {
2021-10-21 03:25:45 +02:00
webpack5Config . snapshot . managedPaths = [
/^(.+?(?:[\\/]\.yarn[\\/]unplugged[\\/][^\\/]+)?[\\/]node_modules[\\/])/ ,
]
2021-10-06 17:40:01 +02:00
} else {
2021-10-21 03:25:45 +02:00
webpack5Config . snapshot . managedPaths = [ /^(.+?[\\/]node_modules[\\/])/ ]
2021-10-06 17:40:01 +02:00
}
2021-10-21 03:25:45 +02:00
if ( process . versions . pnp === '3' ) {
webpack5Config . snapshot . immutablePaths = [
/^(.+?[\\/]cache[\\/][^\\/]+\.zip[\\/]node_modules[\\/])/ ,
]
2021-10-06 17:40:01 +02:00
}
2021-05-19 21:43:16 +02:00
2021-10-06 17:40:01 +02:00
if ( dev ) {
if ( ! webpack5Config . optimization ) {
webpack5Config . optimization = { }
2020-07-09 14:31:06 +02:00
}
2022-03-02 21:57:50 +01:00
// For Server Components, it's necessary to have provided exports collected
// to generate the correct flight manifest.
if ( ! hasServerComponents ) {
webpack5Config . optimization . providedExports = false
}
2021-10-06 17:40:01 +02:00
webpack5Config . optimization . usedExports = false
}
2020-08-18 15:46:55 +02:00
2021-10-06 17:40:01 +02:00
const configVars = JSON . stringify ( {
crossOrigin : config.crossOrigin ,
pageExtensions : config.pageExtensions ,
trailingSlash : config.trailingSlash ,
buildActivity : config.devIndicators.buildActivity ,
2021-11-03 22:17:36 +01:00
buildActivityPosition : config.devIndicators.buildActivityPosition ,
2021-10-06 17:40:01 +02:00
productionBrowserSourceMaps : ! ! config . productionBrowserSourceMaps ,
plugins : config.experimental.plugins ,
reactStrictMode : config.reactStrictMode ,
reactMode : config.experimental.reactMode ,
optimizeFonts : config.optimizeFonts ,
optimizeCss : config.experimental.optimizeCss ,
2022-03-11 23:26:46 +01:00
nextScriptWorkers : config.experimental.nextScriptWorkers ,
2021-10-06 17:40:01 +02:00
scrollRestoration : config.experimental.scrollRestoration ,
basePath : config.basePath ,
pageEnv : config.experimental.pageEnv ,
excludeDefaultMomentLocales : config.excludeDefaultMomentLocales ,
assetPrefix : config.assetPrefix ,
2022-02-08 14:16:46 +01:00
disableOptimizedLoading ,
2021-10-06 17:40:01 +02:00
target ,
2022-04-27 11:50:29 +02:00
isEdgeRuntime : isEdgeServer ,
2021-10-06 17:40:01 +02:00
reactProductionProfiling ,
webpack : ! ! config . webpack ,
hasRewrites ,
reactRoot : config.experimental.reactRoot ,
2022-04-27 11:50:29 +02:00
runtime : config.experimental.runtime ,
2021-10-25 13:49:11 +02:00
swcMinify : config.swcMinify ,
swcLoader : useSWCLoader ,
2022-02-10 02:54:28 +01:00
removeConsole : config.compiler?.removeConsole ,
reactRemoveProperties : config.compiler?.reactRemoveProperties ,
styledComponents : config.compiler?.styledComponents ,
relay : config.compiler?.relay ,
2022-05-21 06:09:30 +02:00
emotion : config.compiler?.emotion ,
2022-03-22 14:20:57 +01:00
modularizeImports : config.experimental?.modularizeImports ,
2022-05-17 17:09:34 +02:00
legacyBrowsers : config.experimental?.legacyBrowsers ,
2021-10-06 17:40:01 +02:00
} )
2020-08-25 00:37:52 +02:00
2021-10-06 17:40:01 +02:00
const cache : any = {
type : 'filesystem' ,
// Includes:
// - Next.js version
// - next.config.js keys that affect compilation
version : ` ${ process . env . __NEXT_VERSION } | ${ configVars } ` ,
cacheDirectory : path.join ( distDir , 'cache' , 'webpack' ) ,
}
2020-08-24 03:37:48 +02:00
2021-10-06 17:40:01 +02:00
// Adds `next.config.js` as a buildDependency when custom webpack config is provided
if ( config . webpack && config . configFile ) {
cache . buildDependencies = {
config : [ config . configFile ] ,
2020-08-25 00:37:52 +02:00
}
2021-10-06 17:40:01 +02:00
}
2020-08-24 03:37:48 +02:00
2021-10-06 17:40:01 +02:00
webpack5Config . cache = cache
if ( process . env . NEXT_WEBPACK_LOGGING ) {
2021-10-11 19:31:12 +02:00
const infra = process . env . NEXT_WEBPACK_LOGGING . includes ( 'infrastructure' )
const profileClient =
2021-10-06 17:40:01 +02:00
process . env . NEXT_WEBPACK_LOGGING . includes ( 'profile-client' )
2021-10-11 19:31:12 +02:00
const profileServer =
2021-10-06 17:40:01 +02:00
process . env . NEXT_WEBPACK_LOGGING . includes ( 'profile-server' )
2021-10-11 19:31:12 +02:00
const summaryClient =
process . env . NEXT_WEBPACK_LOGGING . includes ( 'summary-client' )
const summaryServer =
process . env . NEXT_WEBPACK_LOGGING . includes ( 'summary-server' )
2021-10-06 17:40:01 +02:00
2022-04-27 11:50:29 +02:00
const profile =
( profileClient && isClient ) ||
( profileServer && ( isNodeServer || isEdgeServer ) )
const summary =
( summaryClient && isClient ) ||
( summaryServer && ( isNodeServer || isEdgeServer ) )
2021-10-11 19:31:12 +02:00
const logDefault = ! infra && ! profile && ! summary
if ( logDefault || infra ) {
2021-10-06 17:40:01 +02:00
webpack5Config . infrastructureLogging = {
level : 'verbose' ,
debug : /FileSystemInfo/ ,
2021-03-18 10:46:07 +01:00
}
2021-10-06 17:40:01 +02:00
}
2021-03-18 10:46:07 +01:00
2021-10-11 19:31:12 +02:00
if ( logDefault || profile ) {
2021-10-06 17:40:01 +02:00
webpack5Config . plugins ! . push ( ( compiler : webpack5.Compiler ) = > {
compiler . hooks . done . tap ( 'next-webpack-logging' , ( stats ) = > {
console . log (
stats . toString ( {
colors : true ,
logging : logDefault ? 'log' : 'verbose' ,
} )
)
2021-03-18 10:46:07 +01:00
} )
2021-10-06 17:40:01 +02:00
} )
2021-10-11 19:31:12 +02:00
} else if ( summary ) {
webpack5Config . plugins ! . push ( ( compiler : webpack5.Compiler ) = > {
compiler . hooks . done . tap ( 'next-webpack-logging' , ( stats ) = > {
console . log (
stats . toString ( {
preset : 'summary' ,
colors : true ,
timings : true ,
} )
)
} )
} )
2021-10-06 17:40:01 +02:00
}
2021-03-18 10:46:07 +01:00
2021-10-11 19:31:12 +02:00
if ( profile ) {
2021-10-06 17:40:01 +02:00
const ProgressPlugin =
webpack . ProgressPlugin as unknown as typeof webpack5 . ProgressPlugin
webpack5Config . plugins ! . push (
new ProgressPlugin ( {
profile : true ,
} )
)
webpack5Config . profile = true
2021-03-18 10:46:07 +01:00
}
2020-04-15 20:25:02 +02:00
}
2019-12-09 21:08:15 +01:00
webpackConfig = await buildConfiguration ( webpackConfig , {
2021-11-03 19:38:04 +01:00
supportedBrowsers ,
2019-12-09 21:08:15 +01:00
rootDirectory : dir ,
2022-01-03 18:41:50 +01:00
customAppFile : new RegExp ( escapeStringRegexp ( path . join ( pagesDir , ` _app ` ) ) ) ,
2019-12-09 21:08:15 +01:00
isDevelopment : dev ,
2022-04-27 11:50:29 +02:00
isServer : isNodeServer || isEdgeServer ,
isEdgeRuntime : isEdgeServer ,
targetWeb : isClient || isEdgeServer ,
2020-01-03 18:45:04 +01:00
assetPrefix : config.assetPrefix || '' ,
2020-05-11 04:11:48 +02:00
sassOptions : config.sassOptions ,
2021-01-01 21:30:50 +01:00
productionBrowserSourceMaps : config.productionBrowserSourceMaps ,
2021-01-11 18:19:56 +01:00
future : config.future ,
2021-10-25 01:54:16 +02:00
experimental : config.experimental ,
2021-11-02 21:25:12 +01:00
disableStaticImages : config.images.disableStaticImages ,
2019-12-09 21:08:15 +01:00
} )
2021-10-24 15:25:02 +02:00
// @ts-ignore Cache exists
webpackConfig . cache . name = ` ${ webpackConfig . name } - ${ webpackConfig . mode } ${
isDevFallback ? '-fallback' : ''
} `
2020-06-24 06:15:57 +02:00
let originalDevtool = webpackConfig . devtool
2018-01-30 16:40:52 +01:00
if ( typeof config . webpack === 'function' ) {
2019-04-26 17:23:32 +02:00
webpackConfig = config . webpack ( webpackConfig , {
dir ,
dev ,
2022-04-27 11:50:29 +02:00
isServer : isNodeServer || isEdgeServer ,
2019-04-26 17:23:32 +02:00
buildId ,
config ,
defaultLoaders ,
2022-04-27 11:50:29 +02:00
totalPages : Object.keys ( entrypoints ) . length ,
2019-04-26 17:23:32 +02:00
webpack ,
2022-04-27 11:50:29 +02:00
. . . ( isNodeServer || isEdgeServer
2022-04-26 23:05:40 +02:00
? {
2022-04-27 11:50:29 +02:00
nextRuntime : isEdgeServer ? 'edge' : 'nodejs' ,
2022-04-26 23:05:40 +02:00
}
: { } ) ,
2019-04-26 17:23:32 +02:00
} )
2019-02-28 14:39:51 +01:00
2020-12-01 22:58:52 +01:00
if ( ! webpackConfig ) {
throw new Error (
2021-10-22 01:04:40 +02:00
` Webpack config is undefined. You may have forgot to return properly from within the "webpack" method of your ${ config . configFileName } . \ n ` +
2021-03-29 10:25:00 +02:00
'See more info here https://nextjs.org/docs/messages/undefined-webpack-config'
2020-12-01 22:58:52 +01:00
)
}
2020-06-24 06:15:57 +02:00
if ( dev && originalDevtool !== webpackConfig . devtool ) {
webpackConfig . devtool = originalDevtool
devtoolRevertWarning ( originalDevtool )
}
2021-12-14 11:33:04 +01:00
// eslint-disable-next-line no-shadow
const webpack5Config = webpackConfig as webpack5 . Configuration
// disable lazy compilation of entries as next.js has it's own method here
if ( webpack5Config . experiments ? . lazyCompilation === true ) {
webpack5Config . experiments . lazyCompilation = {
entries : false ,
}
} else if (
typeof webpack5Config . experiments ? . lazyCompilation === 'object' &&
webpack5Config . experiments . lazyCompilation . entries !== false
) {
webpack5Config . experiments . lazyCompilation . entries = false
}
2020-02-17 22:16:19 +01:00
if ( typeof ( webpackConfig as any ) . then === 'function' ) {
2019-04-26 17:23:32 +02:00
console . warn (
2021-03-29 10:25:00 +02:00
'> Promise returned in next config. https://nextjs.org/docs/messages/promise-in-next-config'
2019-04-26 17:23:32 +02:00
)
2019-02-28 14:39:51 +01:00
}
2016-12-17 19:38:11 +01:00
}
2018-01-30 16:40:52 +01:00
2021-10-06 17:40:01 +02:00
if ( ! config . images . disableStaticImages ) {
2021-06-24 00:56:18 +02:00
const rules = webpackConfig . module ? . rules || [ ]
const hasCustomSvg = rules . some (
2021-06-18 02:40:22 +02:00
( rule ) = >
2021-06-24 00:56:18 +02:00
rule . loader !== 'next-image-loader' &&
'test' in rule &&
rule . test instanceof RegExp &&
rule . test . test ( '.svg' )
2021-06-18 02:40:22 +02:00
)
2021-06-24 00:56:18 +02:00
const nextImageRule = rules . find (
( rule ) = > rule . loader === 'next-image-loader'
)
if ( hasCustomSvg && nextImageRule ) {
// Exclude svg if the user already defined it in custom
// webpack config such as `@svgr/webpack` plugin or
// the `babel-plugin-inline-react-svg` plugin.
2021-10-12 01:17:47 +02:00
nextImageRule . test = /\.(png|jpg|jpeg|gif|webp|avif|ico|bmp)$/i
2021-06-24 00:56:18 +02:00
}
2021-06-18 02:40:22 +02:00
}
2021-06-09 16:51:56 +02:00
if (
config . experimental . craCompat &&
webpackConfig . module ? . rules &&
webpackConfig . plugins
) {
// CRA allows importing non-webpack handled files with file-loader
// these need to be the last rule to prevent catching other items
// https://github.com/facebook/create-react-app/blob/fddce8a9e21bf68f37054586deb0c8636a45f50b/packages/react-scripts/config/webpack.config.js#L594
const fileLoaderExclude = [ /\.(js|mjs|jsx|ts|tsx|json)$/ ]
2021-10-06 17:40:01 +02:00
const fileLoader = {
exclude : fileLoaderExclude ,
issuer : fileLoaderExclude ,
type : 'asset/resource' ,
}
2021-06-09 16:51:56 +02:00
const topRules = [ ]
const innerRules = [ ]
for ( const rule of webpackConfig . module . rules ) {
if ( rule . resolve ) {
topRules . push ( rule )
} else {
if (
rule . oneOf &&
! ( rule . test || rule . exclude || rule . resource || rule . issuer )
) {
rule . oneOf . forEach ( ( r ) = > innerRules . push ( r ) )
} else {
innerRules . push ( rule )
}
}
}
webpackConfig . module . rules = [
. . . ( topRules as any ) ,
{
oneOf : [ . . . innerRules , fileLoader ] ,
} ,
]
}
2020-06-26 06:26:09 +02:00
// Backwards compat with webpack-dev-middleware options object
if ( typeof config . webpackDevMiddleware === 'function' ) {
const options = config . webpackDevMiddleware ( {
watchOptions : webpackConfig.watchOptions ,
} )
if ( options . watchOptions ) {
webpackConfig . watchOptions = options . watchOptions
}
}
2019-12-13 21:23:28 +01:00
function canMatchCss ( rule : webpack.RuleSetCondition | undefined ) : boolean {
if ( ! rule ) {
return false
}
2020-01-10 22:07:06 +01:00
const fileNames = [
2022-02-23 13:28:17 +01:00
'/tmp/NEXTJS_CSS_DETECTION_FILE.css' ,
'/tmp/NEXTJS_CSS_DETECTION_FILE.scss' ,
'/tmp/NEXTJS_CSS_DETECTION_FILE.sass' ,
'/tmp/NEXTJS_CSS_DETECTION_FILE.less' ,
'/tmp/NEXTJS_CSS_DETECTION_FILE.styl' ,
2020-01-10 22:07:06 +01:00
]
2020-05-18 21:24:37 +02:00
if ( rule instanceof RegExp && fileNames . some ( ( input ) = > rule . test ( input ) ) ) {
2019-12-13 21:23:28 +01:00
return true
}
if ( typeof rule === 'function' ) {
2020-01-10 22:07:06 +01:00
if (
2020-05-18 21:24:37 +02:00
fileNames . some ( ( input ) = > {
2020-01-10 22:07:06 +01:00
try {
if ( rule ( input ) ) {
return true
}
} catch ( _ ) { }
return false
} )
) {
return true
}
2019-12-13 21:23:28 +01:00
}
if ( Array . isArray ( rule ) && rule . some ( canMatchCss ) ) {
return true
}
return false
}
2020-04-25 21:00:41 +02:00
const hasUserCssConfig =
webpackConfig . module ? . rules . some (
2020-05-18 21:24:37 +02:00
( rule ) = > canMatchCss ( rule . test ) || canMatchCss ( rule . include )
2020-04-25 21:00:41 +02:00
) ? ? false
2020-03-10 19:29:40 +01:00
2020-04-25 21:00:41 +02:00
if ( hasUserCssConfig ) {
// only show warning for one build
2022-04-27 11:50:29 +02:00
if ( isNodeServer || isEdgeServer ) {
2020-04-25 21:00:41 +02:00
console . warn (
chalk . yellow . bold ( 'Warning: ' ) +
chalk . bold (
'Built-in CSS support is being disabled due to custom CSS configuration being detected.\n'
) +
2021-03-29 10:25:00 +02:00
'See here for more info: https://nextjs.org/docs/messages/built-in-css-disabled\n'
2020-04-25 21:00:41 +02:00
)
}
if ( webpackConfig . module ? . rules . length ) {
2021-11-29 15:19:39 +01:00
// Remove default CSS Loaders
webpackConfig . module . rules . forEach ( ( r ) = > {
if ( Array . isArray ( r . oneOf ) ) {
r . oneOf = r . oneOf . filter (
( o ) = > ( o as any ) [ Symbol . for ( '__next_css_remove' ) ] !== true
2020-04-25 21:00:41 +02:00
)
2021-11-29 15:19:39 +01:00
}
} )
2019-12-13 21:23:28 +01:00
}
2020-04-25 21:00:41 +02:00
if ( webpackConfig . plugins ? . length ) {
// Disable CSS Extraction Plugin
webpackConfig . plugins = webpackConfig . plugins . filter (
2020-05-18 21:24:37 +02:00
( p ) = > ( p as any ) . __next_css_remove !== true
2020-04-25 21:00:41 +02:00
)
}
if ( webpackConfig . optimization ? . minimizer ? . length ) {
// Disable CSS Minifier
2021-08-17 09:18:08 +02:00
webpackConfig . optimization . minimizer =
webpackConfig . optimization . minimizer . filter (
( e ) = > ( e as any ) . __next_css_remove !== true
)
2020-04-25 21:00:41 +02:00
}
2019-12-13 21:23:28 +01:00
}
2020-08-04 23:24:56 +02:00
// Inject missing React Refresh loaders so that development mode is fast:
2022-04-27 11:50:29 +02:00
if ( dev && isClient ) {
2020-08-04 23:24:56 +02:00
attachReactRefresh ( webpackConfig , defaultLoaders . babel )
}
2019-04-25 22:49:39 +02:00
// check if using @zeit/next-typescript and show warning
2019-04-26 17:23:32 +02:00
if (
2022-04-27 11:50:29 +02:00
( isNodeServer || isEdgeServer ) &&
2019-04-26 17:23:32 +02:00
webpackConfig . module &&
2019-04-25 22:49:39 +02:00
Array . isArray ( webpackConfig . module . rules )
) {
let foundTsRule = false
2019-04-26 17:23:32 +02:00
webpackConfig . module . rules = webpackConfig . module . rules . filter (
( rule ) : boolean = > {
2019-04-25 22:49:39 +02:00
if ( ! ( rule . test instanceof RegExp ) ) return true
2019-04-26 17:23:32 +02:00
if ( 'noop.ts' . match ( rule . test ) && ! 'noop.js' . match ( rule . test ) ) {
2019-04-25 22:49:39 +02:00
// remove if it matches @zeit/next-typescript
foundTsRule = rule . use === defaultLoaders . babel
return ! foundTsRule
}
return true
2019-04-26 17:23:32 +02:00
}
)
2019-04-25 22:49:39 +02:00
if ( foundTsRule ) {
2019-04-26 17:23:32 +02:00
console . warn (
2021-10-22 01:04:40 +02:00
` \ n@zeit/next-typescript is no longer needed since Next.js has built-in support for TypeScript now. Please remove it from your ${ config . configFileName } and your .babelrc \ n `
2019-04-26 17:23:32 +02:00
)
2019-04-25 22:49:39 +02:00
}
}
2019-11-11 04:56:29 +01:00
// Patch `@zeit/next-sass`, `@zeit/next-less`, `@zeit/next-stylus` for compatibility
2019-10-05 04:53:14 +02:00
if ( webpackConfig . module && Array . isArray ( webpackConfig . module . rules ) ) {
2021-08-17 09:18:08 +02:00
; [ ] . forEach . call (
webpackConfig . module . rules ,
function ( rule : webpack.RuleSetRule ) {
if ( ! ( rule . test instanceof RegExp && Array . isArray ( rule . use ) ) ) {
return
}
2019-10-03 19:10:42 +02:00
2021-08-17 09:18:08 +02:00
const isSass =
rule . test . source === '\\.scss$' || rule . test . source === '\\.sass$'
const isLess = rule . test . source === '\\.less$'
const isCss = rule . test . source === '\\.css$'
const isStylus = rule . test . source === '\\.styl$'
2019-10-03 16:08:49 +02:00
2021-08-17 09:18:08 +02:00
// Check if the rule we're iterating over applies to Sass, Less, or CSS
if ( ! ( isSass || isLess || isCss || isStylus ) ) {
2019-10-03 16:08:49 +02:00
return
}
2021-08-17 09:18:08 +02:00
; [ ] . forEach . call ( rule . use , function ( use : webpack.RuleSetUseItem ) {
if (
! (
use &&
typeof use === 'object' &&
// Identify use statements only pertaining to `css-loader`
( use . loader === 'css-loader' ||
use . loader === 'css-loader/locals' ) &&
use . options &&
typeof use . options === 'object' &&
// The `minimize` property is a good heuristic that we need to
// perform this hack. The `minimize` property was only valid on
// old `css-loader` versions. Custom setups (that aren't next-sass,
// next-less or next-stylus) likely have the newer version.
// We still handle this gracefully below.
( Object . prototype . hasOwnProperty . call ( use . options , 'minimize' ) ||
Object . prototype . hasOwnProperty . call (
use . options ,
'exportOnlyLocals'
) )
)
) {
return
}
2019-10-03 16:08:49 +02:00
2021-08-17 09:18:08 +02:00
// Try to monkey patch within a try-catch. We shouldn't fail the build
// if we cannot pull this off.
// The user may not even be using the `next-sass` or `next-less` or
// `next-stylus` plugins.
// If it does work, great!
try {
// Resolve the version of `@zeit/next-css` as depended on by the Sass,
// Less or Stylus plugin.
const correctNextCss = require . resolve ( '@zeit/next-css' , {
paths : [
isCss
? // Resolve `@zeit/next-css` from the base directory
dir
: // Else, resolve it from the specific plugins
require . resolve (
isSass
? '@zeit/next-sass'
: isLess
? '@zeit/next-less'
: isStylus
? '@zeit/next-stylus'
: 'next'
) ,
] ,
2021-01-11 15:43:08 +01:00
} )
2021-08-17 09:18:08 +02:00
// If we found `@zeit/next-css` ...
if ( correctNextCss ) {
// ... resolve the version of `css-loader` shipped with that
// package instead of whichever was hoisted highest in your
// `node_modules` tree.
const correctCssLoader = require . resolve ( use . loader , {
paths : [ correctNextCss ] ,
} )
if ( correctCssLoader ) {
// We saved the user from a failed build!
use . loader = correctCssLoader
}
2019-10-03 16:08:49 +02:00
}
2021-08-17 09:18:08 +02:00
} catch ( _ ) {
// The error is not required to be handled.
2019-10-03 16:08:49 +02:00
}
2021-08-17 09:18:08 +02:00
} )
}
)
2019-10-03 16:08:49 +02:00
}
2018-07-24 11:24:40 +02:00
// Backwards compat for `main.js` entry key
2021-05-03 12:25:44 +02:00
// and setup of dependencies between entries
// we can't do that in the initial entry for
// backward-compat reasons
2019-03-24 14:33:10 +01:00
const originalEntry : any = webpackConfig . entry
2019-02-20 20:24:02 +01:00
if ( typeof originalEntry !== 'undefined' ) {
2021-05-03 12:25:44 +02:00
const updatedEntry = async ( ) = > {
2021-09-21 19:17:16 +02:00
const entry : webpack5.EntryObject =
2019-04-26 17:23:32 +02:00
typeof originalEntry === 'function'
? await originalEntry ( )
: originalEntry
2019-03-25 15:08:02 +01:00
// Server compilation doesn't have main.js
2021-05-03 12:25:44 +02:00
if (
clientEntries &&
Array . isArray ( entry [ 'main.js' ] ) &&
entry [ 'main.js' ] . length > 0
) {
2020-07-17 10:38:06 +02:00
const originalFile = clientEntries [
CLIENT_STATIC_FILES_RUNTIME_MAIN
] as string
2020-07-20 04:16:50 +02:00
entry [ CLIENT_STATIC_FILES_RUNTIME_MAIN ] = [
. . . entry [ 'main.js' ] ,
originalFile ,
]
2019-02-20 20:24:02 +01:00
}
2019-03-25 15:08:02 +01:00
delete entry [ 'main.js' ]
2018-07-24 11:24:40 +02:00
2022-04-27 11:50:29 +02:00
for ( const name of Object . keys ( entry ) ) {
entry [ name ] = finalizeEntrypoint ( {
value : entry [ name ] ,
compilerType ,
name ,
} )
2021-05-03 12:25:44 +02:00
}
2019-02-20 20:24:02 +01:00
return entry
2018-07-24 11:24:40 +02:00
}
2021-05-03 12:25:44 +02:00
// @ts-ignore webpack 5 typings needed
webpackConfig . entry = updatedEntry
2018-07-24 11:24:40 +02:00
}
2019-04-26 17:23:32 +02:00
if ( ! dev ) {
2020-02-17 22:16:19 +01:00
// entry is always a function
webpackConfig . entry = await ( webpackConfig . entry as webpack . EntryFunc ) ( )
2019-04-22 20:57:02 +02:00
}
2018-01-30 16:40:52 +01:00
return webpackConfig
2016-10-14 17:05:08 +02:00
}
2022-04-26 19:54:28 +02:00
function errorIfEnvConflicted ( config : NextConfigComplete , key : string ) {
const isPrivateKey = /^(?:NODE_.+)|^(?:__.+)$/i . test ( key )
const hasNextRuntimeKey = key === 'NEXT_RUNTIME'
if ( isPrivateKey || hasNextRuntimeKey ) {
throw new Error (
` The key " ${ key } " under "env" in ${ config . configFileName } is not allowed. https://nextjs.org/docs/messages/env-key-not-allowed `
)
}
}