UNPKG

webpack-v5-chain

Version:

Use a chaining API to generate and simplify the modification of webpack 5 configurations.

449 lines (402 loc) 18.7 kB
import Webpack from 'webpack'; import { Configuration } from 'webpack-dev-server'; /* eslint-disable @typescript-eslint/no-explicit-any */ interface Orderable { before(name: string): this; after(name: string): this; } // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters declare class Chained<Parent> { batch(handler: (chained: this) => void): this; end(): Parent; } declare class TypedChainedMap<Parent, OptionsType> extends Chained<Parent> { clear(): this; delete(key: string): this; has(key: string): boolean; get<T extends keyof OptionsType>(key: T): OptionsType[T]; getOrCompute<T extends keyof OptionsType>( key: T, compute: () => OptionsType[T], ): OptionsType[T]; set<T extends keyof OptionsType>(key: T, value: OptionsType[T]): this; merge(obj: Partial<OptionsType>): this; entries(): OptionsType; values<T extends keyof OptionsType>(): [OptionsType[T]][]; when( condition: boolean, trueHandler: (obj: this) => void, falseHandler?: (obj: this) => void, ): this; } declare class ChainedMap<Parent> extends TypedChainedMap<Parent, any> {} declare class TypedChainedSet<Parent, Value> extends Chained<Parent> { add(value: Value): this; prepend(value: Value): this; clear(): this; delete(key: string): this; has(key: string): boolean; merge(arr: Value[]): this; values(): Value[]; when( condition: boolean, trueHandler: (obj: this) => void, falseHandler?: (obj: this) => void, ): this; } declare class ChainedSet<Parent> extends TypedChainedSet<Parent, any> {} /* eslint-disable @typescript-eslint/no-explicit-any */ type WebpackConfig = Required<Webpack.Configuration>; declare class Config extends ChainedMap<void> { entryPoints: TypedChainedMap<Config, Record<string, EntryPoint>>; output: Output; module: Module; optimization: Optimization; performance: Performance & ((value: boolean) => this); plugins: Plugins<this, Webpack.WebpackPluginInstance>; resolve: Resolve; resolveLoader: ResolveLoader; devServer: DevServer; entry(name: string): EntryPoint; plugin(name: string): Plugin<this, Webpack.WebpackPluginInstance>; context(value: WebpackConfig["context"]): this; mode(value: WebpackConfig["mode"]): this; cache(value: WebpackConfig["cache"]): this; devtool(value: WebpackConfig["devtool"]): this; target(value: WebpackConfig["target"]): this; watch(value: WebpackConfig["watch"]): this; watchOptions(value: WebpackConfig["watchOptions"]): this; externals(value: WebpackConfig["externals"]): this; externalsType(value: WebpackConfig["externalsType"]): this; externalsPresets(value: WebpackConfig["externalsPresets"]): this; node(value: WebpackConfig["node"]): this; stats(value: WebpackConfig["stats"]): this; experiments(value: WebpackConfig["experiments"]): this; infrastructureLogging(value: WebpackConfig["infrastructureLogging"]): this; amd(value: WebpackConfig["amd"]): this; bail(value: WebpackConfig["bail"]): this; dependencies(value: WebpackConfig["dependencies"]): this; ignoreWarnings(value: WebpackConfig["ignoreWarnings"]): this; loader(value: WebpackConfig["loader"]): this; name(value: WebpackConfig["name"]): this; parallelism(value: WebpackConfig["parallelism"]): this; profile(value: WebpackConfig["profile"]): this; recordsInputPath(value: WebpackConfig["recordsInputPath"]): this; recordsOutputPath(value: WebpackConfig["recordsOutputPath"]): this; recordsPath(value: WebpackConfig["recordsPath"]): this; snapshot(value: WebpackConfig["snapshot"]): this; toConfig(): Webpack.Configuration; } declare class Plugins< Parent, PluginType extends Webpack.WebpackPluginInstance, > extends TypedChainedMap<Parent, Record<string, Plugin<Parent, PluginType>>> {} declare class Plugin< Parent, PluginType extends Webpack.WebpackPluginInstance | ResolvePlugin, > extends ChainedMap<Parent> implements Orderable { init<P extends PluginType | PluginClass<PluginType>>( value: ( plugin: P, args: P extends PluginClass<PluginType> ? ConstructorParameters<P> : any[], ) => PluginType, ): this; use<P extends string | PluginType | PluginClass<PluginType>>( plugin: P, args?: P extends PluginClass<PluginType> ? ConstructorParameters<P> : any[], ): this; tap<P extends PluginClass<PluginType>>( f: (args: ConstructorParameters<P>) => ConstructorParameters<P>, ): this; // Orderable before(name: string): this; after(name: string): this; } type WebpackEntry = NonNullable<Webpack.Configuration["entry"]>; type WebpackEntryObject = Exclude< WebpackEntry, // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type string | string[] | Function >[string]; declare class EntryPoint extends TypedChainedSet<Config, WebpackEntryObject> {} type WebpackModule = Required<NonNullable<Webpack.Configuration["module"]>>; declare class Module extends ChainedMap<Config> { rules: TypedChainedMap<this, Record<string, Rule>>; generator: ChainedMap<this>; parser: ChainedMap<this>; rule(name: string): Rule; noParse(value: WebpackModule["noParse"]): this; unsafeCache(value: WebpackModule["unsafeCache"]): this; exprContextCritical(value: WebpackModule["exprContextCritical"]): this; exprContextRecursive(value: WebpackModule["exprContextRecursive"]): this; exprContextRegExp(value: WebpackModule["exprContextRegExp"]): this; unknownContextCritical(value: WebpackModule["unknownContextCritical"]): this; unknownContextRecursive( value: WebpackModule["unknownContextRecursive"], ): this; unknownContextRegExp(value: WebpackModule["unknownContextRegExp"]): this; unknownContextRequest(value: WebpackModule["unknownContextRequest"]): this; wrappedContextCritical(value: WebpackModule["wrappedContextCritical"]): this; wrappedContextRecursive( value: WebpackModule["wrappedContextRecursive"], ): this; wrappedContextRegExp(value: WebpackModule["wrappedContextRegExp"]): this; strictExportPresence(value: WebpackModule["strictExportPresence"]): this; } type WebpackOutput = Required<NonNullable<Webpack.Configuration["output"]>>; declare class Output extends ChainedMap<Config> { assetModuleFilename(value: WebpackOutput["assetModuleFilename"]): this; asyncChunks(value: WebpackOutput["asyncChunks"]): this; auxiliaryComment(value: WebpackOutput["auxiliaryComment"]): this; charset(value: WebpackOutput["charset"]): this; chunkFilename(value: WebpackOutput["chunkFilename"]): this; chunkFormat(value: WebpackOutput["chunkFormat"]): this; chunkLoadTimeout(value: WebpackOutput["chunkLoadTimeout"]): this; chunkLoadingGlobal(value: WebpackOutput["chunkLoadingGlobal"]): this; chunkLoading(value: WebpackOutput["chunkLoading"]): this; clean(value: WebpackOutput["clean"]): this; compareBeforeEmit(value: WebpackOutput["compareBeforeEmit"]): this; crossOriginLoading(value: WebpackOutput["crossOriginLoading"]): this; cssChunkFilename(value: WebpackOutput["cssChunkFilename"]): this; cssFilename(value: WebpackOutput["cssFilename"]): this; devtoolFallbackModuleFilenameTemplate( value: WebpackOutput["devtoolFallbackModuleFilenameTemplate"], ): this; devtoolModuleFilenameTemplate( value: WebpackOutput["devtoolModuleFilenameTemplate"], ): this; devtoolNamespace(value: WebpackOutput["devtoolNamespace"]): this; enabledChunkLoadingTypes( value: WebpackOutput["enabledChunkLoadingTypes"], ): this; enabledLibraryTypes(value: WebpackOutput["enabledLibraryTypes"]): this; enabledWasmLoadingTypes( value: WebpackOutput["enabledWasmLoadingTypes"], ): this; environment(value: WebpackOutput["environment"]): this; filename(value: WebpackOutput["filename"]): this; globalObject(value: WebpackOutput["globalObject"]): this; hashDigest(value: WebpackOutput["hashDigest"]): this; hashDigestLength(value: WebpackOutput["hashDigestLength"]): this; hashFunction(value: WebpackOutput["hashFunction"]): this; hashSalt(value: WebpackOutput["hashSalt"]): this; hotUpdateChunkFilename(value: WebpackOutput["hotUpdateChunkFilename"]): this; hotUpdateGlobal(value: WebpackOutput["hotUpdateGlobal"]): this; hotUpdateMainFilename(value: WebpackOutput["hotUpdateMainFilename"]): this; iife(value: WebpackOutput["iife"]): this; ignoreBrowserWarnings(value: WebpackOutput["ignoreBrowserWarnings"]): this; importFunctionName(value: WebpackOutput["importFunctionName"]): this; importMetaName(value: WebpackOutput["importMetaName"]): this; library(value: WebpackOutput["library"]): this; libraryExport(value: WebpackOutput["libraryExport"]): this; libraryTarget(value: WebpackOutput["libraryTarget"]): this; module(value: WebpackOutput["module"]): this; path(value: WebpackOutput["path"]): this; pathinfo(value: WebpackOutput["pathinfo"]): this; publicPath(value: WebpackOutput["publicPath"]): this; scriptType(value: WebpackOutput["scriptType"]): this; sourceMapFilename(value: WebpackOutput["sourceMapFilename"]): this; sourcePrefix(value: WebpackOutput["sourcePrefix"]): this; strictModuleErrorHandling( value: WebpackOutput["strictModuleErrorHandling"], ): this; strictModuleExceptionHandling( value: WebpackOutput["strictModuleExceptionHandling"], ): this; trustedTypes(value: WebpackOutput["trustedTypes"]): this; umdNamedDefine(value: WebpackOutput["umdNamedDefine"]): this; uniqueName(value: WebpackOutput["uniqueName"]): this; wasmLoading(value: WebpackOutput["wasmLoading"]): this; webassemblyModuleFilename( value: WebpackOutput["webassemblyModuleFilename"], ): this; workerChunkLoading(value: WebpackOutput["workerChunkLoading"]): this; workerPublicPath(value: WebpackOutput["workerPublicPath"]): this; workerWasmLoading(value: WebpackOutput["workerWasmLoading"]): this; } type DevServerOptions = Configuration; // await for @types/webpack-dev-server update do v4 to remove all any declare class DevServer extends ChainedMap<Config> { allowedHosts: TypedChainedSet<this, string>; after( value: (app: any, server: any, compiler: Webpack.Compiler) => void, ): this; before( value: (app: any, server: any, compiler: Webpack.Compiler) => void, ): this; app(value: DevServerOptions["app"]): this; bonjour(value: DevServerOptions["bonjour"]): this; client(value: DevServerOptions["client"]): this; compress(value: DevServerOptions["compress"]): this; devMiddleware(value: DevServerOptions["devMiddleware"]): this; headers(value: DevServerOptions["headers"]): this; historyApiFallback(value: DevServerOptions["historyApiFallback"]): this; host(value: DevServerOptions["host"]): this; hot(value: DevServerOptions["hot"]): this; ipc(value: DevServerOptions["ipc"]): this; liveReload(value: DevServerOptions["liveReload"]): this; onListening(value: DevServerOptions["onListening"]): this; open(value: DevServerOptions["open"]): this; port(value: DevServerOptions["port"]): this; proxy(value: DevServerOptions["proxy"]): this; server(value: DevServerOptions["server"]): this; setupExitSignals(value: DevServerOptions["setupExitSignals"]): this; setupMiddlewares(value: DevServerOptions["setupMiddlewares"]): this; static(value: DevServerOptions["static"]): this; watchFiles(value: DevServerOptions["watchFiles"]): this; webSocketServer(value: DevServerOptions["webSocketServer"]): this; } type WebpackPerformance = Exclude< Required<NonNullable<Webpack.Configuration["performance"]>>, false >; declare class Performance extends ChainedMap<Config> { hints(value: WebpackPerformance["hints"]): this; maxEntrypointSize(value: WebpackPerformance["maxEntrypointSize"]): this; maxAssetSize(value: WebpackPerformance["maxAssetSize"]): this; assetFilter(value: WebpackPerformance["assetFilter"]): this; } type WebpackResolve = Required<NonNullable<Webpack.Configuration["resolve"]>>; type ResolvePlugin = Exclude< NonNullable<Webpack.ResolveOptions["plugins"]>[number], "..." >; declare class Resolve<T = Config> extends ChainedMap<T> { alias: TypedChainedMap<this, Record<string, string | false | string[]>>; aliasFields: TypedChainedSet<this, WebpackResolve["aliasFields"][number]>; byDependency: TypedChainedMap<this, WebpackResolve["byDependency"]>; conditionNames: TypedChainedSet< this, WebpackResolve["conditionNames"][number] >; descriptionFiles: TypedChainedSet< this, WebpackResolve["descriptionFiles"][number] >; exportsFields: TypedChainedSet<this, WebpackResolve["exportsFields"][number]>; extensionAlias: TypedChainedMap<this, WebpackResolve["extensionAlias"]>; extensions: TypedChainedSet<this, WebpackResolve["extensions"][number]>; fallback: TypedChainedMap<this, Record<string, string | false | string[]>>; importsFields: TypedChainedSet<this, WebpackResolve["importsFields"][number]>; mainFields: TypedChainedSet<this, WebpackResolve["mainFields"][number]>; mainFiles: TypedChainedSet<this, WebpackResolve["mainFiles"][number]>; modules: TypedChainedSet<this, WebpackResolve["modules"][number]>; plugins: TypedChainedMap< this, Record<string, Plugin<Resolve, ResolvePlugin>> >; restrictions: TypedChainedSet<this, WebpackResolve["restrictions"][number]>; roots: TypedChainedSet<this, WebpackResolve["roots"][number]>; plugin(name: string): Plugin<this, ResolvePlugin>; cache(value: WebpackResolve["cache"]): this; cachePredicate(value: WebpackResolve["cachePredicate"]): this; cacheWithContext(value: WebpackResolve["cacheWithContext"]): this; enforceExtension(value: WebpackResolve["enforceExtension"]): this; fullySpecified(value: WebpackResolve["fullySpecified"]): this; preferAbsolute(value: WebpackResolve["preferAbsolute"]): this; preferRelative(value: WebpackResolve["preferRelative"]): this; symlinks(value: WebpackResolve["symlinks"]): this; unsafeCache(value: WebpackResolve["unsafeCache"]): this; useSyncFileSystemCalls(value: WebpackResolve["useSyncFileSystemCalls"]): this; } declare class RuleResolve<T = Config> extends Resolve<T> { fullySpecified(value: boolean): this; } declare class ResolveLoader extends Resolve { modules: ChainedSet<this>; moduleExtensions: ChainedSet<this>; packageMains: ChainedSet<this>; } type WebpackRuleSet = Required<Webpack.RuleSetRule>; declare class Rule<T = Module> extends ChainedMap<T> implements Orderable { uses: TypedChainedMap<this, Record<string, Use>>; include: TypedChainedSet<this, WebpackRuleSet["include"]>; exclude: TypedChainedSet<this, WebpackRuleSet["exclude"]>; rules: TypedChainedMap<this, Record<string, Rule<Rule>>>; oneOfs: TypedChainedMap<this, Record<string, Rule<Rule>>>; resolve: RuleResolve<Rule<T>>; assert(value: WebpackRuleSet["assert"]): this; compiler(value: WebpackRuleSet["compiler"]): this; enforce(value: WebpackRuleSet["enforce"]): this; issuer(value: WebpackRuleSet["issuer"]): this; issuerLayer(value: WebpackRuleSet["issuerLayer"]): this; layer(value: WebpackRuleSet["layer"]): this; mimetype(value: WebpackRuleSet["mimetype"]): this; parser(value: WebpackRuleSet["parser"]): this; generator(value: WebpackRuleSet["generator"]): this; resource(value: WebpackRuleSet["resource"]): this; resourceQuery(value: WebpackRuleSet["resourceQuery"]): this; scheme(value: WebpackRuleSet["scheme"]): this; sideEffects(value: WebpackRuleSet["sideEffects"]): this; test(value: WebpackRuleSet["test"]): this; type(value: WebpackRuleSet["type"]): this; with(value: WebpackRuleSet["with"]): this; use(name: string): Use<this>; rule(name: string): Rule<Rule>; oneOf(name: string): Rule<Rule>; pre(): this; post(): this; before(name: string): this; after(name: string): this; } type WebpackOptimization = Required< NonNullable<Webpack.Configuration["optimization"]> >; type SplitChunksObject = Exclude<WebpackOptimization["splitChunks"], false>; declare class Optimization extends ChainedMap<Config> { checkWasmTypes(value: WebpackOptimization["checkWasmTypes"]): this; chunkIds(value: WebpackOptimization["chunkIds"]): this; concatenateModules(value: WebpackOptimization["concatenateModules"]): this; emitOnErrors(value: WebpackOptimization["emitOnErrors"]): this; avoidEntryIife(value: WebpackOptimization["avoidEntryIife"]): this; flagIncludedChunks(value: WebpackOptimization["flagIncludedChunks"]): this; innerGraph(value: WebpackOptimization["innerGraph"]): this; mangleExports(value: WebpackOptimization["mangleExports"]): this; mangleWasmImports(value: WebpackOptimization["mangleWasmImports"]): this; mergeDuplicateChunks( value: WebpackOptimization["mergeDuplicateChunks"], ): this; minimize(value: WebpackOptimization["minimize"]): this; minimizer(name: string): Plugin<this, Webpack.WebpackPluginInstance>; moduleIds(value: WebpackOptimization["moduleIds"]): this; nodeEnv(value: WebpackOptimization["nodeEnv"]): this; portableRecords(value: WebpackOptimization["portableRecords"]): this; providedExports(value: WebpackOptimization["providedExports"]): this; realContentHash(value: WebpackOptimization["realContentHash"]): this; removeAvailableModules( value: WebpackOptimization["removeAvailableModules"], ): this; removeEmptyChunks(value: WebpackOptimization["removeEmptyChunks"]): this; runtimeChunk(value: WebpackOptimization["runtimeChunk"]): this; sideEffects(value: WebpackOptimization["sideEffects"]): this; splitChunks: TypedChainedMap<this, SplitChunksObject> & ((value: SplitChunksObject | false) => this); usedExports(value: WebpackOptimization["usedExports"]): this; } interface RuntimeChunk { name: string | RuntimeChunkFunction; } type RuntimeChunkFunction = (entryPoint: EntryPoint) => string; type SplitChunksOptions = Record<string, any>; type LoaderOptions = Record<string, any>; declare class Use<Parent = Rule> extends ChainedMap<Parent> implements Orderable { loader(value: string): this; options(value: LoaderOptions): this; tap(f: (options: LoaderOptions) => LoaderOptions): this; // Orderable before(name: string): this; after(name: string): this; } type PluginClass< PluginType extends Webpack.WebpackPluginInstance | ResolvePlugin, > = new (...opts: any[]) => PluginType; export { Config, DevServer, EntryPoint, Module, Optimization, Output, Performance, Plugin, Plugins, Resolve, ResolveLoader, Rule, RuleResolve, Use }; export type { DevServerOptions, LoaderOptions, PluginClass, ResolvePlugin, RuntimeChunk, RuntimeChunkFunction, SplitChunksObject, SplitChunksOptions, WebpackConfig, WebpackEntry, WebpackEntryObject, WebpackModule, WebpackOptimization, WebpackOutput, WebpackPerformance, WebpackResolve, WebpackRuleSet };