Skip to content

Commit

Permalink
fix(compiler-cli): expose the linker as a Babel plugin (#41918)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JoostK authored and mhevery committed May 4, 2021
1 parent 9759bca commit 8fdac8f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
5 changes: 4 additions & 1 deletion packages/compiler-cli/linker/babel/index.ts
Expand Up @@ -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';
import {defaultLinkerPlugin} from './src/babel_plugin';

export {createEs2015LinkerPlugin} from './src/es2015_linker_plugin';
export default defaultLinkerPlugin;
39 changes: 39 additions & 0 deletions 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<LinkerOptions>): PluginObj {
api.assertVersion(7);

return createEs2015LinkerPlugin({
...options,
fileSystem: new NodeJSFileSystem(),
logger: new ConsoleLogger(LogLevel.info),
});
}
56 changes: 56 additions & 0 deletions 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]/);
});
});

0 comments on commit 8fdac8f

Please sign in to comment.