Skip to content

Commit 87536c8

Browse files
filipesilvahansl
authored andcommitted
feat(build): add --extract-css flag (angular#3943)
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 4c2f06a commit 87536c8

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);
@@ -92,7 +93,7 @@ export function getWebpackCommonConfig(
9293
// create css loaders for component css and for global css
9394
extraRules.push(...makeCssLoaders(globalStyles.map((style) => style.path)));
9495

95-
if (extractedCssEntryPoints.length > 0) {
96+
if (extractCss && extractedCssEntryPoints.length > 0) {
9697
// don't emit the .js entry point for extracted styles
9798
extraPlugins.push(new SuppressEntryChunksWebpackPlugin({ chunks: extractedCssEntryPoints }));
9899
}
@@ -173,7 +174,10 @@ export function getWebpackCommonConfig(
173174
].concat(extraRules)
174175
},
175176
plugins: [
176-
new ExtractTextPlugin(`[name]${hashFormat.extract}.bundle.css`),
177+
new ExtractTextPlugin({
178+
filename: `[name]${hashFormat.extract}.bundle.css`,
179+
disable: !extractCss
180+
}),
177181
new HtmlWebpackPlugin({
178182
template: path.resolve(appRoot, appConfig.index),
179183
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 appConfig = CliConfig.fromProject().config.apps[0];
3940
const projectRoot = this.ngCliProject.root;
@@ -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(projectRoot, appConfig, sourcemap, verbose);
5658

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
if (!config.entry.main) { config.entry.main = []; }
6069
config.entry.main.unshift(...entryPoints);

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)