Skip to content

Commit

Permalink
refactor(@angular/cli): support bootstrapping with CommonJS startup code
Browse files Browse the repository at this point in the history
To support the eventual migration of the CLI to ESM, the CLI commandline tool is now bootstrapped by dynamically importing the main initialization code. This is done to allow the main bin file (`ng`) to remain CommonJS so that older versions of Node.js can be checked and validated prior to the execution of the CLI. This separate bootstrap file is needed to allow the use of a dynamic import expression without crashing older versions of Node.js that do not support dynamic import expressions and would otherwise throw a syntax error. This bootstrap file is required from the main bin file only after the Node.js version is determined to be in the supported range. The use of the dynamic import expression allows CommonJS code to execute either CommonJS or ESM code.
  • Loading branch information
clydin authored and alan-agius4 committed Aug 26, 2021
1 parent a7de97e commit 3df6fba
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 7 deletions.
21 changes: 21 additions & 0 deletions packages/angular/cli/bin/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/**
* @fileoverview
*
* This file is used to bootstrap the CLI process by dynamically importing the main initialization code.
* This is done to allow the main bin file (`ng`) to remain CommonJS so that older versions of Node.js
* can be checked and validated prior to the execution of the CLI. This separate bootstrap file is
* needed to allow the use of a dynamic import expression without crashing older versions of Node.js that
* do not support dynamic import expressions and would otherwise throw a syntax error. This bootstrap file
* is required from the main bin file only after the Node.js version is determined to be in the supported
* range.
*/

import('../lib/init.js');
19 changes: 14 additions & 5 deletions packages/angular/cli/bin/ng → packages/angular/cli/bin/ng.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#!/usr/bin/env node
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/* eslint-disable no-console */
/* eslint-disable import/no-unassigned-import */
'use strict';

// Provide a title to the process in `ps`.
Expand All @@ -13,7 +23,6 @@ try {
// This node version check ensures that extremely old versions of node are not used.
// These may not support ES2015 features such as const/let/async/await/etc.
// These would then crash with a hard to diagnose error message.
// tslint:disable-next-line: no-var-keyword
var version = process.versions.node.split('.').map((part) => Number(part));
if (version[0] % 2 === 1 && version[0] > 14) {
// Allow new odd numbered releases with a warning (currently v15+)
Expand All @@ -25,23 +34,23 @@ if (version[0] % 2 === 1 && version[0] > 14) {
' For more information, please see https://nodejs.org/en/about/releases/.',
);

require('../lib/init');
require('./bootstrap');
} else if (
version[0] < 12 ||
version[0] === 13 ||
(version[0] === 12 && version[1] < 20) ||
(version[0] === 14 && version[1] < 15)
) {
// Error and exit if less than 12.14 or 13.x or less than 14.15
// Error and exit if less than 12.20 or 13.x or less than 14.15
console.error(
'Node.js version ' +
process.version +
' detected.\n' +
'The Angular CLI requires a minimum Node.js version of either v12.14 or v14.15.\n\n' +
'The Angular CLI requires a minimum Node.js version of either v12.20 or v14.15.\n\n' +
'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n',
);

process.exitCode = 3;
} else {
require('../lib/init');
require('./bootstrap');
}
3 changes: 3 additions & 0 deletions packages/angular/cli/bin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
10 changes: 9 additions & 1 deletion packages/angular/cli/bin/postinstall/analytics-prompt.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

'use strict';
// This file is ES6 because it needs to be executed as is.
// This file is ES5 because it needs to be executed as is.

if ('NG_CLI_ANALYTICS' in process.env) {
return;
Expand Down
9 changes: 9 additions & 0 deletions packages/angular/cli/bin/postinstall/script.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#!/usr/bin/env node
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

'use strict';

// These should not fail but if they do they should not block installation of the package
try {
// eslint-disable-next-line import/no-unassigned-import
require('./analytics-prompt');
} catch (_) {}
2 changes: 1 addition & 1 deletion packages/angular/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "CLI tool for Angular",
"main": "lib/cli/index.js",
"bin": {
"ng": "./bin/ng"
"ng": "./bin/ng.js"
},
"keywords": [
"angular",
Expand Down

0 comments on commit 3df6fba

Please sign in to comment.