Skip to content

feat(@angular/cli): add environment option to global styles & scripts #5778

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

Closed
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/documentation/stories/global-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
],
```
7 changes: 6 additions & 1 deletion docs/documentation/stories/global-styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ These will be loaded exactly as if you had added them in a `<link>` 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": [
"styles.css",
"more-styles.css",
{ "input": "lazy-style.scss", "lazy": true },
{ "input": "pre-rename-style.scss", "output": "renamed-style" },
{ "input": "production-style.scss", "env": "prod" }
],
```

Expand Down
31 changes: 30 additions & 1 deletion packages/@angular/cli/lib/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
}
]
},
Expand Down Expand Up @@ -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"
}
},
Expand Down
6 changes: 3 additions & 3 deletions packages/@angular/cli/models/webpack-configs/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
}),
Expand Down
3 changes: 2 additions & 1 deletion packages/@angular/cli/models/webpack-configs/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
4 changes: 3 additions & 1 deletion packages/@angular/cli/models/webpack-configs/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
7 changes: 5 additions & 2 deletions packages/@angular/cli/models/webpack-configs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface ExtraEntry {
lazy?: boolean;
path?: string;
entry?: string;
env?: string;
}

// Filter extra entries out of a arran of extraEntries
Expand All @@ -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) =>
Expand All @@ -66,7 +68,8 @@ export function extraEntryParser(
extraEntry.entry = defaultEntry;
}
return extraEntry;
});
})
.filter(extraEntry => !extraEntry.env || extraEntry.env === environment);
}

export interface HashFormat {
Expand Down
3 changes: 2 additions & 1 deletion packages/@angular/cli/plugins/karma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) }));
Expand Down
6 changes: 3 additions & 3 deletions packages/@angular/cli/utilities/package-chunk-sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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']);
Expand Down
13 changes: 11 additions & 2 deletions tests/e2e/tests/build/scripts-array.ts
Original file line number Diff line number Diff line change
@@ -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 () {
Expand All @@ -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 => {
Expand All @@ -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' }];
}))
Expand All @@ -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`
<link href="common-entry.bundle.css" rel="stylesheet"/>
Expand All @@ -49,6 +57,7 @@ export default function () {
<script type="text/javascript" src="scripts.bundle.js"></script>
<script type="text/javascript" src="renamed-script.bundle.js"></script>
<script type="text/javascript" src="common-entry.bundle.js"></script>
<script type="text/javascript" src="development-script.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>
`))
Expand Down
14 changes: 11 additions & 3 deletions tests/e2e/tests/build/styles/styles-array.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
writeMultipleFiles,
expectFileToMatch
expectFileToMatch,
expectFileToExist
} from '../../../utils/fs';
import { ng } from '../../../utils/process';
import { updateJsonFile } from '../../../utils/project';
Expand All @@ -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];
Expand All @@ -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' }];
}))
Expand All @@ -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`
<link href="common-entry.bundle.css" rel="stylesheet"/>
<link href="styles.bundle.css" rel="stylesheet"/>
<link href="renamed-style.bundle.css" rel="stylesheet"/>
<link href="development-style.bundle.css" rel="stylesheet"/>
`))
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
<script type="text/javascript" src="inline.bundle.js"></script>
Expand Down