Skip to content

Commit 99fdd33

Browse files
jimitndiayeMRHarrison
authored andcommitted
feat(build): use static files for css
Fix angular#2148 Fix angular#2020 Fix angular#2826 Close angular#2646
1 parent e857ca4 commit 99fdd33

File tree

7 files changed

+95
-20
lines changed

7 files changed

+95
-20
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"exit": "^0.1.2",
6969
"exports-loader": "^0.6.3",
7070
"expose-loader": "^0.7.1",
71+
"extract-text-webpack-plugin": "^2.0.0-beta.4",
7172
"file-loader": "^0.8.5",
7273
"fs-extra": "^0.30.0",
7374
"fs.realpath": "^1.0.0",

packages/angular-cli/models/webpack-build-common.ts

-18
Original file line numberDiff line numberDiff line change
@@ -71,24 +71,6 @@ export function getWebpackCommonConfig(
7171
loaders: ['raw-loader', 'postcss-loader', 'sass-loader']
7272
},
7373

74-
// outside of main, load it via style-loader
75-
       {
76-
include: styles,
77-
test: /\.css$/,
78-
loaders: ['style-loader', 'css-loader', 'postcss-loader']
79-
}, {
80-
include: styles,
81-
test: /\.styl$/,
82-
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader']
83-
}, {
84-
include: styles,
85-
test: /\.less$/,
86-
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
87-
}, {
88-
include: styles,
89-
test: /\.scss$|\.sass$/,
90-
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
91-
},
9274

9375
// load global scripts using script-loader
9476
{ include: scripts, test: /\.js$/, loader: 'script-loader' },
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
const path = require('path');
22

33
export const getWebpackDevConfigPartial = function(projectRoot: string, appConfig: any) {
4+
const appRoot = path.resolve(projectRoot, appConfig.root);
5+
const styles = appConfig.styles
6+
? appConfig.styles.map((style: string) => path.resolve(appRoot, style))
7+
: [];
8+
const cssLoaders = ['style-loader', 'css-loader?sourcemap', 'postcss-loader'];
49
return {
510
devtool: 'source-map',
611
output: {
712
path: path.resolve(projectRoot, appConfig.outDir),
813
filename: '[name].bundle.js',
914
sourceMapFilename: '[name].map',
1015
chunkFilename: '[id].chunk.js'
16+
},
17+
module: {
18+
rules: [
19+
// outside of main, load it via style-loader for development builds
20+
       {
21+
include: styles,
22+
test: /\.css$/,
23+
loaders: cssLoaders
24+
}, {
25+
include: styles,
26+
test: /\.styl$/,
27+
loaders: [...cssLoaders, 'stylus-loader?sourcemap']
28+
}, {
29+
include: styles,
30+
test: /\.less$/,
31+
loaders: [...cssLoaders, 'less-loader?sourcemap']
32+
}, {
33+
include: styles,
34+
test: /\.scss$|\.sass$/,
35+
loaders: [...cssLoaders, 'sass-loader?sourcemap']
36+
},
37+
]
1138
}
1239
};
1340
};

packages/angular-cli/models/webpack-build-production.ts

+29
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as path from 'path';
22
const WebpackMd5Hash = require('webpack-md5-hash');
33
const CompressionPlugin = require('compression-webpack-plugin');
44
import * as webpack from 'webpack';
5+
const ExtractTextPlugin = require('extract-text-webpack-plugin');
56

