From d50191a5952e4b8080f1a49f7a6a8a10fd2f68f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rokas=20Brazd=C5=BEionis?= Date: Fri, 31 Mar 2017 15:44:54 +0300 Subject: [PATCH] feat(@angular/cli): add environment option to global styles & scripts closes #4288 --- docs/documentation/stories/global-scripts.md | 7 ++++- docs/documentation/stories/global-styles.md | 7 ++++- packages/@angular/cli/lib/config/schema.json | 31 ++++++++++++++++++- .../cli/models/webpack-configs/browser.ts | 6 ++-- .../cli/models/webpack-configs/common.ts | 3 +- .../cli/models/webpack-configs/styles.ts | 4 ++- .../cli/models/webpack-configs/utils.ts | 7 +++-- packages/@angular/cli/plugins/karma.ts | 3 +- .../cli/utilities/package-chunk-sort.ts | 6 ++-- tests/e2e/tests/build/scripts-array.ts | 13 ++++++-- tests/e2e/tests/build/styles/styles-array.ts | 14 +++++++-- 11 files changed, 82 insertions(+), 19 deletions(-) diff --git a/docs/documentation/stories/global-scripts.md b/docs/documentation/stories/global-scripts.md index 45855278027a..d675309f0024 100644 --- a/docs/documentation/stories/global-scripts.md +++ b/docs/documentation/stories/global-scripts.md @@ -12,12 +12,17 @@ This is especially useful for legacy libraries or analytic snippets. ], ``` -You can also rename the output and lazy load it by using the object format: +You can also use object format to do more advanced things: +- `input` (required) - file path +- `lazy` - flag to indicate if to lazy load it +- `output` - the output bundle name +- `env` - the environment to be included in ```json "scripts": [ "global-script.js", { "input": "lazy-script.js", "lazy": true }, { "input": "pre-rename-script.js", "output": "renamed-script" }, + { "input": "production-script.js", "env": "prod" } ], ``` diff --git a/docs/documentation/stories/global-styles.md b/docs/documentation/stories/global-styles.md index b5313fcb82cc..3ae494cb9769 100644 --- a/docs/documentation/stories/global-styles.md +++ b/docs/documentation/stories/global-styles.md @@ -16,7 +16,11 @@ These will be loaded exactly as if you had added them in a `` tag inside ` ], ``` -You can also rename the output and lazy load it by using the object format: +You can also use object format to do more advanced things: +- `input` (required) - file path +- `lazy` - flag to indicate if to lazy load it +- `output` - the output bundle name +- `env` - the environment to be included in ```json "styles": [ @@ -24,6 +28,7 @@ You can also rename the output and lazy load it by using the object format: "more-styles.css", { "input": "lazy-style.scss", "lazy": true }, { "input": "pre-rename-style.scss", "output": "renamed-style" }, + { "input": "production-style.scss", "env": "prod" } ], ``` diff --git a/packages/@angular/cli/lib/config/schema.json b/packages/@angular/cli/lib/config/schema.json index 17854b6719c8..50dd2fbb241a 100644 --- a/packages/@angular/cli/lib/config/schema.json +++ b/packages/@angular/cli/lib/config/schema.json @@ -126,10 +126,26 @@ "type": "object", "properties": { "input": { + "description": "The file path.", + "type": "string" + }, + "lazy": { + "description": "Flag to indicate if it's lazy loaded.", + "type": "boolean" + }, + "output": { + "description": "The output bundle name.", + "type": "string" + }, + "env": { + "description": "The environment to be included in.", "type": "string" } }, - "additionalProperties": true + "additionalProperties": true, + "required": [ + "input" + ] } ] }, @@ -162,6 +178,19 @@ "type": "object", "properties": { "input": { + "description": "The file path.", + "type": "string" + }, + "lazy": { + "description": "Flag to indicate if it's lazy loaded.", + "type": "boolean" + }, + "output": { + "description": "The output bundle name.", + "type": "string" + }, + "env": { + "description": "The environment to be included in.", "type": "string" } }, diff --git a/packages/@angular/cli/models/webpack-configs/browser.ts b/packages/@angular/cli/models/webpack-configs/browser.ts index b85670529389..bf86666a3347 100644 --- a/packages/@angular/cli/models/webpack-configs/browser.ts +++ b/packages/@angular/cli/models/webpack-configs/browser.ts @@ -18,8 +18,8 @@ export function getBrowserConfig(wco: WebpackConfigOptions) { // figure out which are the lazy loaded entry points const lazyChunks = lazyChunksFilter([ - ...extraEntryParser(appConfig.scripts, appRoot, 'scripts'), - ...extraEntryParser(appConfig.styles, appRoot, 'styles') + ...extraEntryParser(appConfig.scripts, appRoot, 'scripts', buildOptions.environment), + ...extraEntryParser(appConfig.styles, appRoot, 'styles', buildOptions.environment) ]); if (buildOptions.vendorChunk) { @@ -35,7 +35,7 @@ export function getBrowserConfig(wco: WebpackConfigOptions) { new HtmlWebpackPlugin({ template: path.resolve(appRoot, appConfig.index), filename: path.resolve(buildOptions.outputPath, appConfig.index), - chunksSortMode: packageChunkSort(appConfig), + chunksSortMode: packageChunkSort(appConfig, buildOptions.environment), excludeChunks: lazyChunks, xhtml: true }), diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index bec60dda00a3..98b47ce5574d 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -42,7 +42,8 @@ export function getCommonConfig(wco: WebpackConfigOptions) { // process global scripts if (appConfig.scripts.length > 0) { - const globalScripts = extraEntryParser(appConfig.scripts, appRoot, 'scripts'); + const globalScripts = extraEntryParser(appConfig.scripts, appRoot, 'scripts', + buildOptions.environment); // add entry points and lazy chunks globalScripts.forEach(script => { diff --git a/packages/@angular/cli/models/webpack-configs/styles.ts b/packages/@angular/cli/models/webpack-configs/styles.ts index 2324dba536f8..e0e9af653044 100644 --- a/packages/@angular/cli/models/webpack-configs/styles.ts +++ b/packages/@angular/cli/models/webpack-configs/styles.ts @@ -99,7 +99,9 @@ export function getStylesConfig(wco: WebpackConfigOptions) { // process global styles if (appConfig.styles.length > 0) { - const globalStyles = extraEntryParser(appConfig.styles, appRoot, 'styles'); + const globalStyles = extraEntryParser(appConfig.styles, appRoot, 'styles', + buildOptions.environment); + // add style entry points globalStyles.forEach(style => entryPoints[style.entry] diff --git a/packages/@angular/cli/models/webpack-configs/utils.ts b/packages/@angular/cli/models/webpack-configs/utils.ts index e44e4d34b00b..08e912a7320f 100644 --- a/packages/@angular/cli/models/webpack-configs/utils.ts +++ b/packages/@angular/cli/models/webpack-configs/utils.ts @@ -38,6 +38,7 @@ export interface ExtraEntry { lazy?: boolean; path?: string; entry?: string; + env?: string; } // Filter extra entries out of a arran of extraEntries @@ -51,7 +52,8 @@ export function lazyChunksFilter(extraEntries: ExtraEntry[]) { export function extraEntryParser( extraEntries: (string | ExtraEntry)[], appRoot: string, - defaultEntry: string + defaultEntry: string, + environment: string ): ExtraEntry[] { return extraEntries .map((extraEntry: string | ExtraEntry) => @@ -66,7 +68,8 @@ export function extraEntryParser( extraEntry.entry = defaultEntry; } return extraEntry; - }); + }) + .filter(extraEntry => !extraEntry.env || extraEntry.env === environment); } export interface HashFormat { diff --git a/packages/@angular/cli/plugins/karma.ts b/packages/@angular/cli/plugins/karma.ts index 42303db5a9d8..f639aaaf4e86 100644 --- a/packages/@angular/cli/plugins/karma.ts +++ b/packages/@angular/cli/plugins/karma.ts @@ -119,7 +119,8 @@ const init: any = (config: any) => { // Add global scripts. This logic mimics the one in webpack-configs/common. if (appConfig.scripts && appConfig.scripts.length > 0) { - const globalScriptPatterns = extraEntryParser(appConfig.scripts, appRoot, 'scripts') + const globalScriptPatterns = extraEntryParser(appConfig.scripts, appRoot, 'scripts', + testConfig.environment) // Neither renamed nor lazy scripts are currently supported .filter(script => !(script.output || script.lazy)) .map(script => ({ pattern: path.resolve(appRoot, script.input) })); diff --git a/packages/@angular/cli/utilities/package-chunk-sort.ts b/packages/@angular/cli/utilities/package-chunk-sort.ts index 2d64707c28bf..4b60bf5a38f9 100644 --- a/packages/@angular/cli/utilities/package-chunk-sort.ts +++ b/packages/@angular/cli/utilities/package-chunk-sort.ts @@ -2,7 +2,7 @@ import { ExtraEntry, extraEntryParser } from '../models/webpack-configs/utils'; // Sort chunks according to a predefined order: // inline, polyfills, all scripts, all styles, vendor, main -export function packageChunkSort(appConfig: any) { +export function packageChunkSort(appConfig: any, environment: string) { let entryPoints = ['inline', 'polyfills', 'sw-register']; const pushExtraEntries = (extraEntry: ExtraEntry) => { @@ -12,11 +12,11 @@ export function packageChunkSort(appConfig: any) { }; if (appConfig.scripts) { - extraEntryParser(appConfig.scripts, './', 'scripts').forEach(pushExtraEntries); + extraEntryParser(appConfig.scripts, './', 'scripts', environment).forEach(pushExtraEntries); } if (appConfig.styles) { - extraEntryParser(appConfig.styles, './', 'styles').forEach(pushExtraEntries); + extraEntryParser(appConfig.styles, './', 'styles', environment).forEach(pushExtraEntries); } entryPoints.push(...['vendor', 'main']); diff --git a/tests/e2e/tests/build/scripts-array.ts b/tests/e2e/tests/build/scripts-array.ts index be81248ec3f1..0438283f7a01 100644 --- a/tests/e2e/tests/build/scripts-array.ts +++ b/tests/e2e/tests/build/scripts-array.ts @@ -1,10 +1,12 @@ import { writeMultipleFiles, expectFileToMatch, - appendToFile + appendToFile, + expectFileToExist } from '../../utils/fs'; import { ng } from '../../utils/process'; import { updateJsonFile } from '../../utils/project'; +import { expectToFail } from '../../utils/utils'; import { oneLineTrim } from 'common-tags'; export default function () { @@ -16,6 +18,8 @@ export default function () { 'src/pre-rename-lazy-script.js': 'console.log(\'pre-rename-lazy-script\');', 'src/common-entry-script.js': 'console.log(\'common-entry-script\');', 'src/common-entry-style.css': '.common-entry-style { color: red }', + 'src/development-script.js': 'console.log(\'development-script\');', + 'src/production-script.js': 'console.log(\'production-script\');', }) .then(() => appendToFile('src/main.ts', 'import \'./string-script.js\';')) .then(() => updateJsonFile('.angular-cli.json', configJson => { @@ -26,7 +30,9 @@ export default function () { { input: 'lazy-script.js', lazy: true }, { input: 'pre-rename-script.js', output: 'renamed-script' }, { input: 'pre-rename-lazy-script.js', output: 'renamed-lazy-script', lazy: true }, - { input: 'common-entry-script.js', output: 'common-entry' } + { input: 'common-entry-script.js', output: 'common-entry' }, + { input: 'development-script.js', output: 'development-script', env: 'dev' }, + { input: 'production-script.js', output: 'production-script', env: 'prod' }, ]; app['styles'] = [{ input: 'common-entry-style.css', output: 'common-entry' }]; })) @@ -39,6 +45,8 @@ export default function () { .then(() => expectFileToMatch('dist/renamed-lazy-script.bundle.js', 'pre-rename-lazy-script')) .then(() => expectFileToMatch('dist/common-entry.bundle.js', 'common-entry-script')) .then(() => expectFileToMatch('dist/common-entry.bundle.css', '.common-entry-style')) + .then(() => expectFileToMatch('dist/development-script.bundle.js', 'development-script')) + .then(() => expectToFail(() => expectFileToExist('dist/production-script.bundle.js'))) // index.html lists the right bundles .then(() => expectFileToMatch('dist/index.html', oneLineTrim` @@ -49,6 +57,7 @@ export default function () { + `)) diff --git a/tests/e2e/tests/build/styles/styles-array.ts b/tests/e2e/tests/build/styles/styles-array.ts index 5cbb608070a7..b9af67119684 100644 --- a/tests/e2e/tests/build/styles/styles-array.ts +++ b/tests/e2e/tests/build/styles/styles-array.ts @@ -1,6 +1,7 @@ import { writeMultipleFiles, - expectFileToMatch + expectFileToMatch, + expectFileToExist } from '../../../utils/fs'; import { ng } from '../../../utils/process'; import { updateJsonFile } from '../../../utils/project'; @@ -15,7 +16,9 @@ export default function () { 'src/pre-rename-style.css': '.pre-rename-style { color: red }', 'src/pre-rename-lazy-style.css': '.pre-rename-lazy-style { color: red }', 'src/common-entry-style.css': '.common-entry-style { color: red }', - 'src/common-entry-script.js': 'console.log(\'common-entry-script\');' + 'src/common-entry-script.js': 'console.log(\'common-entry-script\');', + 'src/development-style.css': '.environment-style { color: blue }', + 'src/production-style.css': '.environment-style { color: green }', }) .then(() => updateJsonFile('.angular-cli.json', configJson => { const app = configJson['apps'][0]; @@ -25,7 +28,9 @@ export default function () { { input: 'lazy-style.css', lazy: true }, { input: 'pre-rename-style.css', output: 'renamed-style' }, { input: 'pre-rename-lazy-style.css', output: 'renamed-lazy-style', lazy: true }, - { input: 'common-entry-style.css', output: 'common-entry' } + { input: 'common-entry-style.css', output: 'common-entry' }, + { input: 'development-style.css', output: 'development-style', env: 'dev' }, + { input: 'production-style.css', output: 'production-style', env: 'prod' }, ]; app['scripts'] = [{ input: 'common-entry-script.js', output: 'common-entry' }]; })) @@ -38,11 +43,14 @@ export default function () { .then(() => expectFileToMatch('dist/renamed-lazy-style.bundle.css', '.pre-rename-lazy-style')) .then(() => expectFileToMatch('dist/common-entry.bundle.css', '.common-entry-style')) .then(() => expectFileToMatch('dist/common-entry.bundle.js', 'common-entry-script')) + .then(() => expectFileToMatch('dist/development-style.bundle.css', '.environment-style')) + .then(() => expectToFail(() => expectFileToExist('dist/production-style.bundle.css'))) // index.html lists the right bundles .then(() => expectFileToMatch('dist/index.html', oneLineTrim` + `)) .then(() => expectFileToMatch('dist/index.html', oneLineTrim`