Skip to content

Commit 7a7733e

Browse files
committed
feat(build): add --extract-css flag
Having css extraction on all the time makes dev rebuild times very slow for global styles. This flag defaults to false on dev targets and true on prod targets.
1 parent c6d1c99 commit 7a7733e

File tree

11 files changed

+51
-15
lines changed

11 files changed

+51
-15
lines changed

docs/documentation/build.md

+2
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ ng build
3535
`--base-href` (`-bh`) base url for the application being built
3636

3737
`--aot` flag whether to build using Ahead of Time compilation
38+
39+
`--extract-css` extract css from global styles onto css files instead of js ones

docs/documentation/serve.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@
3434

3535
`--aot` flag to turn on Ahead of Time compilation
3636

37-
`--open` (`-o`) opens the app in the default browser
37+
`--open` (`-o`) opens the app in the default browser
38+
39+
`--extract-css` extract css from global styles onto css files instead of js ones

packages/angular-cli/commands/build.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface BuildOptions {
1818
locale?: string;
1919
deployUrl?: string;
2020
outputHashing?: string;
21+
extractCss?: boolean | null;
2122
}
2223

2324
const BuildCommand = Command.extend({
@@ -52,7 +53,8 @@ const BuildCommand = Command.extend({
5253
type: String,
5354
values: ['none', 'all', 'media', 'bundles'],
5455
description: 'define the output filename cache-busting hashing mode'
55-
}
56+
},
57+
{ name: 'extract-css', type: Boolean, default: true }
5658
],
5759

5860
run: function (commandOptions: BuildOptions) {

packages/angular-cli/commands/serve.run.ts

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ export default function serveRun(commandOptions: ServeTaskOptions) {
2020
}
2121
}
2222

23+
// default to extractCss to true on prod target
24+
if (typeof commandOptions.extractCss === 'undefined') {
25+
commandOptions.extractCss = commandOptions.target === 'production';
26+
}
27+
2328
// Check angular version.
2429
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
2530
commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host;

packages/angular-cli/commands/serve.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface ServeTaskOptions {
3030
i18nFile?: string;
3131
i18nFormat?: string;
3232
locale?: string;
33+
extractCss?: boolean | null;
3334
}
3435

3536
const ServeCommand = Command.extend({
@@ -103,7 +104,8 @@ const ServeCommand = Command.extend({
103104
},
104105
{ name: 'i18n-file', type: String, default: null },
105106
{ name: 'i18n-format', type: String, default: null },
106-
{ name: 'locale', type: String, default: null }
107+
{ name: 'locale', type: String, default: null },
108+
{ name: 'extract-css', type: Boolean, default: null }
107109
],
108110

109111
run: function(commandOptions: ServeTaskOptions) {

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function getWebpackCommonConfig(
3434
verbose: boolean,
3535
progress: boolean,
3636
outputHashing: string,
37+
extractCss: boolean,
3738
) {
3839

3940
const appRoot = path.resolve(projectRoot, appConfig.root);
@@ -91,7 +92,7 @@ export function getWebpackCommonConfig(
9192
// create css loaders for component css and for global css
9293
extraRules.push(...makeCssLoaders(globalStyles.map((style) => style.path)));
9394

94-
if (extractedCssEntryPoints.length > 0) {
95+
if (extractCss && extractedCssEntryPoints.length > 0) {
9596
// don't emit the .js entry point for extracted styles
9697
extraPlugins.push(new SuppressEntryChunksWebpackPlugin({ chunks: extractedCssEntryPoints }));
9798
}
@@ -172,7 +173,10 @@ export function getWebpackCommonConfig(
172173
].concat(extraRules)
173174
},
174175
plugins: [
175-
new ExtractTextPlugin(`[name]${hashFormat.extract}.bundle.css`),
176+
new ExtractTextPlugin({
177+
filename: `[name]${hashFormat.extract}.bundle.css`,
178+
disable: !extractCss
179+
}),
176180
new HtmlWebpackPlugin({
177181
template: path.resolve(appRoot, appConfig.index),
178182
filename: path.resolve(appConfig.outDir, appConfig.index),

packages/angular-cli/models/webpack-config.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ export class NgCliWebpackConfig {
3333
verbose = false,
3434
progress = true,
3535
deployUrl?: string,
36-
outputHashing?: string
36+
outputHashing?: string,
37+
extractCss = true,
3738
) {
3839
const config: CliConfig = CliConfig.fromProject();
3940
const appConfig = config.config.apps[0];
@@ -50,7 +51,8 @@ export class NgCliWebpackConfig {
5051
vendorChunk,
5152
verbose,
5253
progress,
53-
outputHashing
54+
outputHashing,
55+
extractCss,
5456
);
5557
let targetConfigPartial = this.getTargetConfig(
5658
this.ngCliProject.root, appConfig, sourcemap, verbose

packages/angular-cli/tasks/build-webpack-watch.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ export default Task.extend({
3434
runTaskOptions.verbose,
3535
runTaskOptions.progress,
3636
deployUrl,
37-
runTaskOptions.outputHashing
37+
runTaskOptions.outputHashing,
38+
runTaskOptions.extractCss,
3839
).config;
3940
const webpackCompiler: any = webpack(config);
4041

packages/angular-cli/tasks/build-webpack.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export default <any>Task.extend({
3535
runTaskOptions.verbose,
3636
runTaskOptions.progress,
3737
deployUrl,
38-
runTaskOptions.outputHashing
38+
runTaskOptions.outputHashing,
39+
runTaskOptions.extractCss,
3940
).config;
4041

4142
const webpackCompiler: any = webpack(config);

packages/angular-cli/tasks/serve-webpack.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ export default Task.extend({
3535
serveTaskOptions.sourcemap,
3636
serveTaskOptions.vendorChunk,
3737
serveTaskOptions.verbose,
38-
serveTaskOptions.progress
38+
serveTaskOptions.progress,
39+
undefined,
40+
undefined,
41+
serveTaskOptions.extractCss
3942
).config;
4043

4144
// This allows for live reload of page when changes are made to repo.
@@ -55,6 +58,12 @@ export default Task.extend({
5558
ui.writeLine(' for information on working with HMR for Webpack.');
5659
entryPoints.push('webpack/hot/dev-server');
5760
config.plugins.push(new webpack.HotModuleReplacementPlugin());
61+
if (serveTaskOptions.extractCss) {
62+
ui.writeLine(oneLine`
63+
${chalk.yellow('NOTICE')} (HMR) does not allow for CSS hot reload when used
64+
together with '--extract-css'.
65+
`);
66+
}
5867
}
5968
config.entry.main.unshift(...entryPoints);
6069
webpackCompiler = webpack(config);

tests/e2e/tests/build/styles/styles-array.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ export default function () {
4040
.then(() => expectFileToMatch('dist/common-entry.bundle.css', '.common-entry-style'))
4141
.then(() => expectFileToMatch('dist/common-entry.bundle.js', 'common-entry-script'))
4242
// there are no js entry points for css only bundles
43-
.then(() => expectToFail(() => expectFileToExist('dist/styles.bundle.js')))
44-
.then(() => expectToFail(() => expectFileToExist('dist/lazy-styles.bundle.js')))
45-
.then(() => expectToFail(() => expectFileToExist('dist/renamed-styles.bundle.js')))
46-
.then(() => expectToFail(() => expectFileToExist('dist/renamed-lazy-styles.bundle.js')))
43+
.then(() => expectToFail(() => expectFileToExist('dist/style.bundle.js')))
44+
.then(() => expectToFail(() => expectFileToExist('dist/lazy-style.bundle.js')))
45+
.then(() => expectToFail(() => expectFileToExist('dist/renamed-style.bundle.js')))
46+
.then(() => expectToFail(() => expectFileToExist('dist/renamed-lazy-style.bundle.js')))
4747
// index.html lists the right bundles
4848
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
4949
<link href="renamed-style.bundle.css" rel="stylesheet"/>
@@ -55,5 +55,11 @@ export default function () {
5555
<script type="text/javascript" src="vendor.bundle.js"></script>
5656
<script type="text/javascript" src="common-entry.bundle.js"></script>
5757
<script type="text/javascript" src="main.bundle.js"></script>
58-
`));
58+
`))
59+
.then(() => ng('build', '--no-extract-css'))
60+
// js files still exist when not extracting css
61+
.then(() => expectFileToExist('dist/styles.bundle.js'))
62+
.then(() => expectFileToExist('dist/lazy-style.bundle.js'))
63+
.then(() => expectFileToExist('dist/renamed-style.bundle.js'))
64+
.then(() => expectFileToExist('dist/renamed-lazy-style.bundle.js'));
5965
}

0 commit comments

Comments
 (0)