Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(@angular/cli): modernize webpack style config #5672

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"autoprefixer": "^6.5.3",
"chalk": "^1.1.3",
"common-tags": "^1.3.1",
"css-loader": "^0.26.1",
"css-loader": "^0.27.3",
"cssnano": "^3.10.0",
"debug": "^2.1.3",
"denodeify": "^1.2.1",
Expand All @@ -53,7 +53,7 @@
"ember-cli-string-utils": "^1.0.0",
"enhanced-resolve": "^3.1.0",
"exports-loader": "^0.6.3",
"extract-text-webpack-plugin": "~2.0.0",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.0",
"fs-extra": "~2.0.0",
"get-caller-file": "^1.0.0",
Expand All @@ -67,7 +67,7 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.0",
"less": "^2.7.2",
"less-loader": "^2.2.3",
"less-loader": "^4.0.2",
"loader-utils": "^1.0.2",
"lodash": "^4.11.1",
"magic-string": "^0.19.0",
Expand All @@ -76,22 +76,22 @@
"nopt": "^4.0.1",
"opn": "4.0.2",
"portfinder": "~1.0.12",
"postcss-loader": "^0.13.0",
"postcss-loader": "^1.3.3",
"postcss-url": "^5.1.2",
"raw-loader": "^0.5.1",
"resolve": "^1.1.7",
"rimraf": "^2.5.3",
"rsvp": "^3.0.17",
"rxjs": "^5.0.1",
"sass-loader": "^4.1.1",
"sass-loader": "^6.0.3",
"script-loader": "^0.7.0",
"semver": "^5.3.0",
"silent-error": "^1.0.0",
"source-map": "^0.5.6",
"source-map-loader": "^0.1.5",
"style-loader": "^0.13.1",
"stylus": "^0.54.5",
"stylus-loader": "^2.4.0",
"stylus-loader": "^3.0.1",
"temp": "0.8.3",
"typescript": "~2.2.0",
"url-loader": "^0.5.7",
Expand Down
153 changes: 85 additions & 68 deletions packages/@angular/cli/models/webpack-configs/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,44 +41,47 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
const cssSourceMap = buildOptions.extractCss && buildOptions.sourcemaps;

// Minify/optimize css in production.
const cssnanoPlugin = cssnano({ safe: true, autoprefixer: false });

const minimizeCss = buildOptions.target === 'production';
// Convert absolute resource URLs to account for base-href and deploy-url.
const baseHref = wco.buildOptions.baseHref || '';
const deployUrl = wco.buildOptions.deployUrl || '';
const postcssUrlOptions = {
url: (URL: string) => {
// Only convert root relative URLs, which CSS-Loader won't process into require().
if (!URL.startsWith('/') || URL.startsWith('//')) {
return URL;
}

if (deployUrl.match(/:\/\//)) {
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
return `${deployUrl.replace(/\/$/, '')}${URL}`;
} else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, '') +
`/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
} else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
}
}
const postcssPluginCreator = function() {
return [
autoprefixer(),
postcssUrl({
url: (URL: string) => {
// Only convert root relative URLs, which CSS-Loader won't process into require().
if (!URL.startsWith('/') || URL.startsWith('//')) {
return URL;
}

if (deployUrl.match(/:\/\//)) {
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
return `${deployUrl.replace(/\/$/, '')}${URL}`;
} else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, '') +
`/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
} else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
}
}
})
].concat(
minimizeCss ? [cssnano({ safe: true, autoprefixer: false })] : []
);
};
(postcssPluginCreator as any)[postcssArgs] = {
variableImports: {
'autoprefixer': 'autoprefixer',
'postcss-url': 'postcssUrl',
'cssnano': 'cssnano'
},
variables: { minimizeCss, baseHref, deployUrl }
};
const urlPlugin = postcssUrl(postcssUrlOptions);
// We need to save baseHref and deployUrl for the Ejected webpack config to work (we reuse
// the function defined above).
(postcssUrlOptions as any).baseHref = baseHref;
(postcssUrlOptions as any).deployUrl = deployUrl;
// Save the original options as arguments for eject.
urlPlugin[postcssArgs] = postcssUrlOptions;

// PostCSS plugins.
const postCssPlugins = [autoprefixer(), urlPlugin].concat(
buildOptions.target === 'production' ? [cssnanoPlugin] : []
);

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

