From 6eafaa7b5e2b85e53b4213f9f7756474609a0fa3 Mon Sep 17 00:00:00 2001 From: JoostK Date: Thu, 29 Apr 2021 23:22:35 +0200 Subject: [PATCH] fix(compiler-cli): expose the linker as a Babel plugin (#41918) This allows the linker to be used as a true Babel plugin. In a Babel configuration file, include the linker as follows: ```js { plugins: [ '@angular/compiler-cli/linker/babel', ] } ``` or, if you need to specify configuration options: ```js { plugins: [ ['@angular/compiler-cli/linker/babel', {linkerJitMode: true}], ] } ``` PR Close #41918 --- packages/compiler-cli/linker/babel/index.ts | 5 +- .../linker/babel/src/babel_plugin.ts | 39 +++++++++++++ .../linker/babel/test/babel_plugin_spec.ts | 56 +++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 packages/compiler-cli/linker/babel/src/babel_plugin.ts create mode 100644 packages/compiler-cli/linker/babel/test/babel_plugin_spec.ts diff --git a/packages/compiler-cli/linker/babel/index.ts b/packages/compiler-cli/linker/babel/index.ts index cf9450bf4b..6b6132e7fe 100644 --- a/packages/compiler-cli/linker/babel/index.ts +++ b/packages/compiler-cli/linker/babel/index.ts @@ -5,4 +5,7 @@ * 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 */ -export {createEs2015LinkerPlugin} from './src/es2015_linker_plugin'; \ No newline at end of file +import {defaultLinkerPlugin} from './src/babel_plugin'; + +export {createEs2015LinkerPlugin} from './src/es2015_linker_plugin'; +export default defaultLinkerPlugin; diff --git a/packages/compiler-cli/linker/babel/src/babel_plugin.ts b/packages/compiler-cli/linker/babel/src/babel_plugin.ts new file mode 100644 index 0000000000..68013ee0d1 --- /dev/null +++ b/packages/compiler-cli/linker/babel/src/babel_plugin.ts @@ -0,0 +1,39 @@ +/** + * @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 + */ +import {ConfigAPI, PluginObj} from '@babel/core'; + +import {NodeJSFileSystem} from '../../../src/ngtsc/file_system'; +import {ConsoleLogger, LogLevel} from '../../../src/ngtsc/logging'; +import {LinkerOptions} from '../../src/file_linker/linker_options'; + +import {createEs2015LinkerPlugin} from './es2015_linker_plugin'; + +/** + * This is the Babel plugin definition that is provided as a default export from the package, such + * that the plugin can be used using the module specifier of the package. This is the recommended + * way of integrating the Angular Linker into a build pipeline other than the Angular CLI. + * + * When the module specifier `@angular/compiler-cli/linker/babel` is used as a plugin in a Babel + * configuration, Babel invokes this function (by means of the default export) to create the plugin + * instance according to the provided options. + * + * The linker plugin that is created uses the native NodeJS filesystem APIs to interact with the + * filesystem. Any logging output is printed to the console. + * + * @param api Provides access to the Babel environment that is configuring this plugin. + * @param options The plugin options that have been configured. + */ +export function defaultLinkerPlugin(api: ConfigAPI, options: Partial): PluginObj { + api.assertVersion(7); + + return createEs2015LinkerPlugin({ + ...options, + fileSystem: new NodeJSFileSystem(), + logger: new ConsoleLogger(LogLevel.info), + }); +} diff --git a/packages/compiler-cli/linker/babel/test/babel_plugin_spec.ts b/packages/compiler-cli/linker/babel/test/babel_plugin_spec.ts new file mode 100644 index 0000000000..781cd3b868 --- /dev/null +++ b/packages/compiler-cli/linker/babel/test/babel_plugin_spec.ts @@ -0,0 +1,56 @@ +/** + * @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 + */ +import {transformSync} from '@babel/core'; + +describe('default babel plugin entry-point', () => { + it('should work as a Babel plugin using the module specifier', () => { + const result = transformSync( + ` + import * as i0 from "@angular/core"; + + export class MyMod {} + export class MyComponent {} + + MyMod.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyMod, declarations: [MyComponent] }); + `, + { + plugins: [ + '@angular/compiler-cli/linker/babel', + ], + filename: 'test.js', + })!; + + expect(result).not.toBeNull(); + expect(result.code).not.toContain('ɵɵngDeclareNgModule'); + expect(result.code).toContain('i0.ɵɵdefineNgModule'); + expect(result.code).not.toMatch(/declarations:\s*\[MyComponent]/); + }); + + it('should be configurable', () => { + const result = transformSync( + ` + import * as i0 from "@angular/core"; + + export class MyMod {} + export class MyComponent {} + + MyMod.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyMod, declarations: [MyComponent] }); + `, + { + plugins: [ + ['@angular/compiler-cli/linker/babel', {linkerJitMode: true}], + ], + filename: 'test.js', + })!; + + expect(result).not.toBeNull(); + expect(result.code).not.toContain('ɵɵngDeclareNgModule'); + expect(result.code).toContain('i0.ɵɵdefineNgModule'); + expect(result.code).toMatch(/declarations:\s*\[MyComponent]/); + }); +});