Skip to content

Commit 4563ec5

Browse files
Charles Lydingfilipesilva
authored andcommitted
refactor(@angular/cli): modernize webpack style config
Close angular#5672
1 parent 16171b9 commit 4563ec5

4 files changed

Lines changed: 118 additions & 122 deletions

File tree

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"autoprefixer": "^6.5.3",
4444
"chalk": "^1.1.3",
4545
"common-tags": "^1.3.1",
46-
"css-loader": "^0.26.1",
46+
"css-loader": "^0.27.3",
4747
"cssnano": "^3.10.0",
4848
"debug": "^2.1.3",
4949
"denodeify": "^1.2.1",
@@ -52,7 +52,7 @@
5252
"ember-cli-string-utils": "^1.0.0",
5353
"enhanced-resolve": "^3.1.0",
5454
"exports-loader": "^0.6.3",
55-
"extract-text-webpack-plugin": "~2.0.0",
55+
"extract-text-webpack-plugin": "^2.1.0",
5656
"file-loader": "^0.10.0",
5757
"fs-extra": "~2.0.0",
5858
"get-caller-file": "^1.0.0",
@@ -66,7 +66,7 @@
6666
"karma-sourcemap-loader": "^0.3.7",
6767
"karma-webpack": "^2.0.0",
6868
"less": "^2.7.2",
69-
"less-loader": "^2.2.3",
69+
"less-loader": "^4.0.2",
7070
"loader-utils": "^1.0.2",
7171
"lodash": "^4.11.1",
7272
"magic-string": "^0.19.0",
@@ -75,22 +75,22 @@
7575
"nopt": "^4.0.1",
7676
"opn": "4.0.2",
7777
"portfinder": "~1.0.12",
78-
"postcss-loader": "^0.13.0",
78+
"postcss-loader": "^1.3.3",
7979
"postcss-url": "^5.1.2",
8080
"raw-loader": "^0.5.1",
8181
"resolve": "^1.1.7",
8282
"rimraf": "^2.5.3",
8383
"rsvp": "^3.0.17",
8484
"rxjs": "^5.0.1",
85-
"sass-loader": "^4.1.1",
85+
"sass-loader": "^6.0.3",
8686
"script-loader": "^0.7.0",
8787
"semver": "^5.3.0",
8888
"silent-error": "^1.0.0",
8989
"source-map": "^0.5.6",
9090
"source-map-loader": "^0.1.5",
9191
"style-loader": "^0.13.1",
9292
"stylus": "^0.54.5",
93-
"stylus-loader": "^2.4.0",
93+
"stylus-loader": "^3.0.1",
9494
"temp": "0.8.3",
9595
"typescript": "~2.2.0",
9696
"url-loader": "^0.5.7",

packages/@angular/cli/models/webpack-configs/styles.ts

Lines changed: 85 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -41,44 +41,47 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
4141
const cssSourceMap = buildOptions.extractCss && buildOptions.sourcemaps;
4242

