@@ -322,37 +322,83 @@ class WebpackCLI implements IWebpackCLI {
322322 process . exit ( 2 ) ;
323323 }
324324
325- async tryRequireThenImport < T > ( module : ModuleName , handleError = true ) : Promise < T > {
325+ async tryRequireThenImport < T > (
326+ module : ModuleName ,
327+ handleError = true ,
328+ moduleType : "unknown" | "commonjs" | "esm" = "unknown" ,
329+ ) : Promise < T > {
326330 let result ;
327331
328- try {
329- result = require ( module ) ;
330- } catch ( error ) {
331- const dynamicImportLoader : null | DynamicImport < T > =
332- require ( "./utils/dynamic-import-loader" ) ( ) ;
333- if (
334- ( ( error as ImportLoaderError ) . code === "ERR_REQUIRE_ESM" ||
335- process . env . WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG ) &&
336- pathToFileURL &&
337- dynamicImportLoader
338- ) {
339- const urlForConfig = pathToFileURL ( module ) ;
340-
341- result = await dynamicImportLoader ( urlForConfig ) ;
342- result = result . default ;
332+ switch ( moduleType ) {
333+ case "unknown" : {
334+ try {
335+ result = require ( module ) ;
336+ } catch ( error ) {
337+ const dynamicImportLoader : null | DynamicImport < T > =
338+ require ( "./utils/dynamic-import-loader" ) ( ) ;
339+ if (
340+ ( ( error as ImportLoaderError ) . code === "ERR_REQUIRE_ESM" ||
341+ process . env . WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG ) &&
342+ pathToFileURL &&
343+ dynamicImportLoader
344+ ) {
345+ const urlForConfig = pathToFileURL ( module ) ;
346+
347+ result = await dynamicImportLoader ( urlForConfig ) ;
348+ result = result . default ;
349+
350+ return result ;
351+ }
343352
344- return result ;
353+ if ( handleError ) {
354+ this . logger . error ( error ) ;
355+ process . exit ( 2 ) ;
356+ } else {
357+ throw error ;
358+ }
359+ }
360+ break ;
345361 }
362+ case "commonjs" : {
363+ try {
364+ result = require ( module ) ;
365+ } catch ( error ) {
366+ if ( handleError ) {
367+ this . logger . error ( error ) ;
368+ process . exit ( 2 ) ;
369+ } else {
370+ throw error ;
371+ }
372+ }
373+ break ;
374+ }
375+ case "esm" : {
376+ try {
377+ const dynamicImportLoader : null | DynamicImport < T > =
378+ require ( "./utils/dynamic-import-loader" ) ( ) ;
346379
347- if ( handleError ) {
348- this . logger . error ( error ) ;
349- process . exit ( 2 ) ;
350- } else {
351- throw error ;
380+ if ( pathToFileURL && dynamicImportLoader ) {
381+ const urlForConfig = pathToFileURL ( module ) ;
382+
383+ result = await dynamicImportLoader ( urlForConfig ) ;
384+ result = result . default ;
385+
386+ return result ;
387+ }
388+ } catch ( error ) {
389+ if ( handleError ) {
390+ this . logger . error ( error ) ;
391+ process . exit ( 2 ) ;
392+ } else {
393+ throw error ;
394+ }
395+ }
396+
397+ break ;
352398 }
353399 }
354400
355- // For babel/typescript
401+ // For babel and other, only commonjs
356402 if ( result && typeof result === "object" && "default" in result ) {
357403 result = result . default || { } ;
358404 }
@@ -1749,8 +1795,15 @@ class WebpackCLI implements IWebpackCLI {
17491795
17501796 const interpret = require ( "interpret" ) ;
17511797 const loadConfigByPath = async ( configPath : string , argv : Argv = { } ) => {
1752- const ext = path . extname ( configPath ) ;
1753- const interpreted = Object . keys ( interpret . jsVariants ) . find ( ( variant ) => variant === ext ) ;
1798+ const ext = path . extname ( configPath ) . toLowerCase ( ) ;
1799+ let interpreted = interpret . jsVariants [ ext ] ;
1800+
1801+ // Fallback `.cts` to `.ts`
1802+ // TODO implement good `.mts` support after https://github.com/gulpjs/rechoir/issues/43
1803+ // For ESM and `.mts` you need to use: 'NODE_OPTIONS="--loader ts-node/esm" webpack-cli --config ./webpack.config.mts'
1804+ if ( ! interpreted && / \. c t s $ / . test ( ext ) ) {
1805+ interpreted = interpret . jsVariants [ ".ts" ] ;
1806+ }
17541807
17551808 if ( interpreted && ! disableInterpret ) {
17561809 const rechoir : Rechoir = require ( "rechoir" ) ;
@@ -1777,10 +1830,24 @@ class WebpackCLI implements IWebpackCLI {
17771830
17781831 type LoadConfigOption = PotentialPromise < WebpackConfiguration > ;
17791832
1833+ let moduleType : "unknown" | "commonjs" | "esm" = "unknown" ;
1834+
1835+ switch ( ext ) {
1836+ case ".cjs" :
1837+ case ".cts" :
1838+ moduleType = "commonjs" ;
1839+ break ;
1840+ case ".mjs" :
1841+ case ".mts" :
1842+ moduleType = "esm" ;
1843+ break ;
1844+ }
1845+
17801846 try {
17811847 options = await this . tryRequireThenImport < LoadConfigOption | LoadConfigOption [ ] > (
17821848 configPath ,
17831849 false ,
1850+ moduleType ,
17841851 ) ;
17851852 // @ts -expect-error error type assertion
17861853 } catch ( error : Error ) {
@@ -1897,14 +1964,15 @@ class WebpackCLI implements IWebpackCLI {
18971964 ".cjs" ,
18981965 ".ts" ,
18991966 ".cts" ,
1967+ ".mts" ,
19001968 ...Object . keys ( interpret . extensions ) ,
19011969 ] ;
19021970 // Order defines the priority, in decreasing order
1903- const defaultConfigFiles = [
1904- "webpack.config" ,
1905- ".webpack/webpack.config" ,
1906- ".webpack/webpackfile" ,
1907- ] . flatMap ( ( filename ) => extensions . map ( ( ext ) => path . resolve ( filename + ext ) ) ) ;
1971+ const defaultConfigFiles = new Set (
1972+ [ "webpack.config" , ".webpack/webpack.config" , ".webpack/webpackfile" ] . flatMap ( ( filename ) =>
1973+ extensions . map ( ( ext ) => path . resolve ( filename + ext ) ) ,
1974+ ) ,
1975+ ) ;
19081976
19091977 let foundDefaultConfigFile ;
19101978
0 commit comments