diff --git a/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts b/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts index 49d0633f7a21..86449d8c9d0a 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/tests/setup.ts @@ -20,7 +20,7 @@ export const KARMA_BUILDER_INFO = Object.freeze({ * Also disables progress reporting to minimize logging output. */ export const BASE_OPTIONS = Object.freeze({ - polyfills: ['zone.js', 'zone.js/testing', '@angular/localize/init'], + polyfills: ['zone.js', 'zone.js/testing'], tsConfig: 'src/tsconfig.spec.json', karmaConfig: 'karma.conf.js', browsers: 'ChromeHeadlessCI', 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 6b7c85c021f3..8e98c191e91b 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts @@ -96,14 +96,33 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise t === '@angular/localize' || t === localizePackageInitEntryPoint, + ); + + if (hasLocalizeType) { + entryPoints['main'] = [localizePackageInitEntryPoint]; + } + if (buildOptions.main) { const mainPath = path.resolve(root, buildOptions.main); - entryPoints['main'] = [mainPath]; + if (Array.isArray(entryPoints['main'])) { + entryPoints['main'].push(mainPath); + } else { + entryPoints['main'] = [mainPath]; + } } if (isPlatformServer) { // Fixes Critical dependency: the request of a dependency is an expression extraPlugins.push(new ContextReplacementPlugin(/@?hapi|express[\\/]/)); + + if (Array.isArray(entryPoints['main'])) { + // This import must come before any imports (direct or transitive) that rely on DOM built-ins being + // available, such as `@angular/elements`. + entryPoints['main'].unshift('@angular/platform-server/init'); + } } if (polyfills?.length) { diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/angular.json b/packages/angular_devkit/build_angular/test/hello-world-app/angular.json index a07d22ad3216..ffb889dc2573 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/angular.json +++ b/packages/angular_devkit/build_angular/test/hello-world-app/angular.json @@ -111,7 +111,7 @@ "test": { "builder": "@angular-devkit/build-angular:karma", "options": { - "polyfills": ["zone.js", "zone.js/testing", "@angular/localize/init"], + "polyfills": ["zone.js", "zone.js/testing"], "tsConfig": "src/tsconfig.spec.json", "karmaConfig": "karma.conf.js", diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/src/main.server.ts b/packages/angular_devkit/build_angular/test/hello-world-app/src/main.server.ts index 11c93d4085fd..4448f40d8a49 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/src/main.server.ts +++ b/packages/angular_devkit/build_angular/test/hello-world-app/src/main.server.ts @@ -6,6 +6,4 @@ * found in the LICENSE file at https://angular.io/license */ -import '@angular/localize/init'; - export { AppServerModule } from './app/app.server.module'; diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/src/polyfills.ts b/packages/angular_devkit/build_angular/test/hello-world-app/src/polyfills.ts index eb6530df1887..f530c61c1167 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/src/polyfills.ts +++ b/packages/angular_devkit/build_angular/test/hello-world-app/src/polyfills.ts @@ -36,9 +36,6 @@ */ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. - -import '@angular/localize/init'; - /** * By default, zone.js will patch all possible macroTask and DomEvents * user can disable parts of macroTask/DomEvents patch by setting following flags diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.app.json b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.app.json index f761e8b2c4fc..0fd75806850e 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.app.json +++ b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.app.json @@ -2,7 +2,7 @@ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/app", - "types": [] + "types": ["@angular/localize/init"] }, "files": [ "main.ts", diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.server.json b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.server.json index 0b0bc22e90b6..9599811a5803 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.server.json +++ b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.server.json @@ -4,7 +4,7 @@ "outDir": "../dist-server", "target": "es2016", "baseUrl": "./", - "types": [] + "types": ["@angular/localize/init"] }, "files": [ "main.server.ts" diff --git a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.spec.json b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.spec.json index 7ece4f757a0d..13749f5c0c0c 100644 --- a/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.spec.json +++ b/packages/angular_devkit/build_angular/test/hello-world-app/src/tsconfig.spec.json @@ -3,7 +3,8 @@ "compilerOptions": { "outDir": "../out-tsc/spec", "types": [ - "jasmine" + "jasmine", + "@angular/localize/init" ] }, "files": [ diff --git a/packages/schematics/angular/universal/files/root/tsconfig.server.json.template b/packages/schematics/angular/universal/files/root/tsconfig.server.json.template index f43b41cae4ad..20751626f84d 100644 --- a/packages/schematics/angular/universal/files/root/tsconfig.server.json.template +++ b/packages/schematics/angular/universal/files/root/tsconfig.server.json.template @@ -5,7 +5,8 @@ "outDir": "<%= relativePathToWorkspaceRoot %>/out-tsc/server", "target": "es2019", "types": [ - "node" + "node"<% if (hasLocalizePackage) { %>, + "@angular/localize/init"<% } %> ] }, "files": [ diff --git a/packages/schematics/angular/universal/files/src/__main@stripTsExtension__.ts.template b/packages/schematics/angular/universal/files/src/__main@stripTsExtension__.ts.template index a820cfb07611..5ccc29c792b0 100644 --- a/packages/schematics/angular/universal/files/src/__main@stripTsExtension__.ts.template +++ b/packages/schematics/angular/universal/files/src/__main@stripTsExtension__.ts.template @@ -1,16 +1,2 @@ -/*************************************************************************************************** - * Initialize the server environment - for example, adding DOM built-in types to the global scope. - * - * NOTE: - * This import must come before any imports (direct or transitive) that rely on DOM built-ins being - * available, such as `@angular/elements`. - */ -import '@angular/platform-server/init'; -<% if (hasLocalizePackage) { %>/*************************************************************************************************** - * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. - */ -import '@angular/localize/init'; - -<% } %> export { <%= rootModuleClassName %> } from './app/<%= stripTsExtension(rootModuleFileName) %>'; diff --git a/packages/schematics/angular/universal/index.ts b/packages/schematics/angular/universal/index.ts index 2eae32dcd947..471ca3b61126 100644 --- a/packages/schematics/angular/universal/index.ts +++ b/packages/schematics/angular/universal/index.ts @@ -258,7 +258,6 @@ export default function (options: UniversalOptions): Rule { ...strings, ...options, stripTsExtension: (s: string) => s.replace(/\.ts$/, ''), - hasLocalizePackage: !!getPackageJsonDependency(host, '@angular/localize'), }), move(join(normalize(clientProject.root), 'src')), ]); @@ -273,6 +272,7 @@ export default function (options: UniversalOptions): Rule { ...options, stripTsExtension: (s: string) => s.replace(/\.ts$/, ''), tsConfigExtends, + hasLocalizePackage: !!getPackageJsonDependency(host, '@angular/localize'), relativePathToWorkspaceRoot: relativePathToWorkspaceRoot(tsConfigDirectory), }), move(tsConfigDirectory), diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts index 85a8b5bfa658..56efc3ae9ee4 100644 --- a/packages/schematics/angular/universal/index_spec.ts +++ b/packages/schematics/angular/universal/index_spec.ts @@ -9,6 +9,7 @@ import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { parse as parseJson } from 'jsonc-parser'; import { Schema as ApplicationOptions, Style } from '../application/schema'; +import { CompilerOptions } from '../third_party/github.com/Microsoft/TypeScript/lib/typescript'; import { NodeDependencyType, addPackageJsonDependency } from '../utility/dependencies'; import { Schema as WorkspaceOptions } from '../workspace/schema'; import { Schema as UniversalOptions } from './schema'; @@ -225,36 +226,29 @@ describe('Universal Schematic', () => { expect(tree.exists(filePath)).toEqual(true); }); - it(`should add import to '@angular/platform-server/init' in main file`, async () => { + it(`should not add import to '@angular/localize' as type in 'tsconfig.server.json' when it's not a depedency`, async () => { const tree = await schematicRunner .runSchematicAsync('universal', defaultOptions, appTree) .toPromise(); - const filePath = '/projects/bar/src/main.server.ts'; - const contents = tree.readContent(filePath); - expect(contents).toContain("import '@angular/platform-server/init'"); + const { compilerOptions } = tree.readJson('/projects/bar/tsconfig.server.json') as { + compilerOptions: CompilerOptions; + }; + expect(compilerOptions.types).not.toContain('@angular/localize/init'); }); - it(`should not add import to '@angular/localize' in main file when it's not a depedency`, async () => { - const tree = await schematicRunner - .runSchematicAsync('universal', defaultOptions, appTree) - .toPromise(); - const filePath = '/projects/bar/src/main.server.ts'; - const contents = tree.readContent(filePath); - expect(contents).not.toContain('@angular/localize'); - }); - - it(`should add import to '@angular/localize' in main file when it's a depedency`, async () => { + it(`should add import to '@angular/localize' as type in 'tsconfig.server.json' when it's not a depedency`, async () => { addPackageJsonDependency(appTree, { name: '@angular/localize', type: NodeDependencyType.Default, version: 'latest', }); - const tree = await schematicRunner .runSchematicAsync('universal', defaultOptions, appTree) .toPromise(); - const filePath = '/projects/bar/src/main.server.ts'; - const contents = tree.readContent(filePath); - expect(contents).toContain('@angular/localize/init'); + + const { compilerOptions } = tree.readJson('/projects/bar/tsconfig.server.json') as { + compilerOptions: CompilerOptions; + }; + expect(compilerOptions.types).toContain('@angular/localize/init'); }); });