4343
// Minify/optimize css in production.
44-
const cssnanoPlugin = cssnano({ safe: true, autoprefixer: false });
45-
44+
const minimizeCss = buildOptions.target === 'production';
4645
// Convert absolute resource URLs to account for base-href and deploy-url.
4746
const baseHref = wco.buildOptions.baseHref || '';
4847
const deployUrl = wco.buildOptions.deployUrl || '';
49-
const postcssUrlOptions = {
50-
url: (URL: string) => {
51-
// Only convert root relative URLs, which CSS-Loader won't process into require().
52-
if (!URL.startsWith('/') || URL.startsWith('//')) {
53-
return URL;
54-
}
5548

56-
if (deployUrl.match(/:\/\//)) {
57-
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
58-
return `${deployUrl.replace(/\/$/, '')}${URL}`;
59-
} else if (baseHref.match(/:\/\//)) {
60-
// If baseHref contains a scheme, include it as is.
61-
return baseHref.replace(/\/$/, '') +
62-
`/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
63-
} else {
64-
// Join together base-href, deploy-url and the original URL.
65-
// Also dedupe multiple slashes into single ones.
66-
return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
67-
}
68-
}
49+
const postcssPluginCreator = function() {
50+
return [
51+
autoprefixer(),
52+
postcssUrl({
53+
url: (URL: string) => {
54+
// Only convert root relative URLs, which CSS-Loader won't process into require().
55+
if (!URL.startsWith('/') || URL.startsWith('//')) {
56+
return URL;
57+
}
58+
59+
if (deployUrl.match(/:\/\//)) {
60+
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
61+
return `${deployUrl.replace(/\/$/, '')}${URL}`;
62+
} else if (baseHref.match(/:\/\//)) {
63+
// If baseHref contains a scheme, include it as is.
64+
return baseHref.replace(/\/$/, '') +
65+
`/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
66+
} else {
67+
// Join together base-href, deploy-url and the original URL.
68+
// Also dedupe multiple slashes into single ones.
69+
return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
70+
}
71+
}
72+
})
73+
].concat(
74+
minimizeCss ? [cssnano({ safe: true, autoprefixer: false })] : []
75+
);
76+
};
77+
(postcssPluginCreator as any)[postcssArgs] = {
78+
variableImports: {
79+
'autoprefixer': 'autoprefixer',
80+
'postcss-url': 'postcssUrl',
81+
'cssnano': 'cssnano'
82+
},
83+
variables: { minimizeCss, baseHref, deployUrl }
6984
};
70-
const urlPlugin = postcssUrl(postcssUrlOptions);
71-
// We need to save baseHref and deployUrl for the Ejected webpack config to work (we reuse
72-
// the function defined above).
73-
(postcssUrlOptions as any).baseHref = baseHref;
74-
(postcssUrlOptions as any).deployUrl = deployUrl;
75-
// Save the original options as arguments for eject.
76-
urlPlugin[postcssArgs] = postcssUrlOptions;
77-
78-
// PostCSS plugins.
79-
const postCssPlugins = [autoprefixer(), urlPlugin].concat(
80-
buildOptions.target === 'production' ? [cssnanoPlugin] : []
81-
);
8285

8386
// determine hashing format
8487
const hashFormat = getOutputHashFormat(buildOptions.outputHashing);
@@ -108,59 +111,86 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
108111
}
109112

