mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
fix(compiler): remove TypeScript from linker (#61618)
This commit removes the direct dependency on TypeScript within the linker, addressing a performance overhead that was adding between 500ms to 1s to compilation times for applications. The primary cause of this overhead was the linker's direct reliance on TypeScript's which was caused by importing from barrel files. While convenient, barrel files are detrimental to code splitting and code motion. They force the bundling of all exported modules, even if only a subset is actually used. By removing the usage of this barrel file and restructuring the imports to be more granular, we can avoid unnecessary TypeScript imports. Furthermore, TypeScript has now been changed to an optional peer dependency as using only the linker does not require TypeScript. PR Close #61618
This commit is contained in:
parent
82327f2092
commit
e9fcbb8af1
18 changed files with 67 additions and 23 deletions
|
|
@ -3,7 +3,7 @@
|
|||
# This file should be checked into version control along with the pnpm-lock.yaml file.
|
||||
.npmrc=-1406867100
|
||||
package.json=-1316846371
|
||||
packages/compiler-cli/package.json=1094415146
|
||||
packages/compiler-cli/package.json=-1344632265
|
||||
packages/compiler/package.json=1190056499
|
||||
pnpm-lock.yaml=1584116426
|
||||
pnpm-workspace.yaml=353334404
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ integration/ng_elements/node_modules
|
|||
integration/ng_update/node_modules
|
||||
integration/ng_update_migrations/node_modules
|
||||
integration/ng-add-localize/node_modules
|
||||
integration/no_ts_linker/node_modules
|
||||
integration/nodenext_resolution/node_modules
|
||||
integration/platform-server/node_modules
|
||||
integration/platform-server-zoneless/node_modules
|
||||
|
|
|
|||
5
integration/no_ts_linker/BUILD.bazel
Normal file
5
integration/no_ts_linker/BUILD.bazel
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
load("//integration:index.bzl", "ng_integration_test")
|
||||
|
||||
ng_integration_test(
|
||||
name = "test",
|
||||
)
|
||||
16
integration/no_ts_linker/package.json
Normal file
16
integration/no_ts_linker/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "angular-integration",
|
||||
"description": "Assert that the linker has no dependency on TypeScript.",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@angular/compiler": "file:../../dist/packages-dist/compiler",
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@angular/core": "file:../../dist/packages-dist/core",
|
||||
"rxjs": "file:../../node_modules/rxjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node ./test.mjs"
|
||||
}
|
||||
}
|
||||
18
integration/no_ts_linker/test.mjs
Normal file
18
integration/no_ts_linker/test.mjs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import assert from 'node:assert';
|
||||
|
||||
(async () => {
|
||||
// Verify that TypeScript is not installed.
|
||||
await assert.rejects(
|
||||
() => import('typescript'),
|
||||
({code, message}) => {
|
||||
assert.strictEqual(code, 'ERR_MODULE_NOT_FOUND');
|
||||
assert.match(message, new RegExp(`Cannot find package 'typescript'`));
|
||||
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
// This validates that the linker has no dependency on TypeScript.
|
||||
await import('@angular/compiler-cli/linker');
|
||||
await import('@angular/compiler-cli/linker/babel');
|
||||
})();
|
||||
|
|
@ -16,7 +16,7 @@ import {
|
|||
SourceMapRange,
|
||||
TemplateLiteral,
|
||||
VariableDeclarationType,
|
||||
} from '../../../../src/ngtsc/translator';
|
||||
} from '../../../../src/ngtsc/translator/src/api/ast_factory';
|
||||
|
||||
/**
|
||||
* A Babel flavored implementation of the AstFactory.
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
*/
|
||||
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';
|
||||
import {NodeJSFileSystem} from '../../../src/ngtsc/file_system/src/node_js_file_system';
|
||||
|
||||
/**
|
||||
* This is the Babel plugin definition that is provided as a default export from the package, such
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
import {LinkerOptions} from '../..';
|
||||
import {ReadonlyFileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {ReadonlyFileSystem} from '../../../src/ngtsc/file_system/src/types';
|
||||
import {Logger} from '../../../src/ngtsc/logging';
|
||||
|
||||
export interface LinkerPluginOptions extends Partial<LinkerOptions> {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
import {R3PartialDeclaration} from '@angular/compiler';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {AstObject} from '../ast/ast_value';
|
||||
|
||||
import {DeclarationScope} from './declaration_scope';
|
||||
|
|
@ -15,6 +14,7 @@ import {EmitScope} from './emit_scopes/emit_scope';
|
|||
import {LocalEmitScope} from './emit_scopes/local_emit_scope';
|
||||
import {LinkerEnvironment} from './linker_environment';
|
||||
import {createLinkerMap, PartialLinkerSelector} from './partial_linkers/partial_linker_selector';
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system/src/types';
|
||||
|
||||
export const NO_STATEMENTS: Readonly<any[]> = [] as const;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system/src/types';
|
||||
import {SourceFile, SourceFileLoader} from '../../../src/ngtsc/sourcemaps';
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +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.dev/license
|
||||
*/
|
||||
import {ReadonlyFileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {ReadonlyFileSystem} from '../../../src/ngtsc/file_system/src/types';
|
||||
import {Logger} from '../../../src/ngtsc/logging';
|
||||
import {SourceFileLoader} from '../../../src/ngtsc/sourcemaps';
|
||||
import {AstFactory} from '../../../src/ngtsc/translator';
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import {
|
|||
} from '@angular/compiler';
|
||||
import semver from 'semver';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
|
||||
import {Range} from '../../ast/ast_host';
|
||||
import {AstObject, AstValue} from '../../ast/ast_value';
|
||||
import {FatalLinkerError} from '../../fatal_linker_error';
|
||||
|
|
@ -42,6 +41,7 @@ import {GetSourceFileFn} from '../get_source_file';
|
|||
import {toR3DirectiveMeta} from './partial_directive_linker_1';
|
||||
import {LinkedDefinition, PartialLinker} from './partial_linker';
|
||||
import {extractForwardRef, PLACEHOLDER_VERSION} from './util';
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system/src/types';
|
||||
|
||||
function makeDirectiveMetadata<TExpression>(
|
||||
directiveExpr: AstObject<R3DeclareDirectiveDependencyMetadata, TExpression>,
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@ import {
|
|||
R3QueryMetadata,
|
||||
} from '@angular/compiler';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
|
||||
import {Range} from '../../ast/ast_host';
|
||||
import {AstObject, AstValue} from '../../ast/ast_value';
|
||||
import {FatalLinkerError} from '../../fatal_linker_error';
|
||||
|
||||
import {LinkedDefinition, PartialLinker} from './partial_linker';
|
||||
import {extractForwardRef, getDefaultStandaloneValue, wrapReference} from './util';
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system/src/types';
|
||||
|
||||
/**
|
||||
* A `PartialLinker` that is designed to process `ɵɵngDeclareDirective()` call expressions.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
import semver from 'semver';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
|
||||
import {Logger} from '../../../../src/ngtsc/logging';
|
||||
import {createGetSourceFile} from '../get_source_file';
|
||||
import {LinkerEnvironment} from '../linker_environment';
|
||||
|
|
@ -23,6 +22,7 @@ import {PartialLinker} from './partial_linker';
|
|||
import {PartialNgModuleLinkerVersion1} from './partial_ng_module_linker_1';
|
||||
import {PartialPipeLinkerVersion1} from './partial_pipe_linker_1';
|
||||
import {PLACEHOLDER_VERSION} from './util';
|
||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system/src/types';
|
||||
|
||||
export const ɵɵngDeclareDirective = 'ɵɵngDeclareDirective';
|
||||
export const ɵɵngDeclareClassMetadata = 'ɵɵngDeclareClassMetadata';
|
||||
|
|
|
|||
|
|
@ -6,14 +6,13 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
import * as o from '@angular/compiler';
|
||||
|
||||
import {
|
||||
AstFactory,
|
||||
Context,
|
||||
ExpressionTranslatorVisitor,
|
||||
ImportGenerator,
|
||||
TranslatorOptions,
|
||||
} from '../../../src/ngtsc/translator';
|
||||
} from '../../../src/ngtsc/translator/src/translator';
|
||||
import {Context} from '../../../src/ngtsc/translator/src/context';
|
||||
import {ImportGenerator} from '../../../src/ngtsc/translator/src/api/import_generator';
|
||||
import {AstFactory} from '../../../src/ngtsc/translator/src/api/ast_factory';
|
||||
|
||||
/**
|
||||
* Generic translator helper class, which exposes methods for translating expressions and
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@
|
|||
"@angular/compiler": "0.0.0-PLACEHOLDER",
|
||||
"typescript": ">=5.8 <5.9"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/compiler": "workspace:*"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ import {
|
|||
import {ImportGenerator} from './api/import_generator';
|
||||
import {Context} from './context';
|
||||
|
||||
const UNARY_OPERATORS = new Map<o.UnaryOperator, UnaryOperator>([
|
||||
const UNARY_OPERATORS = /* @__PURE__ */ new Map<o.UnaryOperator, UnaryOperator>([
|
||||
[o.UnaryOperator.Minus, '-'],
|
||||
[o.UnaryOperator.Plus, '+'],
|
||||
]);
|
||||
|
||||
const BINARY_OPERATORS = new Map<o.BinaryOperator, BinaryOperator>([
|
||||
const BINARY_OPERATORS = /* @__PURE__ */ new Map<o.BinaryOperator, BinaryOperator>([
|
||||
[o.BinaryOperator.And, '&&'],
|
||||
[o.BinaryOperator.Bigger, '>'],
|
||||
[o.BinaryOperator.BiggerEquals, '>='],
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ enum PureAnnotation {
|
|||
TERSER = '@__PURE__',
|
||||
}
|
||||
|
||||
const UNARY_OPERATORS: Record<UnaryOperator, ts.PrefixUnaryOperator> = {
|
||||
const UNARY_OPERATORS: Record<UnaryOperator, ts.PrefixUnaryOperator> = /* @__PURE__ */ (() => ({
|
||||
'+': ts.SyntaxKind.PlusToken,
|
||||
'-': ts.SyntaxKind.MinusToken,
|
||||
'!': ts.SyntaxKind.ExclamationToken,
|
||||
};
|
||||
}))();
|
||||
|
||||
const BINARY_OPERATORS: Record<BinaryOperator, ts.BinaryOperator> = {
|
||||
const BINARY_OPERATORS: Record<BinaryOperator, ts.BinaryOperator> = /* @__PURE__ */ (() => ({
|
||||
'&&': ts.SyntaxKind.AmpersandAmpersandToken,
|
||||
'>': ts.SyntaxKind.GreaterThanToken,
|
||||
'>=': ts.SyntaxKind.GreaterThanEqualsToken,
|
||||
|
|
@ -61,13 +61,13 @@ const BINARY_OPERATORS: Record<BinaryOperator, ts.BinaryOperator> = {
|
|||
'+': ts.SyntaxKind.PlusToken,
|
||||
'??': ts.SyntaxKind.QuestionQuestionToken,
|
||||
'in': ts.SyntaxKind.InKeyword,
|
||||
};
|
||||
}))();
|
||||
|
||||
const VAR_TYPES: Record<VariableDeclarationType, ts.NodeFlags> = {
|
||||
const VAR_TYPES: Record<VariableDeclarationType, ts.NodeFlags> = /* @__PURE__ */ (() => ({
|
||||
'const': ts.NodeFlags.Const,
|
||||
'let': ts.NodeFlags.Let,
|
||||
'var': ts.NodeFlags.None,
|
||||
};
|
||||
}))();
|
||||
|
||||
/**
|
||||
* A TypeScript flavoured implementation of the AstFactory.
|
||||
|
|
|
|||
Loading…
Reference in a new issue