67
declare module 'webpack' {
78
export interface LoaderOptionsPlugin {}
@@ -14,6 +15,11 @@ declare module 'webpack' {
1415
}
1516

1617
export const getWebpackProdConfigPartial = function(projectRoot: string, appConfig: any) {
18+
const appRoot = path.resolve(projectRoot, appConfig.root);
19+
const styles = appConfig.styles
20+
? appConfig.styles.map((style: string) => path.resolve(appRoot, style))
21+
: [];
22+
const cssLoaders = ['css-loader?sourcemap&minimize', 'postcss-loader'];
1723
return {
1824
devtool: 'source-map',
1925
output: {
@@ -23,7 +29,30 @@ export const getWebpackProdConfigPartial = function(projectRoot: string, appConf
2329
sourceMapFilename: '[name].[chunkhash].bundle.map',
2430
chunkFilename: '[id].[chunkhash].chunk.js'
2531
},
32+
module: {
33+
rules: [
34+
// outside of main, load it via extract-text-plugin for production builds
35+
       {
36+
include: styles,
37+
test: /\.css$/,
38+
loaders: ExtractTextPlugin.extract(cssLoaders)
39+
}, {
40+
include: styles,
41+
test: /\.styl$/,
42+
loaders: ExtractTextPlugin.extract([...cssLoaders, 'stylus-loader?sourcemap'])
43+
}, {
44+
include: styles,
45+
test: /\.less$/,
46+
loaders: ExtractTextPlugin.extract([...cssLoaders, 'less-loader?sourcemap'])
47+
}, {
48+
include: styles,
49+
test: /\.scss$|\.sass$/,
50+
loaders: ExtractTextPlugin.extract([...cssLoaders, 'sass-loader?sourcemap'])
51+
},
52+
]
53+
},
2654
plugins: [
55+
new ExtractTextPlugin('[name].[contenthash].bundle.css'),
2756
new WebpackMd5Hash(),
2857
new webpack.DefinePlugin({
2958
'process.env.NODE_ENV': JSON.stringify('production')

packages/angular-cli/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"exit": "^0.1.2",
5050
"exports-loader": "^0.6.3",
5151
"expose-loader": "^0.7.1",
52+
"extract-text-webpack-plugin": "^2.0.0-beta.4",
5253
"file-loader": "^0.8.5",
5354
"fs-extra": "^0.30.0",
5455
"fs.realpath": "^1.0.0",

tests/e2e/tests/build/prod-build.ts

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default function() {
3434
.then(() => expectFileToExist(join(process.cwd(), 'dist')))
3535
// Check for cache busting hash script src
3636
.then(() => expectFileToMatch('dist/index.html', /main\.[0-9a-f]{20}\.bundle\.js/))
37+
.then(() => expectFileToMatch('dist/index.html', /styles\.[0-9a-f]{32}\.bundle\.css/))
3738

3839
// Check that the process didn't change local files.
3940
.then(() => expectGitToBeClean())

tests/e2e/tests/build/styles/css.ts

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,53 @@
1+
import * as glob from 'glob';
2+
13
import {writeMultipleFiles, expectFileToMatch} from '../../../utils/fs';
24
import {ng} from '../../../utils/process';
5+
import {updateJsonFile} from '../../../utils/project';
36

47

58
export default function() {
69
return writeMultipleFiles({
710
'src/styles.css': `
811
@import './imported-styles.css';
9-
12+
1013
body { background-color: blue; }
1114
`,
1215
'src/imported-styles.css': `
1316
p { background-color: red; }
17+
`,
18+
'src/styles.less': `
19+
.outer {
20+
.inner {
21+
background: #fff;
22+
}
23+
}
24+
`,
25+
'src/styles.scss': `
26+
.upper {
27+
.lower {
28+
background: #def;
29+
}
30+
}
1431
`
1532
})
33+
.then(() => updateJsonFile('angular-cli.json', configJson => {
34+
const app = configJson['apps'][0];
35+
app['styles'].push('styles.less');
36+
app['styles'].push('styles.scss');
37+
}))
1638
.then(() => ng('build'))
1739
.then(() => expectFileToMatch('dist/styles.bundle.js', 'body { background-color: blue; }'))
18-
.then(() => expectFileToMatch('dist/styles.bundle.js', 'p { background-color: red; }'));
40+
.then(() => expectFileToMatch('dist/styles.bundle.js', 'p { background-color: red; }'))
41+
.then(() => expectFileToMatch('dist/styles.bundle.js', /.outer.*.inner.*background:\s*#[fF]+/))
42+
.then(() => expectFileToMatch('dist/styles.bundle.js', /.upper.*.lower.*background.*#def/))
43+
44+
.then(() => ng('build', '--prod'))
45+
.then(() => new Promise<string>(() =>
46+
glob.sync('dist/styles.*.bundle.css').find(file => !!file)))
47+
.then((styles) =>
48+
expectFileToMatch(styles, 'body { background-color: blue; }')
49+
.then(() => expectFileToMatch(styles, 'p { background-color: red; }')
50+
.then(() => expectFileToMatch(styles, /.outer.*.inner.*background:\s*#[fF]+/))
51+
.then(() => expectFileToMatch(styles, /.upper.*.lower.*background.*#def/)))
52+
);
1953
}

0 commit comments

Comments
 (0)