110113
// set base rules to derive final rules from
111-
const baseRules = [
112-
{ test: /\.css$/, loaders: [] },
113-
{ test: /\.scss$|\.sass$/, loaders: ['sass-loader'] },
114-
{ test: /\.less$/, loaders: ['less-loader'] },
115-
// stylus-loader doesn't support webpack.LoaderOptionsPlugin properly,
116-
// so we need to add options in its query
114+
const baseRules: webpack.NewUseRule[] = [
115+
{ test: /\.css$/, use: [] },
116+
{ test: /\.scss$|\.sass$/, use: [{
117+
loader: 'sass-loader',
118+
options: {
119+
sourceMap: cssSourceMap,
120+
includePaths
121+
}
122+
}]
123+
},
124+
{ test: /\.less$/, use: [{
125+
loader: 'less-loader',
126+
options: {
127+
sourceMap: cssSourceMap
128+
}
129+
}]
130+
},
117131
{
118-
test: /\.styl$/, loaders: [`stylus-loader?${JSON.stringify({
119-
sourceMap: cssSourceMap,
120-
paths: includePaths
121-
})}`]
132+
test: /\.styl$/, use: [{
133+
loader: 'stylus-loader',
134+
options: {
135+
sourceMap: cssSourceMap,
136+
paths: includePaths
137+
}
138+
}]
122139
}
123140
];
124141

125-
const commonLoaders = [
126-
// css-loader doesn't support webpack.LoaderOptionsPlugin properly,
127-
// so we need to add options in its query
128-
`css-loader?${JSON.stringify({ sourceMap: cssSourceMap, importLoaders: 1 })}`,
129-
'postcss-loader'
142+
const commonLoaders: webpack.Loader[] = [
143+
{
144+
loader: 'css-loader',
145+
options: {
146+
sourceMap: cssSourceMap,
147+
importLoaders: 1
148+
}
149+
},
150+
{
151+
loader: 'postcss-loader',
152+
options: {
153+
// A non-function property is required to workaround a webpack option handling bug
154+
ident: 'postcss',
155+
plugins: postcssPluginCreator
156+
}
157+
}
130158
];
131159

132160
// load component css as raw strings
133-
let rules: any = baseRules.map(({test, loaders}) => ({
134-
exclude: globalStylePaths, test, loaders: [
161+
const rules: webpack.Rule[] = baseRules.map(({test, use}) => ({
162+
exclude: globalStylePaths, test, use: [
135163
'exports-loader?module.exports.toString()',
136164
...commonLoaders,
137-
...loaders
165+
...(use as webpack.Loader[])
138166
]
139167
}));
140168

141169
// load global css as css files
142170
if (globalStylePaths.length > 0) {
143-
rules.push(...baseRules.map(({test, loaders}) => {
171+
rules.push(...baseRules.map(({test, use}) => {
144172
const extractTextPlugin = {
145173
use: [
146174
...commonLoaders,
147-
...loaders
175+
...(use as webpack.Loader[])
148176
],
149177
fallback: 'style-loader',
150178
// publicPath needed as a workaround https://github.com/angular/angular-cli/issues/4035
151179
publicPath: ''
152180
};
153181
const ret: any = {
154-
include: globalStylePaths, test, loaders: ExtractTextPlugin.extract(extractTextPlugin)
182+
include: globalStylePaths,
183+
test,
184+
use: ExtractTextPlugin.extract(extractTextPlugin)
155185
};
156186
// Save the original options as arguments for eject.
157187
ret[pluginArgs] = extractTextPlugin;
158188
return ret;
159189
}));
160190
}
161191

162-
// supress empty .js files in css only entry points
163192
if (buildOptions.extractCss) {
193+
// suppress empty .js files in css only entry points
164194
extraPlugins.push(new SuppressExtractedTextChunksWebpackPlugin());
165195
}
166196

@@ -172,19 +202,6 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
172202
new ExtractTextPlugin({
173203
filename: `[name]${hashFormat.extract}.bundle.css`,
174204
disable: !buildOptions.extractCss
175-
}),
176-
new webpack.LoaderOptionsPlugin({
177-
sourceMap: cssSourceMap,
178-
options: {
179-
postcss: postCssPlugins,
180-
// css-loader, stylus-loader don't support LoaderOptionsPlugin properly
181-
// options are in query instead
182-
sassLoader: { sourceMap: cssSourceMap, includePaths },
183-
// less-loader doesn't support paths
184-
lessLoader: { sourceMap: cssSourceMap },
185-
// context needed as a workaround https://github.com/jtangelder/sass-loader/issues/285
186-
context: projectRoot,
187-
},
188205
})
189206
].concat(extraPlugins)
190207
};

packages/@angular/cli/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@
3232
"autoprefixer": "^6.5.3",
3333
"chalk": "^1.1.3",
3434
"common-tags": "^1.3.1",
35-
"css-loader": "^0.26.1",
35+
"css-loader": "^0.27.3",
3636
"cssnano": "^3.10.0",
3737
"debug": "^2.1.3",
3838
"denodeify": "^1.2.1",
3939
"diff": "^3.1.0",
4040
"ember-cli-normalize-entity-name": "^1.0.0",
4141
"ember-cli-string-utils": "^1.0.0",
4242
"exports-loader": "^0.6.3",
43-
"extract-text-webpack-plugin": "~2.0.0",
43+
"extract-text-webpack-plugin": "^2.1.0",
4444
"file-loader": "^0.10.0",
4545
"fs-extra": "^2.0.0",
4646
"get-caller-file": "^1.0.0",
@@ -53,29 +53,29 @@
5353
"karma-sourcemap-loader": "^0.3.7",
5454
"karma-webpack": "^2.0.0",
5555
"less": "^2.7.2",
56-
"less-loader": "^2.2.3",
56+
"less-loader": "^4.0.2",
5757
"lodash": "^4.11.1",
5858
"minimatch": "^3.0.3",
5959
"node-modules-path": "^1.0.0",
6060
"nopt": "^4.0.1",
6161
"opn": "4.0.2",
6262
"portfinder": "~1.0.12",
63-
"postcss-loader": "^0.13.0",
63+
"postcss-loader": "^1.3.3",
6464
"postcss-url": "^5.1.2",
6565
"raw-loader": "^0.5.1",
6666
"resolve": "^1.1.7",
6767
"rimraf": "^2.5.3",
6868
"rsvp": "^3.0.17",
6969
"rxjs": "^5.0.1",
70-
"sass-loader": "^4.1.1",
70+
"sass-loader": "^6.0.3",
7171
"script-loader": "^0.7.0",
7272
"semver": "^5.1.0",
7373
"silent-error": "^1.0.0",
7474
"source-map-loader": "^0.1.5",
7575
"istanbul-instrumenter-loader": "^2.0.0",
7676
"style-loader": "^0.13.1",
7777
"stylus": "^0.54.5",
78-
"stylus-loader": "^2.4.0",
78+
"stylus-loader": "^3.0.1",
7979
"temp": "0.8.3",
8080
"typescript": ">=2.0.0 <2.3.0",
8181
"url-loader": "^0.5.7",

0 commit comments

Comments
 (0)