diff --git a/packages/next/build/compiler.ts b/packages/next/build/compiler.ts index 05257a29dbb33..074211a97dbf6 100644 --- a/packages/next/build/compiler.ts +++ b/packages/next/build/compiler.ts @@ -1,5 +1,5 @@ import { webpack } from 'next/dist/compiled/webpack/webpack' -import type webpack5 from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { Span } from '../trace' export type CompilerResult = { diff --git a/packages/next/build/entries.ts b/packages/next/build/entries.ts index 6882ff1ba0d11..80dcc53c9c3e3 100644 --- a/packages/next/build/entries.ts +++ b/packages/next/build/entries.ts @@ -12,7 +12,7 @@ import { ClientPagesLoaderOptions } from './webpack/loaders/next-client-pages-lo import { ServerlessLoaderQuery } from './webpack/loaders/next-serverless-loader' import { LoadedEnvFiles } from '@next/env' import { NextConfigComplete } from '../server/config-shared' -import type webpack5 from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' type ObjectValue = T extends { [key: string]: infer V } ? V : never type PagesMapping = { diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index dbeb63c0b9af2..7a5404ffe25e4 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -98,6 +98,7 @@ import { NextConfigComplete } from '../server/config-shared' import isError, { NextError } from '../lib/is-error' import { TelemetryPlugin } from './webpack/plugins/telemetry-plugin' import { MiddlewareManifest } from './webpack/plugins/middleware-plugin' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' const RESERVED_PAGE = /^\/(_app|_error|_document|api(\/|$))/ @@ -1777,7 +1778,9 @@ export default async function build( }) ) - const telemetryPlugin = clientConfig.plugins?.find(isTelemetryPlugin) + const telemetryPlugin = ( + clientConfig as webpack.Configuration + ).plugins?.find(isTelemetryPlugin) if (telemetryPlugin) { const events = eventBuildFeatureUsage(telemetryPlugin) telemetry.record(events) diff --git a/packages/next/build/output/index.ts b/packages/next/build/output/index.ts index 7701932c7fa18..9e95dc3ea35d7 100644 --- a/packages/next/build/output/index.ts +++ b/packages/next/build/output/index.ts @@ -4,13 +4,14 @@ import textTable from 'next/dist/compiled/text-table' import createStore from 'next/dist/compiled/unistore' import formatWebpackMessages from '../../client/dev/error-overlay/format-webpack-messages' import { OutputState, store as consoleStore } from './store' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' export function startedDevelopmentServer(appUrl: string, bindAddr: string) { consoleStore.setState({ appUrl, bindAddr }) } -let previousClient: import('webpack').Compiler | null = null -let previousServer: import('webpack').Compiler | null = null +let previousClient: webpack5.Compiler | null = null +let previousServer: webpack5.Compiler | null = null type CompilerDiagnostics = { modules: number @@ -207,8 +208,8 @@ export function ampValidation( } export function watchCompilers( - client: import('webpack').Compiler, - server: import('webpack').Compiler + client: webpack5.Compiler, + server: webpack5.Compiler ) { if (previousClient === client && previousServer === server) { return @@ -229,29 +230,26 @@ export function watchCompilers( onEvent({ loading: true }) }) - compiler.hooks.done.tap( - `NextJsDone-${key}`, - (stats: import('webpack5').Stats) => { - buildStore.setState({ amp: {} }) - - const { errors, warnings } = formatWebpackMessages( - stats.toJson({ - preset: 'error-warnings', - moduleTrace: true, - }) - ) - - const hasErrors = !!errors?.length - const hasWarnings = !!warnings?.length - - onEvent({ - loading: false, - modules: stats.compilation.modules.size, - errors: hasErrors ? errors : null, - warnings: hasWarnings ? warnings : null, + compiler.hooks.done.tap(`NextJsDone-${key}`, (stats: webpack5.Stats) => { + buildStore.setState({ amp: {} }) + + const { errors, warnings } = formatWebpackMessages( + stats.toJson({ + preset: 'error-warnings', + moduleTrace: true, }) - } - ) + ) + + const hasErrors = !!errors?.length + const hasWarnings = !!warnings?.length + + onEvent({ + loading: false, + modules: stats.compilation.modules.size, + errors: hasErrors ? errors : null, + warnings: hasWarnings ? warnings : null, + }) + }) } tapCompiler('client', client, (status) => { diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 6f1be734c9b4d..17cfaa41616a9 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -5,7 +5,7 @@ import { readFileSync } from 'fs' import { codeFrameColumns } from 'next/dist/compiled/babel/code-frame' import semver from 'next/dist/compiled/semver' import { webpack } from 'next/dist/compiled/webpack/webpack' -import type webpack5 from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import path, { join as pathJoin, relative as relativePath } from 'path' import escapeRegExp from 'next/dist/compiled/escape-string-regexp' import { diff --git a/packages/next/build/webpack/plugins/css-minimizer-plugin.ts b/packages/next/build/webpack/plugins/css-minimizer-plugin.ts index fbd32151281df..038189f26ec4a 100644 --- a/packages/next/build/webpack/plugins/css-minimizer-plugin.ts +++ b/packages/next/build/webpack/plugins/css-minimizer-plugin.ts @@ -2,6 +2,7 @@ import cssnanoSimple from 'cssnano-simple' import postcssScss from 'next/dist/compiled/postcss-scss' import postcss, { Parser } from 'postcss' import { webpack, sources } from 'next/dist/compiled/webpack/webpack' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { spans } from './profiling-plugin' // https://github.com/NMFR/optimize-css-assets-webpack-plugin/blob/0a410a9bf28c7b0e81a3470a13748e68ca2f50aa/src/index.js#L20 @@ -54,7 +55,7 @@ export class CssMinimizerPlugin { }) } - apply(compiler: webpack.Compiler) { + apply(compiler: webpack5.Compiler) { compiler.hooks.compilation.tap('CssMinimizerPlugin', (compilation: any) => { const cache = compilation.getCache('CssMinimizerPlugin') compilation.hooks.processAssets.tapPromise( diff --git a/packages/next/build/webpack/plugins/next-trace-entrypoints-plugin.ts b/packages/next/build/webpack/plugins/next-trace-entrypoints-plugin.ts index 14c92c8f5a2fb..3364606950e6b 100644 --- a/packages/next/build/webpack/plugins/next-trace-entrypoints-plugin.ts +++ b/packages/next/build/webpack/plugins/next-trace-entrypoints-plugin.ts @@ -8,6 +8,7 @@ import { } from 'next/dist/compiled/@vercel/nft' import { TRACE_OUTPUT_VERSION } from '../../../shared/lib/constants' import { webpack, sources } from 'next/dist/compiled/webpack/webpack' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { nextImageLoaderRegex, NODE_ESM_RESOLVE_OPTIONS, @@ -26,11 +27,11 @@ const TRACE_IGNORES = [ function getModuleFromDependency( compilation: any, dep: any -): webpack.Module & { resource?: string } { +): webpack5.Module & { resource?: string } { return compilation.moduleGraph.getModule(dep) } -export class TraceEntryPointsPlugin implements webpack.Plugin { +export class TraceEntryPointsPlugin implements webpack5.WebpackPluginInstance { private appDir: string private entryTraces: Map> private excludeFiles: string[] @@ -100,7 +101,7 @@ export class TraceEntryPointsPlugin implements webpack.Plugin { } tapfinishModules( - compilation: webpack.compilation.Compilation, + compilation: webpack5.Compilation, traceEntrypointsPluginSpan: Span, doResolve?: ( request: string, @@ -126,9 +127,7 @@ export class TraceEntryPointsPlugin implements webpack.Plugin { const depModMap = new Map() finishModulesSpan.traceChild('get-entries').traceFn(() => { - compilation.entries.forEach((entry) => { - const name = entry.name || entry.options?.name - + compilation.entries.forEach((entry, name) => { if (name?.replace(/\\/g, '/').startsWith('pages/')) { for (const dep of entry.dependencies) { if (!dep) continue @@ -369,7 +368,7 @@ export class TraceEntryPointsPlugin implements webpack.Plugin { ) } - apply(compiler: webpack.Compiler) { + apply(compiler: webpack5.Compiler) { compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { const compilationSpan = spans.get(compilation) || spans.get(compiler)! const traceEntrypointsPluginSpan = compilationSpan.traceChild( @@ -420,7 +419,7 @@ export class TraceEntryPointsPlugin implements webpack.Plugin { missingDependencies: compilation.missingDependencies, contextDependencies: compilation.contextDependencies, }, - async (err: any, result: string, resContext: any) => { + async (err: any, result?: string | false, resContext?: any) => { if (err) return reject(err) if (!result) { diff --git a/packages/next/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts b/packages/next/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts index 8f13385b68a2b..a1b26d7cd401b 100644 --- a/packages/next/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts +++ b/packages/next/build/webpack/plugins/nextjs-require-cache-hot-reloader.ts @@ -1,9 +1,12 @@ -import type { Compiler, WebpackPluginInstance } from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { clearSandboxCache } from '../../../server/web/sandbox' import { realpathSync } from 'fs' import path from 'path' import isError from '../../../lib/is-error' +type Compiler = webpack5.Compiler +type WebpackPluginInstance = webpack5.WebpackPluginInstance + const originModules = [ require.resolve('../../../server/require'), require.resolve('../../../server/load-components'), diff --git a/packages/next/build/webpack/plugins/profiling-plugin.ts b/packages/next/build/webpack/plugins/profiling-plugin.ts index edea13d7d1477..7712dd691a366 100644 --- a/packages/next/build/webpack/plugins/profiling-plugin.ts +++ b/packages/next/build/webpack/plugins/profiling-plugin.ts @@ -1,6 +1,6 @@ import { NormalModule } from 'next/dist/compiled/webpack/webpack' import { Span } from '../../../trace' -import type webpack from 'webpack' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' const pluginName = 'ProfilingPlugin' export const spans = new WeakMap() diff --git a/packages/next/build/webpack/plugins/telemetry-plugin.ts b/packages/next/build/webpack/plugins/telemetry-plugin.ts index b11f846252aed..7093aa91fee26 100644 --- a/packages/next/build/webpack/plugins/telemetry-plugin.ts +++ b/packages/next/build/webpack/plugins/telemetry-plugin.ts @@ -1,4 +1,4 @@ -import type { Compiler, Compilation } from 'webpack' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' type Feature = 'next/image' | 'next/script' | 'next/dynamic' @@ -34,7 +34,7 @@ const FEATURE_MODULE_MAP: ReadonlyMap = new Map([ * certain features (e.g. next/image and next/script) and record how many times * they are imported. */ -export class TelemetryPlugin { +export class TelemetryPlugin implements webpack.WebpackPluginInstance { private usageTracker = new Map() constructor() { @@ -46,13 +46,13 @@ export class TelemetryPlugin { } } - apply(compiler: Compiler): void { + apply(compiler: webpack.Compiler): void { compiler.hooks.make.tapAsync( TelemetryPlugin.name, - async (compilation: Compilation, callback: () => void) => { + async (compilation: webpack.Compilation, callback: () => void) => { compilation.hooks.finishModules.tapAsync( TelemetryPlugin.name, - async (modules: Set, modulesFinish: () => void) => { + async (modules: Iterable, modulesFinish: () => void) => { for (const module of modules) { const feature = findFeatureInModule(module) if (!feature) { diff --git a/packages/next/build/webpack/plugins/wellknown-errors-plugin/index.ts b/packages/next/build/webpack/plugins/wellknown-errors-plugin/index.ts index b86d2ae16af1d..c7de52cc80ac4 100644 --- a/packages/next/build/webpack/plugins/wellknown-errors-plugin/index.ts +++ b/packages/next/build/webpack/plugins/wellknown-errors-plugin/index.ts @@ -1,8 +1,8 @@ -import type webpack5 from 'webpack5' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' import { getModuleBuildError } from './webpackModuleError' export class WellKnownErrorsPlugin { - apply(compiler: webpack5.Compiler) { + apply(compiler: webpack.Compiler) { compiler.hooks.compilation.tap('WellKnownErrorsPlugin', (compilation) => { compilation.hooks.afterSeal.tapPromise( 'WellKnownErrorsPlugin', diff --git a/packages/next/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts b/packages/next/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts index e8ca933547a58..465dec54fd24a 100644 --- a/packages/next/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts +++ b/packages/next/build/webpack/plugins/wellknown-errors-plugin/parseNotFoundError.ts @@ -1,7 +1,7 @@ import Chalk from 'chalk' import { SimpleWebpackError } from './simpleWebpackError' import { createOriginalStackFrame } from '@next/react-dev-overlay/lib/middleware' -import type webpack5 from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' const chalk = new Chalk.constructor({ enabled: true }) diff --git a/packages/next/build/webpack/plugins/wellknown-errors-plugin/simpleWebpackError.ts b/packages/next/build/webpack/plugins/wellknown-errors-plugin/simpleWebpackError.ts index 1771cfb4a28b3..ac2d3263683fa 100644 --- a/packages/next/build/webpack/plugins/wellknown-errors-plugin/simpleWebpackError.ts +++ b/packages/next/build/webpack/plugins/wellknown-errors-plugin/simpleWebpackError.ts @@ -1,9 +1,9 @@ -import type webpack5 from 'webpack5' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' // This class creates a simplified webpack error that formats nicely based on // webpack's build in serializer. // https://github.com/webpack/webpack/blob/c9d4ff7b054fc581c96ce0e53432d44f9dd8ca72/lib/Stats.js#L294-L356 -export class SimpleWebpackError extends (Error as unknown as typeof webpack5.WebpackError) { +export class SimpleWebpackError extends (Error as unknown as typeof webpack.WebpackError) { file: string constructor(file: string, message: string) { diff --git a/packages/next/build/webpack/plugins/wellknown-errors-plugin/webpackModuleError.ts b/packages/next/build/webpack/plugins/wellknown-errors-plugin/webpackModuleError.ts index cbced5835c1ab..dc7e0e3cf36f3 100644 --- a/packages/next/build/webpack/plugins/wellknown-errors-plugin/webpackModuleError.ts +++ b/packages/next/build/webpack/plugins/wellknown-errors-plugin/webpackModuleError.ts @@ -1,15 +1,15 @@ import { readFileSync } from 'fs' import * as path from 'path' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' import { getBabelError } from './parseBabel' import { getCssError } from './parseCss' import { getScssError } from './parseScss' import { getNotFoundError } from './parseNotFoundError' import { SimpleWebpackError } from './simpleWebpackError' import isError from '../../../../lib/is-error' -import type webpack5 from 'webpack5' function getFileData( - compilation: webpack5.Compilation, + compilation: webpack.Compilation, m: any ): [string, string | null] { let resolved: string @@ -41,7 +41,7 @@ function getFileData( } export async function getModuleBuildError( - compilation: webpack5.Compilation, + compilation: webpack.Compilation, input: any ): Promise { if ( diff --git a/packages/next/server/config-shared.ts b/packages/next/server/config-shared.ts index 1d163de24ee99..92956781d2e77 100644 --- a/packages/next/server/config-shared.ts +++ b/packages/next/server/config-shared.ts @@ -1,5 +1,5 @@ import os from 'os' -import type webpack5 from 'webpack5' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { Header, Redirect, Rewrite } from '../lib/load-custom-routes' import { ImageConfig, diff --git a/packages/next/server/dev/hot-middleware.ts b/packages/next/server/dev/hot-middleware.ts index d912f0f2ac129..955a9e99f0c9b 100644 --- a/packages/next/server/dev/hot-middleware.ts +++ b/packages/next/server/dev/hot-middleware.ts @@ -21,7 +21,7 @@ // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -import { webpack } from 'next/dist/compiled/webpack/webpack' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' import type ws from 'ws' export class WebpackHotMiddleware { diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index d79c0fe83f4ca..21b182d6af859 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -4,6 +4,7 @@ import { WebpackHotMiddleware } from './hot-middleware' import { join, relative, isAbsolute } from 'path' import { UrlObject } from 'url' import { webpack } from 'next/dist/compiled/webpack/webpack' +import type { webpack5 } from 'next/dist/compiled/webpack/webpack' import { createEntrypoints, createPagesMapping, @@ -103,14 +104,14 @@ function findEntryModule(issuer: any): any { return issuer } -function erroredPages(compilation: webpack.compilation.Compilation) { +function erroredPages(compilation: webpack5.Compilation) { const failedPages: { [page: string]: any[] } = {} for (const error of compilation.errors) { - if (!error.origin) { + if (!error.module) { continue } - const entryModule = findEntryModule(error.origin) + const entryModule = findEntryModule(error.module) const { name } = entryModule if (!name) { continue @@ -140,8 +141,8 @@ export default class HotReloader { private pagesDir: string private webpackHotMiddleware?: WebpackHotMiddleware private config: NextConfigComplete - public clientStats: webpack.Stats | null - public serverStats: webpack.Stats | null + public clientStats: webpack5.Stats | null + public serverStats: webpack5.Stats | null private clientError: Error | null = null private serverError: Error | null = null private serverPrevDocumentHash: string | null @@ -472,7 +473,7 @@ export default class HotReloader { // @ts-ignore webpack 5 configs.parallelism = 1 - const multiCompiler = webpack(configs) + const multiCompiler = webpack(configs) as unknown as webpack5.MultiCompiler watchCompilers(multiCompiler.compilers[0], multiCompiler.compilers[1]) @@ -485,7 +486,7 @@ export default class HotReloader { const trackPageChanges = (pageHashMap: Map, changedItems: Set) => - (stats: webpack.compilation.Compilation) => { + (stats: webpack5.Compilation) => { stats.entrypoints.forEach((entry, key) => { if (key.startsWith('pages/')) { // TODO this doesn't handle on demand loaded chunks @@ -539,7 +540,7 @@ export default class HotReloader { // Initial value if (this.serverPrevDocumentHash === null) { - this.serverPrevDocumentHash = documentChunk.hash + this.serverPrevDocumentHash = documentChunk.hash || null return } @@ -550,7 +551,7 @@ export default class HotReloader { // Notify reload to reload the page, as _document.js was changed (different hash) this.send('reloadPage') - this.serverPrevDocumentHash = documentChunk.hash + this.serverPrevDocumentHash = documentChunk.hash || null } ) multiCompiler.hooks.done.tap('NextjsHotReloaderForServer', () => { diff --git a/packages/next/server/dev/on-demand-entry-handler.ts b/packages/next/server/dev/on-demand-entry-handler.ts index df65213a6fd87..c66cf46ab1d8d 100644 --- a/packages/next/server/dev/on-demand-entry-handler.ts +++ b/packages/next/server/dev/on-demand-entry-handler.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events' import { join, posix } from 'path' -import { webpack } from 'next/dist/compiled/webpack/webpack' +import type { webpack5 as webpack } from 'next/dist/compiled/webpack/webpack' import { normalizePagePath, normalizePathSep } from '../normalize-page-path' import { pageNotFoundError } from '../require' import { findPageFile } from '../lib/find-page-file' @@ -47,7 +47,7 @@ export default function onDemandEntryHandler( for (const compiler of compilers) { compiler.hooks.make.tap( 'NextJsOnDemandEntries', - (_compilation: webpack.compilation.Compilation) => { + (_compilation: webpack.Compilation) => { invalidator.startBuilding() } ) diff --git a/packages/next/types/webpack.d.ts b/packages/next/types/webpack.d.ts index dfd223784cc18..e38c9adec8913 100644 --- a/packages/next/types/webpack.d.ts +++ b/packages/next/types/webpack.d.ts @@ -29,31 +29,26 @@ declare module 'next/dist/compiled/loader-utils' declare module 'next/dist/compiled/webpack/webpack' { import webpackSources from 'webpack-sources1' import webpack4, { loader } from 'webpack4' - export { NormalModule, WebpackError } from 'webpack' + import webpack5 from 'webpack5' + export { NormalModule } from 'webpack5' export function init(): void export let BasicEvaluatedExpression: any export let GraphHelpers: any - // TODO change this to webpack4 | webpack5 export let sources: typeof webpackSources - // TODO change this to webpack - export { webpack4 as webpack, loader } + // TODO change this to webpack5 + export { webpack4 as webpack, loader, webpack4, webpack5 } } declare module 'webpack' { - import webpack4 from 'webpack4' - import webpack5 from 'webpack5' - export type Compiler = webpack4.Compiler | webpack5.Compiler - export type Compilation = - | webpack4.compilation.Compilation - | webpack5.Compilation - export type Module = webpack4.Module | webpack5.Module - export type Stats = webpack4.Stats | webpack5.Stats export { + Compiler, + Compilation, + Module, + Stats, Template, RuntimeModule, RuntimeGlobals, NormalModule, - WebpackError, } from 'webpack5' } diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 251c059de1e5e..b8565e5ddf7a8 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -30,6 +30,12 @@ }, "peerDependencies": { "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "webpack": "^4 || ^5" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } } diff --git a/packages/react-dev-overlay/src/middleware.ts b/packages/react-dev-overlay/src/middleware.ts index 24318c74c4893..828f9a6f5c1a3 100644 --- a/packages/react-dev-overlay/src/middleware.ts +++ b/packages/react-dev-overlay/src/middleware.ts @@ -11,7 +11,7 @@ import { StackFrame } from 'stacktrace-parser' import url from 'url' // @ts-ignore // eslint-disable-next-line import/no-extraneous-dependencies -import type webpack from 'webpack4' +import type webpack from 'webpack' import { getRawSourceMap } from './internal/helpers/getRawSourceMap' import { launchEditor } from './internal/helpers/launchEditor'