11import * as webpack from 'webpack' ;
22import * as path from 'path' ;
3- import { GlobCopyWebpackPlugin } from '../plugins/glob-copy-webpack-plugin' ;
4- import { packageChunkSort } from '../utilities/package-chunk-sort' ;
5- import { BaseHrefWebpackPlugin } from '@angular-cli/base-href-webpack' ;
3+ import { GlobCopyWebpackPlugin } from '../plugins/glob-copy-webpack-plugin' ;
4+ import { SuppressEntryChunksWebpackPlugin } from '../plugins/suppress-entry-chunks-webpack-plugin' ;
5+ import { packageChunkSort } from '../utilities/package-chunk-sort' ;
6+ import { BaseHrefWebpackPlugin } from '@angular-cli/base-href-webpack' ;
7+ import { extraEntryParser , makeCssLoaders } from './webpack-build-utils' ;
68
7- const ProgressPlugin = require ( 'webpack/lib/ProgressPlugin' ) ;
9+ const ProgressPlugin = require ( 'webpack/lib/ProgressPlugin' ) ;
810const HtmlWebpackPlugin = require ( 'html-webpack-plugin' ) ;
911const autoprefixer = require ( 'autoprefixer' ) ;
1012
11-
1213export function getWebpackCommonConfig (
1314 projectRoot : string ,
1415 environment : string ,
@@ -23,21 +24,60 @@ export function getWebpackCommonConfig(
2324 const appRoot = path . resolve ( projectRoot , appConfig . root ) ;
2425 const appMain = path . resolve ( appRoot , appConfig . main ) ;
2526 const nodeModules = path . resolve ( projectRoot , 'node_modules' ) ;
26- const styles = appConfig . styles
27- ? appConfig . styles . map ( ( style : string ) => path . resolve ( appRoot , style ) )
28- : [ ] ;
29- const scripts = appConfig . scripts
30- ? appConfig . scripts . map ( ( script : string ) => path . resolve ( appRoot , script ) )
31- : [ ] ;
32- const extraPlugins : any [ ] = [ ] ;
33-
34- let entry : { [ key : string ] : string [ ] } = {
27+
28+ let extraPlugins : any [ ] = [ ] ;
29+ let extraRules : any [ ] = [ ] ;
30+ let lazyChunks : string [ ] = [ ] ;
31+
32+ let entryPoints : { [ key : string ] : string [ ] } = {
3533 main : [ appMain ]
3634 } ;
3735
38- // Only add styles/scripts if there's actually entries there
39- if ( appConfig . styles . length > 0 ) { entry [ 'styles' ] = styles ; }
40- if ( appConfig . scripts . length > 0 ) { entry [ 'scripts' ] = scripts ; }
36+ // process global scripts
37+ if ( appConfig . scripts . length > 0 ) {
38+ const globalScrips = extraEntryParser ( appConfig . scripts , appRoot , 'scripts' ) ;
39+
40+ // add entry points and lazy chunks
41+ globalScrips . forEach ( script => {
42+ if ( script . lazy ) { lazyChunks . push ( script . entry ) ; }
43+ entryPoints [ script . entry ] = ( entryPoints [ script . entry ] || [ ] ) . concat ( script . path ) ;
44+ } ) ;
45+
46+ // load global scripts using script-loader
47+ extraRules . push ( {
48+ include : globalScrips . map ( ( script ) => script . path ) , test : / \. j s $ / , loader : 'script-loader'
49+ } ) ;
50+ }
51+
52+ // process global styles
53+ if ( appConfig . styles . length === 0 ) {
54+ // create css loaders for component css
55+ extraRules . push ( ...makeCssLoaders ( ) ) ;
56+ } else {
57+ const globalStyles = extraEntryParser ( appConfig . styles , appRoot , 'styles' ) ;
58+ let extractedCssEntryPoints : string [ ] = [ ] ;
59+ // add entry points and lazy chunks
60+ globalStyles . forEach ( style => {
61+ if ( style . lazy ) { lazyChunks . push ( style . entry ) ; }
62+ if ( ! entryPoints [ style . entry ] ) {
63+ // since this entry point doesn't exist yet, it's going to only have
64+ // extracted css and we can supress the entry point
65+ extractedCssEntryPoints . push ( style . entry ) ;
66+ entryPoints [ style . entry ] = ( entryPoints [ style . entry ] || [ ] ) . concat ( style . path ) ;
67+ } else {
68+ // existing entry point, just push the css in
69+ entryPoints [ style . entry ] . push ( style . path ) ;
70+ }
71+ } ) ;
72+
73+ // create css loaders for component css and for global css
74+ extraRules . push ( ...makeCssLoaders ( globalStyles . map ( ( style ) => style . path ) ) ) ;
75+
76+ if ( extractedCssEntryPoints . length > 0 ) {
77+ // don't emit the .js entry point for extracted styles
78+ extraPlugins . push ( new SuppressEntryChunksWebpackPlugin ( { chunks : extractedCssEntryPoints } ) ) ;
79+ }
80+ }
4181
4282 if ( vendorChunk ) {
4383 extraPlugins . push ( new webpack . optimize . CommonsChunkPlugin ( {
@@ -47,12 +87,7 @@ export function getWebpackCommonConfig(
4787 } ) ) ;
4888 }
4989
50- if ( progress ) {
51- extraPlugins . push ( new ProgressPlugin ( {
52- profile : verbose ,
53- colors : true
54- } ) ) ;
55- }
90+ if ( progress ) { extraPlugins . push ( new ProgressPlugin ( { profile : verbose , colors : true } ) ) ; }
5691
5792 return {
5893 devtool : sourcemap ? 'source-map' : false ,
@@ -61,7 +96,7 @@ export function getWebpackCommonConfig(
6196 modules : [ nodeModules ]
6297 } ,
6398 context : path . resolve ( __dirname , './' ) ,
64- entry : entry ,
99+ entry : entryPoints ,
65100 output : {
66101 path : path . resolve ( projectRoot , appConfig . outDir ) ,
67102 filename : '[name].bundle.js' ,
@@ -70,48 +105,22 @@ export function getWebpackCommonConfig(
70105 } ,
71106 module : {
72107 rules : [
73- {
74- enforce : 'pre' ,
75- test : / \. j s $ / ,
76- loader : 'source-map-loader' ,
77- exclude : [ nodeModules ]
78- } ,
79- // in main, load css as raw text
80- {
81- exclude : styles ,
82- test : / \. c s s $ / ,
83- loaders : [ 'raw-loader' , 'postcss-loader' ]
84- } , {
85- exclude : styles ,
86- test : / \. s t y l $ / ,
87- loaders : [ 'raw-loader' , 'postcss-loader' , 'stylus-loader' ] } ,
88- {
89- exclude : styles ,
90- test : / \. l e s s $ / ,
91- loaders : [ 'raw-loader' , 'postcss-loader' , 'less-loader' ]
92- } , {
93- exclude : styles ,
94- test : / \. s c s s $ | \. s a s s $ / ,
95- loaders : [ 'raw-loader' , 'postcss-loader' , 'sass-loader' ]
96- } ,
97-
98-
99- // load global scripts using script-loader
100- { include : scripts , test : / \. j s $ / , loader : 'script-loader' } ,
108+ { enforce : 'pre' , test : / \. j s $ / , loader : 'source-map-loader' , exclude : [ nodeModules ] } ,
101109
102- { test : / \. j s o n $ / , loader : 'json-loader' } ,
103- { test : / \. ( j p g | p n g | g i f ) $ / , loader : 'url-loader?limit=10000' } ,
104- { test : / \. h t m l $ / , loader : 'raw-loader' } ,
110+ { test : / \. j s o n $ / , loader : 'json-loader' } ,
111+ { test : / \. ( j p g | p n g | g i f ) $ / , loader : 'url-loader?limit=10000' } ,
112+ { test : / \. h t m l $ / , loader : 'raw-loader' } ,
105113
106114 { test : / \. ( o t f | t t f | w o f f | w o f f 2 ) $ / , loader : 'url-loader?limit=10000' } ,
107115 { test : / \. ( e o t | s v g ) $ / , loader : 'file-loader' }
108- ]
116+ ] . concat ( extraRules )
109117 } ,
110118 plugins : [
111119 new HtmlWebpackPlugin ( {
112120 template : path . resolve ( appRoot , appConfig . index ) ,
113121 filename : path . resolve ( appConfig . outDir , appConfig . index ) ,
114- chunksSortMode : packageChunkSort ( [ 'inline' , 'styles' , 'scripts' , 'vendor' , 'main' ] )
122+ chunksSortMode : packageChunkSort ( [ 'inline' , 'styles' , 'scripts' , 'vendor' , 'main' ] ) ,
123+ excludeChunks : lazyChunks
115124 } ) ,
116125 new BaseHrefWebpackPlugin ( {
117126 baseHref : baseHref
@@ -130,12 +139,18 @@ export function getWebpackCommonConfig(
130139 } ) ,
131140 new GlobCopyWebpackPlugin ( {
132141 patterns : appConfig . assets ,
133- globOptions : { cwd : appRoot , dot : true , ignore : '**/.gitkeep' }
142+ globOptions : { cwd : appRoot , dot : true , ignore : '**/.gitkeep' }
134143 } ) ,
135144 new webpack . LoaderOptionsPlugin ( {
136145 test : / \. ( c s s | s c s s | s a s s | l e s s | s t y l ) $ / ,
137146 options : {
138- postcss : [ autoprefixer ( ) ]
147+ postcss : [ autoprefixer ( ) ] ,
148+ cssLoader : { sourceMap : sourcemap } ,
149+ sassLoader : { sourceMap : sourcemap } ,
150+ lessLoader : { sourceMap : sourcemap } ,
151+ stylusLoader : { sourceMap : sourcemap } ,
152+ // context needed as a workaround https://github.com/jtangelder/sass-loader/issues/285
153+ context : path . resolve ( __dirname , './' )
139154 } ,
140155 } )
141156 ] . concat ( extraPlugins ) ,
0 commit comments