@@ -847,7 +847,7 @@ class WebpackCLI {
847
847
options . entry = [ ...entries , ...( options . entry || [ ] ) ] ;
848
848
}
849
849
850
- await this . buildCommand ( options , isWatchCommandUsed ) ;
850
+ await this . runWebpack ( options , isWatchCommandUsed ) ;
851
851
} ,
852
852
) ;
853
853
} else if ( isCommand ( commandName , helpCommandOptions ) ) {
@@ -1521,107 +1521,124 @@ class WebpackCLI {
1521
1521
await this . program . parseAsync ( args , parseOptions ) ;
1522
1522
}
1523
1523
1524
- async resolveConfig ( options ) {
1525
- const loadConfig = async ( configPath ) => {
1526
- const { interpret } = this . utils ;
1527
- const ext = path . extname ( configPath ) ;
1528
- const interpreted = Object . keys ( interpret . jsVariants ) . find (
1529
- ( variant ) => variant === ext ,
1530
- ) ;
1524
+ async loadConfig ( configPath , argv = { } ) {
1525
+ const { interpret } = this . utils ;
1526
+ const ext = path . extname ( configPath ) ;
1527
+ const interpreted = Object . keys ( interpret . jsVariants ) . find ( ( variant ) => variant === ext ) ;
1531
1528
1532
- if ( interpreted ) {
1533
- const { rechoir } = this . utils ;
1534
-
1535
- try {
1536
- rechoir . prepare ( interpret . extensions , configPath ) ;
1537
- } catch ( error ) {
1538
- if ( error . failures ) {
1539
- this . logger . error ( `Unable load '${ configPath } '` ) ;
1540
- this . logger . error ( error . message ) ;
1541
-
1542
- error . failures . forEach ( ( failure ) => {
1543
- this . logger . error ( failure . error . message ) ;
1544
- } ) ;
1545
- this . logger . error ( "Please install one of them" ) ;
1546
- process . exit ( 2 ) ;
1547
- }
1548
-
1549
- this . logger . error ( error ) ;
1550
- process . exit ( 2 ) ;
1551
- }
1552
- }
1553
-
1554
- let options ;
1529
+ if ( interpreted ) {
1530
+ const { rechoir } = this . utils ;
1555
1531
1556
1532
try {
1557
- options = await this . tryRequireThenImport ( configPath , false ) ;
1533
+ rechoir . prepare ( interpret . extensions , configPath ) ;
1558
1534
} catch ( error ) {
1559
- this . logger . error ( `Failed to load '${ configPath } ' config` ) ;
1560
-
1561
- if ( this . isValidationError ( error ) ) {
1535
+ if ( error . failures ) {
1536
+ this . logger . error ( `Unable load '${ configPath } '` ) ;
1562
1537
this . logger . error ( error . message ) ;
1563
- } else {
1564
- this . logger . error ( error ) ;
1538
+
1539
+ error . failures . forEach ( ( failure ) => {
1540
+ this . logger . error ( failure . error . message ) ;
1541
+ } ) ;
1542
+ this . logger . error ( "Please install one of them" ) ;
1543
+ process . exit ( 2 ) ;
1565
1544
}
1566
1545
1546
+ this . logger . error ( error ) ;
1567
1547
process . exit ( 2 ) ;
1568
1548
}
1549
+ }
1569
1550
1570
- return { options, path : configPath } ;
1571
- } ;
1551
+ let options ;
1572
1552
1573
- const evaluateConfig = async ( loadedConfig , argv ) => {
1574
- const isMultiCompiler = Array . isArray ( loadedConfig . options ) ;
1575
- const config = isMultiCompiler ? loadedConfig . options : [ loadedConfig . options ] ;
1553
+ try {
1554
+ options = await this . tryRequireThenImport ( configPath , false ) ;
1555
+ } catch ( error ) {
1556
+ this . logger . error ( `Failed to load '${ configPath } ' config` ) ;
1557
+
1558
+ if ( this . isValidationError ( error ) ) {
1559
+ this . logger . error ( error . message ) ;
1560
+ } else {
1561
+ this . logger . error ( error ) ;
1562
+ }
1576
1563
1577
- const evaluatedConfig = await Promise . all (
1578
- config . map ( async ( rawConfig ) => {
1579
- if ( typeof rawConfig . then === "function" ) {
1580
- rawConfig = await rawConfig ;
1564
+ process . exit ( 2 ) ;
1565
+ }
1566
+
1567
+ if ( Array . isArray ( options ) ) {
1568
+ await Promise . all (
1569
+ options . map ( async ( _ , i ) => {
1570
+ if ( typeof options [ i ] . then === "function" ) {
1571
+ options [ i ] = await options [ i ] ;
1581
1572
}
1582
1573
1583
1574
// `Promise` may return `Function`
1584
- if ( typeof rawConfig === "function" ) {
1575
+ if ( typeof options [ i ] === "function" ) {
1585
1576
// when config is a function, pass the env from args to the config function
1586
- rawConfig = await rawConfig ( argv . env , argv ) ;
1577
+ options [ i ] = await options [ i ] ( argv . env , argv ) ;
1587
1578
}
1588
-
1589
- return rawConfig ;
1590
1579
} ) ,
1591
1580
) ;
1581
+ } else {
1582
+ if ( typeof options . then === "function" ) {
1583
+ options = await options ;
1584
+ }
1592
1585
1593
- loadedConfig . options = isMultiCompiler ? evaluatedConfig : evaluatedConfig [ 0 ] ;
1586
+ // `Promise` may return `Function`
1587
+ if ( typeof options === "function" ) {
1588
+ // when config is a function, pass the env from args to the config function
1589
+ options = await options ( argv . env , argv ) ;
1590
+ }
1591
+ }
1594
1592
1595
- const isObject = ( value ) => typeof value === "object" && value !== null ;
1593
+ const isObject = ( value ) => typeof value === "object" && value !== null ;
1596
1594
1597
- if ( ! isObject ( loadedConfig . options ) && ! Array . isArray ( loadedConfig . options ) ) {
1598
- this . logger . error ( `Invalid configuration in '${ loadedConfig . path } '` ) ;
1599
- process . exit ( 2 ) ;
1600
- }
1595
+ if ( ! isObject ( options ) && ! Array . isArray ( options ) ) {
1596
+ this . logger . error ( `Invalid configuration in '${ configPath } '` ) ;
1601
1597
1602
- return loadedConfig ;
1603
- } ;
1598
+ process . exit ( 2 ) ;
1599
+ }
1604
1600
1601
+ return { options, path : configPath } ;
1602
+ }
1603
+
1604
+ async resolveConfig ( options ) {
1605
1605
const config = { options : { } , path : new WeakMap ( ) } ;
1606
1606
1607
1607
if ( options . config && options . config . length > 0 ) {
1608
- const evaluatedConfigs = await Promise . all (
1609
- options . config . map ( async ( value ) =>
1610
- evaluateConfig ( await loadConfig ( path . resolve ( value ) ) , options . argv || { } ) ,
1608
+ const loadedConfigs = await Promise . all (
1609
+ options . config . map ( ( configPath ) =>
1610
+ this . loadConfig ( path . resolve ( configPath ) , options . argv ) ,
1611
1611
) ,
1612
1612
) ;
1613
1613
1614
1614
config . options = [ ] ;
1615
1615
1616
- evaluatedConfigs . forEach ( ( evaluatedConfig ) => {
1617
- if ( Array . isArray ( evaluatedConfig . options ) ) {
1618
- evaluatedConfig . options . forEach ( ( options ) => {
1619
- config . options . push ( options ) ;
1620
- config . path . set ( options , evaluatedConfig . path ) ;
1616
+ loadedConfigs . forEach ( ( loadedConfig ) => {
1617
+ const isArray = Array . isArray ( loadedConfig . options ) ;
1618
+
1619
+ // TODO we should run webpack multiple times when the `--config` options have multiple values with `--merge`, need to solve for the next major release
1620
+ if ( config . options . length === 0 ) {
1621
+ config . options = loadedConfig . options ;
1622
+ } else {
1623
+ if ( ! Array . isArray ( config . options ) ) {
1624
+ config . options = [ config . options ] ;
1625
+ }
1626
+
1627
+ if ( isArray ) {
1628
+ loadedConfig . options . forEach ( ( item ) => {
1629
+ config . options . push ( item ) ;
1630
+ } ) ;
1631
+ } else {
1632
+ config . options . push ( loadedConfig . options ) ;
1633
+ }
1634
+ }
1635
+
1636
+ if ( isArray ) {
1637
+ loadedConfig . options . forEach ( ( options ) => {
1638
+ config . path . set ( options , loadedConfig . path ) ;
1621
1639
} ) ;
1622
1640
} else {
1623
- config . options . push ( evaluatedConfig . options ) ;
1624
- config . path . set ( evaluatedConfig . options , evaluatedConfig . path ) ;
1641
+ config . path . set ( loadedConfig . options , loadedConfig . path ) ;
1625
1642
}
1626
1643
} ) ;
1627
1644
@@ -1657,23 +1674,25 @@ class WebpackCLI {
1657
1674
}
1658
1675
1659
1676
if ( foundDefaultConfigFile ) {
1660
- const loadedConfig = await loadConfig ( foundDefaultConfigFile . path ) ;
1661
- const evaluatedConfig = await evaluateConfig ( loadedConfig , options . argv || { } ) ;
1677
+ const loadedConfig = await this . loadConfig (
1678
+ foundDefaultConfigFile . path ,
1679
+ options . argv ,
1680
+ ) ;
1662
1681
1663
- config . options = evaluatedConfig . options ;
1682
+ config . options = loadedConfig . options ;
1664
1683
1665
1684
if ( Array . isArray ( config . options ) ) {
1666
- config . options . forEach ( ( options ) => {
1667
- config . path . set ( options , evaluatedConfig . path ) ;
1685
+ config . options . forEach ( ( item ) => {
1686
+ config . path . set ( item , loadedConfig . path ) ;
1668
1687
} ) ;
1669
1688
} else {
1670
- config . path . set ( evaluatedConfig . options , evaluatedConfig . path ) ;
1689
+ config . path . set ( loadedConfig . options , loadedConfig . path ) ;
1671
1690
}
1672
1691
}
1673
1692
}
1674
1693
1675
1694
if ( options . configName ) {
1676
- const notfoundConfigNames = [ ] ;
1695
+ const notFoundConfigNames = [ ] ;
1677
1696
1678
1697
config . options = options . configName . map ( ( configName ) => {
1679
1698
let found ;
@@ -1685,15 +1704,15 @@ class WebpackCLI {
1685
1704
}
1686
1705
1687
1706
if ( ! found ) {
1688
- notfoundConfigNames . push ( configName ) ;
1707
+ notFoundConfigNames . push ( configName ) ;
1689
1708
}
1690
1709
1691
1710
return found ;
1692
1711
} ) ;
1693
1712
1694
- if ( notfoundConfigNames . length > 0 ) {
1713
+ if ( notFoundConfigNames . length > 0 ) {
1695
1714
this . logger . error (
1696
- notfoundConfigNames
1715
+ notFoundConfigNames
1697
1716
. map (
1698
1717
( configName ) =>
1699
1718
`Configuration with the name "${ configName } " was not found.` ,
@@ -1731,6 +1750,18 @@ class WebpackCLI {
1731
1750
return config ;
1732
1751
}
1733
1752
1753
+ runFunctionOnOptions ( options , fn ) {
1754
+ if ( Array . isArray ( options ) ) {
1755
+ for ( let item of options ) {
1756
+ item = fn ( item ) ;
1757
+ }
1758
+ } else {
1759
+ options = fn ( options ) ;
1760
+ }
1761
+
1762
+ return options ;
1763
+ }
1764
+
1734
1765
// TODO refactor
1735
1766
async applyOptions ( config , options ) {
1736
1767
if ( options . analyze ) {
@@ -1786,9 +1817,7 @@ class WebpackCLI {
1786
1817
return configOptions ;
1787
1818
} ;
1788
1819
1789
- config . options = Array . isArray ( config . options )
1790
- ? config . options . map ( ( options ) => outputHints ( options ) )
1791
- : outputHints ( config . options ) ;
1820
+ this . runFunctionOnOptions ( config . options , outputHints ) ;
1792
1821
1793
1822
if ( this . webpack . cli ) {
1794
1823
const processArguments = ( configOptions ) => {
@@ -1850,9 +1879,7 @@ class WebpackCLI {
1850
1879
return configOptions ;
1851
1880
} ;
1852
1881
1853
- config . options = Array . isArray ( config . options )
1854
- ? config . options . map ( ( options ) => processArguments ( options ) )
1855
- : processArguments ( config . options ) ;
1882
+ this . runFunctionOnOptions ( config . options , processArguments ) ;
1856
1883
1857
1884
const setupDefaultOptions = ( configOptions ) => {
1858
1885
// No need to run for webpack@4
@@ -1881,9 +1908,7 @@ class WebpackCLI {
1881
1908
return configOptions ;
1882
1909
} ;
1883
1910
1884
- config . options = Array . isArray ( config . options )
1885
- ? config . options . map ( ( options ) => setupDefaultOptions ( options ) )
1886
- : setupDefaultOptions ( config . options ) ;
1911
+ this . runFunctionOnOptions ( config . options , setupDefaultOptions ) ;
1887
1912
}
1888
1913
1889
1914
// Logic for webpack@4
@@ -1943,12 +1968,10 @@ class WebpackCLI {
1943
1968
return configOptions ;
1944
1969
} ;
1945
1970
1946
- config . options = Array . isArray ( config . options )
1947
- ? config . options . map ( ( options ) => processLegacyArguments ( options ) )
1948
- : processLegacyArguments ( config . options ) ;
1971
+ this . runFunctionOnOptions ( config . options , processLegacyArguments ) ;
1949
1972
1950
1973
// Apply `stats` and `stats.colors` options
1951
- const applyStatsColors = ( configOptions ) => {
1974
+ const applyStatsOption = ( configOptions ) => {
1952
1975
// TODO remove after drop webpack@4
1953
1976
const statsForWebpack4 = this . webpack . Stats && this . webpack . Stats . presetToOptions ;
1954
1977
@@ -2005,24 +2028,22 @@ class WebpackCLI {
2005
2028
return configOptions ;
2006
2029
} ;
2007
2030
2008
- config . options = Array . isArray ( config . options )
2009
- ? config . options . map ( ( options ) => applyStatsColors ( options ) )
2010
- : applyStatsColors ( config . options ) ;
2031
+ this . runFunctionOnOptions ( config . options , applyStatsOption ) ;
2011
2032
2012
2033
return config ;
2013
2034
}
2014
2035
2015
2036
async applyCLIPlugin ( config , cliOptions ) {
2016
2037
const CLIPlugin = await this . tryRequireThenImport ( "./plugins/CLIPlugin" ) ;
2017
2038
2018
- const addCLIPlugin = ( configOptions ) => {
2019
- if ( ! configOptions . plugins ) {
2020
- configOptions . plugins = [ ] ;
2039
+ const addCLIPlugin = ( options ) => {
2040
+ if ( ! options . plugins ) {
2041
+ options . plugins = [ ] ;
2021
2042
}
2022
2043
2023
- configOptions . plugins . unshift (
2044
+ options . plugins . unshift (
2024
2045
new CLIPlugin ( {
2025
- configPath : config . path . get ( configOptions ) ,
2046
+ configPath : config . path . get ( options ) ,
2026
2047
helpfulOutput : ! cliOptions . json ,
2027
2048
hot : cliOptions . hot ,
2028
2049
progress : cliOptions . progress ,
@@ -2031,12 +2052,10 @@ class WebpackCLI {
2031
2052
} ) ,
2032
2053
) ;
2033
2054
2034
- return configOptions ;
2055
+ return options ;
2035
2056
} ;
2036
2057
2037
- config . options = Array . isArray ( config . options )
2038
- ? config . options . map ( ( options ) => addCLIPlugin ( options ) )
2039
- : addCLIPlugin ( config . options ) ;
2058
+ this . runFunctionOnOptions ( config . options , addCLIPlugin ) ;
2040
2059
2041
2060
return config ;
2042
2061
}
@@ -2102,7 +2121,7 @@ class WebpackCLI {
2102
2121
return compiler ;
2103
2122
}
2104
2123
2105
- async buildCommand ( options , isWatchCommand ) {
2124
+ async runWebpack ( options , isWatchCommand ) {
2106
2125
// eslint-disable-next-line prefer-const
2107
2126
let compiler ;
2108
2127
let createJsonStringifyStream ;
0 commit comments