// set base rules to derive final rules from
const baseRules = [
{ test: /\.css$/, loaders: [] },
{ test: /\.scss$|\.sass$/, loaders: ['sass-loader'] },
{ test: /\.less$/, loaders: ['less-loader'] },
// stylus-loader doesn't support webpack.LoaderOptionsPlugin properly,
// so we need to add options in its query
const baseRules: webpack.NewUseRule[] = [
{ test: /\.css$/, use: [] },
{ test: /\.scss$|\.sass$/, use: [{
loader: 'sass-loader',
options: {
sourceMap: cssSourceMap,
includePaths
}
}]
},
{ test: /\.less$/, use: [{
loader: 'less-loader',
options: {
sourceMap: cssSourceMap
}
}]
},
{
test: /\.styl$/, loaders: [`stylus-loader?${JSON.stringify({
sourceMap: cssSourceMap,
paths: includePaths
})}`]
test: /\.styl$/, use: [{
loader: 'stylus-loader',
options: {
sourceMap: cssSourceMap,
paths: includePaths
}
}]
}
];

const commonLoaders = [
// css-loader doesn't support webpack.LoaderOptionsPlugin properly,
// so we need to add options in its query
`css-loader?${JSON.stringify({ sourceMap: cssSourceMap, importLoaders: 1 })}`,
'postcss-loader'
const commonLoaders: webpack.Loader[] = [
{
loader: 'css-loader',
options: {
sourceMap: cssSourceMap,
importLoaders: 1
}
},
{
loader: 'postcss-loader',
options: {
// A non-function property is required to workaround a webpack option handling bug
ident: 'postcss',
plugins: postcssPluginCreator
}
}
];

// load component css as raw strings
let rules: any = baseRules.map(({test, loaders}) => ({
exclude: globalStylePaths, test, loaders: [
const rules: webpack.Rule[] = baseRules.map(({test, use}) => ({
exclude: globalStylePaths, test, use: [
'exports-loader?module.exports.toString()',
...commonLoaders,
...loaders
...(use as webpack.Loader[])
]
}));

// load global css as css files
if (globalStylePaths.length > 0) {
rules.push(...baseRules.map(({test, loaders}) => {
rules.push(...baseRules.map(({test, use}) => {
const extractTextPlugin = {
use: [
...commonLoaders,
...loaders
...(use as webpack.Loader[])
],
fallback: 'style-loader',
// publicPath needed as a workaround https://github.com/angular/angular-cli/issues/4035
publicPath: ''
};
const ret: any = {
include: globalStylePaths, test, loaders: ExtractTextPlugin.extract(extractTextPlugin)
include: globalStylePaths,
test,
use: ExtractTextPlugin.extract(extractTextPlugin)
};
// Save the original options as arguments for eject.
ret[pluginArgs] = extractTextPlugin;
return ret;
}));
}

// supress empty .js files in css only entry points
if (buildOptions.extractCss) {
// suppress empty .js files in css only entry points
extraPlugins.push(new SuppressExtractedTextChunksWebpackPlugin());
}

Expand All @@ -172,19 +202,6 @@ export function getStylesConfig(wco: WebpackConfigOptions) {
new ExtractTextPlugin({
filename: `[name]${hashFormat.extract}.bundle.css`,
disable: !buildOptions.extractCss
}),
new webpack.LoaderOptionsPlugin({
sourceMap: cssSourceMap,
options: {
postcss: postCssPlugins,
// css-loader, stylus-loader don't support LoaderOptionsPlugin properly
// options are in query instead
sassLoader: { sourceMap: cssSourceMap, includePaths },
// less-loader doesn't support paths
lessLoader: { sourceMap: cssSourceMap },
// context needed as a workaround https://github.com/jtangelder/sass-loader/issues/285
context: projectRoot,
},
})
].concat(extraPlugins)
};
Expand Down
12 changes: 6 additions & 6 deletions packages/@angular/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@
"autoprefixer": "^6.5.3",
"chalk": "^1.1.3",
"common-tags": "^1.3.1",
"css-loader": "^0.26.1",
"css-loader": "^0.27.3",
"cssnano": "^3.10.0",
"debug": "^2.1.3",
"denodeify": "^1.2.1",
"diff": "^3.1.0",
"ember-cli-normalize-entity-name": "^1.0.0",
"ember-cli-string-utils": "^1.0.0",
"exports-loader": "^0.6.3",
"extract-text-webpack-plugin": "~2.0.0",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.0",
"fs-extra": "^2.0.0",
"get-caller-file": "^1.0.0",
Expand All @@ -53,29 +53,29 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.0",
"less": "^2.7.2",
"less-loader": "^2.2.3",
"less-loader": "^4.0.2",
"lodash": "^4.11.1",
"minimatch": "^3.0.3",
"node-modules-path": "^1.0.0",
"nopt": "^4.0.1",
"opn": "4.0.2",
"portfinder": "~1.0.12",
"postcss-loader": "^0.13.0",
"postcss-loader": "^1.3.3",
"postcss-url": "^5.1.2",
"raw-loader": "^0.5.1",
"resolve": "^1.1.7",
"rimraf": "^2.5.3",
"rsvp": "^3.0.17",
"rxjs": "^5.0.1",
"sass-loader": "^4.1.1",
"sass-loader": "^6.0.3",
"script-loader": "^0.7.0",
"semver": "^5.1.0",
"silent-error": "^1.0.0",
"source-map-loader": "^0.1.5",
"istanbul-instrumenter-loader": "^2.0.0",
"style-loader": "^0.13.1",
"stylus": "^0.54.5",
"stylus-loader": "^2.4.0",
"stylus-loader": "^3.0.1",
"temp": "0.8.3",
"typescript": ">=2.0.0 <2.3.0",
"url-loader": "^0.5.7",
Expand Down