Skip to content

Commit cd44902

Browse files
petebacondarwinmatsko
authored andcommitted
feat(ivy): ngcc - compile only specified package.json format properties (angular#29092)
You can now specify a list of properties in the package.json that should be considered (in order) to find the path to the format to compile. The build marker system has been updated to store the markers in the package.json rather than an additional external file. Also instead of tracking the underlying bundle format that was compiled, it now tracks the package.json property. BREAKING CHANGE: The `proertiesToConsider` option replaces the previous `formats` option, which specified the final bundle format, rather than the property in the package.json. If you were using this option to compile only specific bundle formats, you must now modify your usage to pass in the properties in the package.json that map to the format that you wish to compile. In the CLI, the `--formats` is no longer available. Instead use the `--properties` option. FW-1120 PR Close angular#29092
1 parent 4bb0259 commit cd44902

File tree

11 files changed

+329
-244
lines changed

11 files changed

+329
-244
lines changed

aio/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"build": "yarn ~~build",
1818
"prebuild-local": "yarn setup-local",
1919
"build-local": "yarn ~~build",
20-
"prebuild-with-ivy": "yarn setup-local && yarn ivy-ngcc --formats fesm2015 fesm5",
20+
"prebuild-with-ivy": "yarn setup-local && yarn ivy-ngcc",
2121
"build-with-ivy": "node scripts/build-with-ivy",
2222
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js cafa558cf",
2323
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",

aio/tools/examples/example-boilerplate.js

Lines changed: 38 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,80 +12,36 @@ const EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples');
1212

1313
const BOILERPLATE_PATHS = {
1414
cli: [
15-
'src/environments/environment.prod.ts',
16-
'src/environments/environment.ts',
17-
'src/assets/.gitkeep',
18-
'src/browserslist',
19-
'src/favicon.ico',
20-
'src/karma.conf.js',
21-
'src/polyfills.ts',
22-
'src/test.ts',
23-
'src/tsconfig.app.json',
24-
'src/tsconfig.spec.json',
25-
'src/tslint.json',
26-
'e2e/src/app.po.ts',
27-
'e2e/protractor.conf.js',
28-
'e2e/tsconfig.e2e.json',
29-
'.editorconfig',
30-
'angular.json',
31-
'package.json',
32-
'tsconfig.json',
33-
'tslint.json'
15+
'src/environments/environment.prod.ts', 'src/environments/environment.ts',
16+
'src/assets/.gitkeep', 'src/browserslist', 'src/favicon.ico', 'src/karma.conf.js',
17+
'src/polyfills.ts', 'src/test.ts', 'src/tsconfig.app.json', 'src/tsconfig.spec.json',
18+
'src/tslint.json', 'e2e/src/app.po.ts', 'e2e/protractor.conf.js', 'e2e/tsconfig.e2e.json',
19+
'.editorconfig', 'angular.json', 'package.json', 'tsconfig.json', 'tslint.json'
3420
],
3521
systemjs: [
36-
'src/systemjs-angular-loader.js',
37-
'src/systemjs.config.js',
38-
'src/tsconfig.json',
39-
'bs-config.json',
40-
'bs-config.e2e.json',
41-
'package.json',
42-
'tslint.json'
22+
'src/systemjs-angular-loader.js', 'src/systemjs.config.js', 'src/tsconfig.json',
23+
'bs-config.json', 'bs-config.e2e.json', 'package.json', 'tslint.json'
4324
],
44-
common: [
45-
'src/styles.css'
46-
]
25+
common: ['src/styles.css']
4726
};
4827

4928
// All paths in this tool are relative to the current boilerplate folder, i.e boilerplate/i18n
5029
// This maps the CLI files that exists in a parent folder
5130
const cliRelativePath = BOILERPLATE_PATHS.cli.map(file => `../cli/${file}`);
5231

53-
BOILERPLATE_PATHS.elements = [
54-
...cliRelativePath,
55-
'tsconfig.json'
56-
];
32+
BOILERPLATE_PATHS.elements = [...cliRelativePath, 'tsconfig.json'];
5733

58-
BOILERPLATE_PATHS.i18n = [
59-
...cliRelativePath,
60-
'angular.json',
61-
'package.json'
62-
];
34+
BOILERPLATE_PATHS.i18n = [...cliRelativePath, 'angular.json', 'package.json'];
6335

64-
BOILERPLATE_PATHS['service-worker'] = [
65-
...cliRelativePath,
66-
'angular.json',
67-
'package.json'
68-
];
36+
BOILERPLATE_PATHS['service-worker'] = [...cliRelativePath, 'angular.json', 'package.json'];
6937

70-
BOILERPLATE_PATHS.testing = [
71-
...cliRelativePath,
72-
'angular.json'
73-
];
38+
BOILERPLATE_PATHS.testing = [...cliRelativePath, 'angular.json'];
7439

75-
BOILERPLATE_PATHS.universal = [
76-
...cliRelativePath,
77-
'angular.json',
78-
'package.json'
79-
];
40+
BOILERPLATE_PATHS.universal = [...cliRelativePath, 'angular.json', 'package.json'];
8041

8142
BOILERPLATE_PATHS.ivy = {
82-
systemjs: [
83-
'rollup-config.js',
84-
'tsconfig-aot.json'
85-
],
86-
cli: [
87-
'src/tsconfig.app.json'
88-
]
43+
systemjs: ['rollup-config.js', 'tsconfig-aot.json'],
44+
cli: ['src/tsconfig.app.json']
8945
};
9046

9147
BOILERPLATE_PATHS.schematics = [
@@ -101,11 +57,13 @@ class ExampleBoilerPlate {
10157
*/
10258
add(ivy = false) {
10359
// Get all the examples folders, indicated by those that contain a `example-config.json` file
104-
const exampleFolders = this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
60+
const exampleFolders =
61+
this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
10562

10663
if (!fs.existsSync(SHARED_NODE_MODULES_PATH)) {
107-
throw new Error(`The shared node_modules folder for the examples (${SHARED_NODE_MODULES_PATH}) is missing.\n` +
108-
`Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`);
64+
throw new Error(
65+
`The shared node_modules folder for the examples (${SHARED_NODE_MODULES_PATH}) is missing.\n` +
66+
`Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`);
10967
}
11068

11169
if (ivy) {
@@ -114,7 +72,7 @@ class ExampleBoilerPlate {
11472
// the module typings if we specified an "es2015" format. This means that
11573
// we also need to build with "fesm2015" in order to get updated typings
11674
// which are needed for compilation.
117-
shelljs.exec(`yarn --cwd ${SHARED_PATH} ivy-ngcc --formats fesm2015 fesm5`);
75+
shelljs.exec(`yarn --cwd ${SHARED_PATH} ivy-ngcc`);
11876
}
11977

12078
exampleFolders.forEach(exampleFolder => {
@@ -128,40 +86,41 @@ class ExampleBoilerPlate {
12886
const boilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, boilerPlateType);
12987

13088
// Copy the boilerplate specific files
131-
BOILERPLATE_PATHS[boilerPlateType].forEach(filePath => this.copyFile(boilerPlateBasePath, exampleFolder, filePath));
89+
BOILERPLATE_PATHS[boilerPlateType].forEach(
90+
filePath => this.copyFile(boilerPlateBasePath, exampleFolder, filePath));
13291

13392
// Copy the boilerplate common files
134-
BOILERPLATE_PATHS.common.forEach(filePath => this.copyFile(BOILERPLATE_COMMON_BASE_PATH, exampleFolder, filePath));
93+
BOILERPLATE_PATHS.common.forEach(
94+
filePath => this.copyFile(BOILERPLATE_COMMON_BASE_PATH, exampleFolder, filePath));
13595

13696
// Copy Ivy specific files
13797
if (ivy) {
13898
const ivyBoilerPlateType = boilerPlateType === 'systemjs' ? 'systemjs' : 'cli';
139-
const ivyBoilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, 'ivy', ivyBoilerPlateType);
140-
BOILERPLATE_PATHS.ivy[ivyBoilerPlateType].forEach(filePath => this.copyFile(ivyBoilerPlateBasePath, exampleFolder, filePath));
99+
const ivyBoilerPlateBasePath =
100+
path.resolve(BOILERPLATE_BASE_PATH, 'ivy', ivyBoilerPlateType);
101+
BOILERPLATE_PATHS.ivy[ivyBoilerPlateType].forEach(
102+
filePath => this.copyFile(ivyBoilerPlateBasePath, exampleFolder, filePath));
141103
}
142104
});
143105
}
144106

145107
/**
146108
* Remove all the boilerplate files from all the examples
147109
*/
148-
remove() {
149-
shelljs.exec('git clean -xdfq', { cwd: EXAMPLES_BASE_PATH });
150-
}
110+
remove() { shelljs.exec('git clean -xdfq', {cwd: EXAMPLES_BASE_PATH}); }
151111

152112
main() {
153-
yargs
154-
.usage('$0 <cmd> [args]')
155-
.command('add', 'add the boilerplate to each example', (yrgs) => this.add(yrgs.argv.ivy))
156-
.command('remove', 'remove the boilerplate from each example', () => this.remove())
157-
.demandCommand(1, 'Please supply a command from the list above')
158-
.argv;
113+
yargs.usage('$0 <cmd> [args]')
114+
.command('add', 'add the boilerplate to each example', (yrgs) => this.add(yrgs.argv.ivy))
115+
.command('remove', 'remove the boilerplate from each example', () => this.remove())
116+
.demandCommand(1, 'Please supply a command from the list above')
117+
.argv;
159118
}
160119

161120
getFoldersContaining(basePath, filename, ignore) {
162121
const pattern = path.resolve(basePath, '**', filename);
163122
const ignorePattern = path.resolve(basePath, '**', ignore, '**');
164-
return glob.sync(pattern, { ignore: [ignorePattern] }).map(file => path.dirname(file));
123+
return glob.sync(pattern, {ignore: [ignorePattern]}).map(file => path.dirname(file));
165124
}
166125

167126
copyFile(sourceFolder, destinationFolder, filePath) {
@@ -171,13 +130,11 @@ class ExampleBoilerPlate {
171130
filePath = this.normalizePath(filePath);
172131

173132
const destinationPath = path.resolve(destinationFolder, filePath);
174-
fs.copySync(sourcePath, destinationPath, { overwrite: true });
133+
fs.copySync(sourcePath, destinationPath, {overwrite: true});
175134
fs.chmodSync(destinationPath, 444);
176135
}
177136

178-
loadJsonFile(filePath) {
179-
return fs.readJsonSync(filePath, { throws: false }) || {};
180-
}
137+
loadJsonFile(filePath) { return fs.readJsonSync(filePath, {throws: false}) || {}; }
181138

182139
normalizePath(filePath) {
183140
// transform for example ../cli/src/tsconfig.app.json to src/tsconfig.app.json

integration/ngcc/test.sh

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,25 @@ ivy-ngcc --help
1010
ivy-ngcc
1111

1212
# Did it add the appropriate build markers?
13+
14+
# - esm2015
15+
grep '"__modified_by_ngcc__":[^}]*"esm2015":"' node_modules/@angular/common/package.json
16+
if [[ $? != 0 ]]; then exit 1; fi
17+
1318
# - fesm2015
14-
ls node_modules/@angular/common | grep __modified_by_ngcc_for_fesm2015
19+
grep '"__modified_by_ngcc__":[^}]*"fesm2015":"' node_modules/@angular/common/package.json
1520
if [[ $? != 0 ]]; then exit 1; fi
16-
# - esm2015
17-
ls node_modules/@angular/common | grep __modified_by_ngcc_for_esm2015
21+
grep '"__modified_by_ngcc__":[^}]*"es2015":"' node_modules/@angular/common/package.json
22+
if [[ $? != 0 ]]; then exit 1; fi
23+
24+
# - esm5
25+
grep '"__modified_by_ngcc__":[^}]*"esm5":"' node_modules/@angular/common/package.json
26+
if [[ $? != 0 ]]; then exit 1; fi
27+
28+
# - fesm5
29+
grep '"__modified_by_ngcc__":[^}]*"module":"' node_modules/@angular/common/package.json
30+
if [[ $? != 0 ]]; then exit 1; fi
31+
grep '"__modified_by_ngcc__":[^}]*"fesm5":"' node_modules/@angular/common/package.json
1832
if [[ $? != 0 ]]; then exit 1; fi
1933

2034
# Did it replace the PRE_R3 markers correctly?
@@ -48,6 +62,9 @@ ivy-ngcc
4862
# Can it be safely run again (as a noop)?
4963
ivy-ngcc
5064

65+
# Does running it with --formats fail?
66+
ivy-ngcc --formats fesm2015 && exit 1
67+
5168
# Now try compiling the app using the ngcc compiled libraries
5269
ngc -p tsconfig-app.json
5370

packages/compiler-cli/ngcc/main-ngcc.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as path from 'canonical-path';
1010
import * as yargs from 'yargs';
1111

1212
import {mainNgcc} from './src/main';
13-
import {EntryPointFormat} from './src/packages/entry_point';
13+
import {EntryPointJsonProperty} from './src/packages/entry_point';
1414

1515
// CLI entry point
1616
if (require.main === module) {
@@ -22,11 +22,15 @@ if (require.main === module) {
2222
describe: 'A path to the root folder to compile.',
2323
default: './node_modules'
2424
})
25-
.option('f', {
26-
alias: 'formats',
25+
.option('f', {alias: 'formats', hiddentrue, array: true})
26+
.option('p', {
27+
alias: 'properties',
2728
array: true,
28-
describe: 'An array of formats to compile.',
29-
default: ['fesm2015', 'esm2015', 'fesm5', 'esm5']
29+
describe:
30+
'An array of names of properties in package.json (e.g. `module` or `es2015`)\n' +
31+
'These properties should hold a path to a bundle-format to compile.\n' +
32+
'If provided, only the specified properties are considered for processing.\n' +
33+
'If not provided, all the supported format properties (e.g. fesm2015, fesm5, es2015, esm2015, esm5, main, module) in the package.json are considered.'
3034
})
3135
.option('t', {
3236
alias: 'target',
@@ -36,11 +40,16 @@ if (require.main === module) {
3640
.help()
3741
.parse(args);
3842

43+
if (options['f'] && options['f'].length) {
44+
console.error(
45+
'The formats option (-f/--formats) has been removed. Consider the properties option (-p/--properties) instead.');
46+
process.exit(1);
47+
}
3948
const baseSourcePath: string = path.resolve(options['s']);
40-
const formats: EntryPointFormat[] = options['f'];
49+
const propertiesToConsider: EntryPointJsonProperty[] = options['p'];
4150
const baseTargetPath: string = options['t'];
4251
try {
43-
mainNgcc({baseSourcePath, formats, baseTargetPath});
52+
mainNgcc({baseSourcePath, propertiesToConsider, baseTargetPath});
4453
process.exitCode = 0;
4554
} catch (e) {
4655
console.error(e.stack || e.message);

0 commit comments

Comments
 (0)