mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 11:03:53 +08:00
feat(@angular-devkit/build-angular): integrate JIT mode linker
With this change we intergate JIT mode linker into the Angular CLI. Closes #20281
This commit is contained in:
parent
8862a9f07c
commit
2616ef0d3f
@ -16,7 +16,10 @@ export interface ApplicationPresetOptions {
|
|||||||
translation?: unknown;
|
translation?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
angularLinker?: boolean;
|
angularLinker?: {
|
||||||
|
shouldLink: boolean;
|
||||||
|
jitMode: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
forceES5?: boolean;
|
forceES5?: boolean;
|
||||||
forceAsyncTransformation?: boolean;
|
forceAsyncTransformation?: boolean;
|
||||||
@ -124,13 +127,14 @@ export default function (api: unknown, options: ApplicationPresetOptions) {
|
|||||||
const plugins = [];
|
const plugins = [];
|
||||||
let needRuntimeTransform = false;
|
let needRuntimeTransform = false;
|
||||||
|
|
||||||
if (options.angularLinker) {
|
if (options.angularLinker?.shouldLink) {
|
||||||
// Babel currently is synchronous so import cannot be used
|
// Babel currently is synchronous so import cannot be used
|
||||||
const {
|
const {
|
||||||
createEs2015LinkerPlugin,
|
createEs2015LinkerPlugin,
|
||||||
} = require('@angular/compiler-cli/linker/babel');
|
} = require('@angular/compiler-cli/linker/babel') as typeof import('@angular/compiler-cli/linker/babel');
|
||||||
|
|
||||||
plugins.push(createEs2015LinkerPlugin({
|
plugins.push(createEs2015LinkerPlugin({
|
||||||
|
linkerJitMode: options.angularLinker.jitMode,
|
||||||
logger: createNgtscLogger(options.diagnosticReporter),
|
logger: createNgtscLogger(options.diagnosticReporter),
|
||||||
fileSystem: {
|
fileSystem: {
|
||||||
resolve: path.resolve,
|
resolve: path.resolve,
|
||||||
@ -138,7 +142,9 @@ export default function (api: unknown, options: ApplicationPresetOptions) {
|
|||||||
dirname: path.dirname,
|
dirname: path.dirname,
|
||||||
relative: path.relative,
|
relative: path.relative,
|
||||||
readFile: fs.readFileSync,
|
readFile: fs.readFileSync,
|
||||||
},
|
// Node.JS types don't overlap the Compiler types.
|
||||||
|
// tslint:disable-next-line: no-any
|
||||||
|
} as any,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,9 @@ import { custom } from 'babel-loader';
|
|||||||
import { ScriptTarget } from 'typescript';
|
import { ScriptTarget } from 'typescript';
|
||||||
import { ApplicationPresetOptions } from './presets/application';
|
import { ApplicationPresetOptions } from './presets/application';
|
||||||
|
|
||||||
interface AngularCustomOptions {
|
interface AngularCustomOptions extends Pick<ApplicationPresetOptions, 'angularLinker' | 'i18n'> {
|
||||||
forceAsyncTransformation: boolean;
|
forceAsyncTransformation: boolean;
|
||||||
forceES5: boolean;
|
forceES5: boolean;
|
||||||
shouldLink: boolean;
|
|
||||||
i18n: ApplicationPresetOptions['i18n'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function requiresLinking(
|
function requiresLinking(
|
||||||
@ -41,20 +39,25 @@ export default custom<AngularCustomOptions>(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async customOptions({ i18n, scriptTarget, ...rawOptions }, { source }) {
|
async customOptions({ i18n, scriptTarget, aot, ...rawOptions }, { source }) {
|
||||||
// Must process file if plugins are added
|
// Must process file if plugins are added
|
||||||
let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
|
let shouldProcess = Array.isArray(rawOptions.plugins) && rawOptions.plugins.length > 0;
|
||||||
|
|
||||||
const customOptions: AngularCustomOptions = {
|
const customOptions: AngularCustomOptions = {
|
||||||
forceAsyncTransformation: false,
|
forceAsyncTransformation: false,
|
||||||
forceES5: false,
|
forceES5: false,
|
||||||
shouldLink: false,
|
angularLinker: undefined,
|
||||||
i18n: undefined,
|
i18n: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Analyze file for linking
|
// Analyze file for linking
|
||||||
customOptions.shouldLink = await requiresLinking(this.resourcePath, source);
|
if (await requiresLinking(this.resourcePath, source)) {
|
||||||
shouldProcess ||= customOptions.shouldLink;
|
customOptions.angularLinker = {
|
||||||
|
shouldLink: true,
|
||||||
|
jitMode: aot !== true,
|
||||||
|
};
|
||||||
|
shouldProcess = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Analyze for ES target processing
|
// Analyze for ES target processing
|
||||||
const esTarget = scriptTarget as ScriptTarget | undefined;
|
const esTarget = scriptTarget as ScriptTarget | undefined;
|
||||||
@ -109,10 +112,7 @@ export default custom<AngularCustomOptions>(() => {
|
|||||||
[
|
[
|
||||||
require('./presets/application').default,
|
require('./presets/application').default,
|
||||||
{
|
{
|
||||||
angularLinker: customOptions.shouldLink,
|
...customOptions,
|
||||||
forceES5: customOptions.forceES5,
|
|
||||||
forceAsyncTransformation: customOptions.forceAsyncTransformation,
|
|
||||||
i18n: customOptions.i18n,
|
|
||||||
diagnosticReporter: (type, message) => {
|
diagnosticReporter: (type, message) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'error':
|
case 'error':
|
||||||
|
@ -493,6 +493,7 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
|
|||||||
options: {
|
options: {
|
||||||
cacheDirectory: findCachePath('babel-webpack'),
|
cacheDirectory: findCachePath('babel-webpack'),
|
||||||
scriptTarget: wco.scriptTarget,
|
scriptTarget: wco.scriptTarget,
|
||||||
|
aot: buildOptions.aot,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
...buildOptimizerUseRule,
|
...buildOptimizerUseRule,
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { writeFile } from '../../../utils/fs';
|
|
||||||
import { getActivePackageManager } from '../../../utils/packages';
|
|
||||||
import { ng, silentYarn } from '../../../utils/process';
|
|
||||||
import { updateJsonFile } from '../../../utils/project';
|
|
||||||
import { getGlobalVariable } from '../../../utils/env';
|
import { getGlobalVariable } from '../../../utils/env';
|
||||||
|
import { writeFile } from '../../../utils/fs';
|
||||||
|
import { ng } from '../../../utils/process';
|
||||||
|
import { updateJsonFile } from '../../../utils/project';
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
if ((getGlobalVariable('argv')['ve'])) {
|
if ((getGlobalVariable('argv')['ve'])) {
|
||||||
@ -13,8 +12,7 @@ export default async function () {
|
|||||||
await ng('generate', 'library', 'my-lib');
|
await ng('generate', 'library', 'my-lib');
|
||||||
|
|
||||||
// Enable partial compilation mode (linker) for the library
|
// 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.json', config => {
|
||||||
await updateJsonFile('projects/my-lib/tsconfig.lib.prod.json', config => {
|
|
||||||
const { angularCompilerOptions = {} } = config;
|
const { angularCompilerOptions = {} } = config;
|
||||||
angularCompilerOptions.enableIvy = true;
|
angularCompilerOptions.enableIvy = true;
|
||||||
angularCompilerOptions.compilationMode = 'partial';
|
angularCompilerOptions.compilationMode = 'partial';
|
||||||
@ -51,7 +49,7 @@ export default async function () {
|
|||||||
template: '<lib-my-lib></lib-my-lib>'
|
template: '<lib-my-lib></lib-my-lib>'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'app';
|
title = 'test-project';
|
||||||
|
|
||||||
constructor(myLibService: MyLibService) {
|
constructor(myLibService: MyLibService) {
|
||||||
console.log(myLibService);
|
console.log(myLibService);
|
||||||
@ -85,18 +83,23 @@ export default async function () {
|
|||||||
});
|
});
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await runLibraryTests();
|
// Build library in partial mode (development)
|
||||||
await runLibraryTests(true);
|
await ng('build', 'my-lib', '--configuration=development');
|
||||||
|
|
||||||
|
// AOT linking
|
||||||
|
await runTests();
|
||||||
|
|
||||||
|
// 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 runLibraryTests(prodMode = false): Promise<void> {
|
async function runTests(): Promise<void> {
|
||||||
const args = ['build', 'my-lib'];
|
|
||||||
if (!prodMode) {
|
|
||||||
args.push('--configuration=development');
|
|
||||||
}
|
|
||||||
|
|
||||||
await ng(...args);
|
|
||||||
|
|
||||||
// Check that the tests succeeds both with named project, unnamed (should test app), and prod.
|
// Check that the tests succeeds both with named project, unnamed (should test app), and prod.
|
||||||
await ng('e2e');
|
await ng('e2e');
|
||||||
await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production');
|
await ng('e2e', 'test-project', '--devServerTarget=test-project:serve:production');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user