diff --git a/packages/angular_devkit/build_angular/src/babel/presets/application.ts b/packages/angular_devkit/build_angular/src/babel/presets/application.ts index bd5ffcc6b52f..a1cf286cda8b 100644 --- a/packages/angular_devkit/build_angular/src/babel/presets/application.ts +++ b/packages/angular_devkit/build_angular/src/babel/presets/application.ts @@ -16,7 +16,10 @@ export interface ApplicationPresetOptions { translation?: unknown; }; - angularLinker?: boolean; + angularLinker?: { + shouldLink: boolean; + jitMode: boolean; + }; forceES5?: boolean; forceAsyncTransformation?: boolean; @@ -124,13 +127,14 @@ export default function (api: unknown, options: ApplicationPresetOptions) { const plugins = []; let needRuntimeTransform = false; - if (options.angularLinker) { + if (options.angularLinker?.shouldLink) { // Babel currently is synchronous so import cannot be used const { createEs2015LinkerPlugin, - } = require('@angular/compiler-cli/linker/babel'); + } = require('@angular/compiler-cli/linker/babel') as typeof import('@angular/compiler-cli/linker/babel'); plugins.push(createEs2015LinkerPlugin({ + linkerJitMode: options.angularLinker.jitMode, logger: createNgtscLogger(options.diagnosticReporter), fileSystem: { resolve: path.resolve, @@ -138,7 +142,9 @@ export default function (api: unknown, options: ApplicationPresetOptions) { dirname: path.dirname, relative: path.relative, readFile: fs.readFileSync, - }, + // Node.JS types don't overlap the Compiler types. + // tslint:disable-next-line: no-any + } as any, })); } diff --git a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts index a3b65df921c5..fefbfa10c4fa 100644 --- a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts +++ b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts @@ -10,11 +10,9 @@ import { custom } from 'babel-loader'; import { ScriptTarget } from 'typescript'; import { ApplicationPresetOptions } from './presets/application'; -interface AngularCustomOptions { +interface AngularCustomOptions extends Pick { forceAsyncTransformation: boolean; forceES5: boolean; - shouldLink: boolean; - i18n: ApplicationPresetOptions['i18n']; } function requiresLinking( @@ -41,20 +39,25 @@ export default custom(() => { }); return { - async customOptions({ i18n, scriptTarget, ...rawOptions }, { source }) { + async customOptions({ i18n, scriptTarget, aot, ...rawOptions }, { source }) { // Must process file if plugins are added let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0; const customOptions: AngularCustomOptions = { forceAsyncTransformation: false, forceES5: false, - shouldLink: false, + angularLinker: undefined, i18n: undefined, }; // Analyze file for linking - customOptions.shouldLink = await requiresLinking(this.resourcePath, source); - shouldProcess ||= customOptions.shouldLink; + if (await requiresLinking(this.resourcePath, source)) { + customOptions.angularLinker = { + shouldLink: true, + jitMode: aot !== true, + }; + shouldProcess = true; + } // Analyze for ES target processing const esTarget = scriptTarget as ScriptTarget | undefined; @@ -109,10 +112,7 @@ export default custom(() => { [ require('./presets/application').default, { - angularLinker: customOptions.shouldLink, - forceES5: customOptions.forceES5, - forceAsyncTransformation: customOptions.forceAsyncTransformation, - i18n: customOptions.i18n, + ...customOptions, diagnosticReporter: (type, message) => { switch (type) { case 'error': diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts index 89fdeb03bf0e..9b8e4a6f51c1 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts @@ -493,6 +493,7 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration { options: { cacheDirectory: findCachePath('babel-webpack'), scriptTarget: wco.scriptTarget, + aot: buildOptions.aot, }, }, ...buildOptimizerUseRule, diff --git a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-linker.ts b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-linker.ts index 8275c5b5491b..4875cb03a247 100644 --- a/tests/legacy-cli/e2e/tests/generate/library/library-consumption-linker.ts +++ b/tests/legacy-cli/e2e/tests/generate/library/library-consumption-linker.ts @@ -1,8 +1,7 @@ +import { getGlobalVariable } from '../../../utils/env'; import { writeFile } from '../../../utils/fs'; -import { getActivePackageManager } from '../../../utils/packages'; -import { ng, silentYarn } from '../../../utils/process'; +import { ng } from '../../../utils/process'; import { updateJsonFile } from '../../../utils/project'; -import { getGlobalVariable } from '../../../utils/env'; export default async function () { if ((getGlobalVariable('argv')['ve'])) { @@ -13,8 +12,7 @@ export default async function () { await ng('generate', 'library', 'my-lib'); // Enable partial compilation mode (linker) for the library - // Enable ivy for production as well (current schematic disables ivy in production) - await updateJsonFile('projects/my-lib/tsconfig.lib.prod.json', config => { + await updateJsonFile('projects/my-lib/tsconfig.lib.json', config => { const { angularCompilerOptions = {} } = config; angularCompilerOptions.enableIvy = true; angularCompilerOptions.compilationMode = 'partial'; @@ -51,7 +49,7 @@ export default async function () { template: '' }) export class AppComponent { - title = 'app'; + title = 'test-project'; constructor(myLibService: MyLibService) { console.log(myLibService); @@ -85,18 +83,23 @@ export default async function () { }); `); - await runLibraryTests(); - await runLibraryTests(true); -} + // Build library in partial mode (development) + await ng('build', 'my-lib', '--configuration=development'); -async function runLibraryTests(prodMode = false): Promise { - const args = ['build', 'my-lib']; - if (!prodMode) { - args.push('--configuration=development'); - } + // AOT linking + await runTests(); - await ng(...args); + // JIT linking + await updateJsonFile('angular.json', config => { + const build = config.projects['test-project'].architect.build; + build.options.aot = false; + build.configurations.production.buildOptimizer = false; + }); + + await runTests(); +} +async function runTests(): Promise { // Check that the tests succeeds both with named project, unnamed (should test app), and prod. await ng('e2e'); await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production');