diff --git a/aio/tools/transforms/angular-api-package/index.js b/aio/tools/transforms/angular-api-package/index.js
index af48da87f0..555ecd0645 100644
--- a/aio/tools/transforms/angular-api-package/index.js
+++ b/aio/tools/transforms/angular-api-package/index.js
@@ -107,6 +107,7 @@ module.exports =
'platform-browser-dynamic/index.ts',
'platform-browser-dynamic/testing/index.ts',
'platform-server/index.ts',
+ 'platform-server/init/index.ts',
'platform-server/testing/index.ts',
'platform-webworker/index.ts',
'platform-webworker-dynamic/index.ts',
diff --git a/aio/tools/transforms/authors-package/api-package.js b/aio/tools/transforms/authors-package/api-package.js
index cc23500436..a7d42bd103 100644
--- a/aio/tools/transforms/authors-package/api-package.js
+++ b/aio/tools/transforms/authors-package/api-package.js
@@ -18,7 +18,7 @@ const packageMap = {
forms: ['forms/index.ts'],
'platform-browser': ['platform-browser/index.ts', 'platform-browser/animations/index.ts', 'platform-browser/testing/index.ts'],
'platform-browser-dynamic': ['platform-browser-dynamic/index.ts', 'platform-browser-dynamic/testing/index.ts'],
- 'platform-server': ['platform-server/index.ts', 'platform-server/testing/index.ts'],
+ 'platform-server': ['platform-server/index.ts', 'platform-server/init/index.ts', 'platform-server/testing/index.ts'],
router: ['router/index.ts', 'router/testing/index.ts', 'router/upgrade/index.ts'],
'service-worker': ['service-worker/index.ts'],
upgrade: ['upgrade/index.ts', 'upgrade/static/index.ts', 'upgrade/static/testing/index.ts']
diff --git a/goldens/public-api/platform-server/init/init.d.ts b/goldens/public-api/platform-server/init/init.d.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/integration/cli-elements-universal/src/main.server.ts b/integration/cli-elements-universal/src/main.server.ts
index 10150a7181..cb15695aa9 100644
--- a/integration/cli-elements-universal/src/main.server.ts
+++ b/integration/cli-elements-universal/src/main.server.ts
@@ -1,3 +1,4 @@
+import '@angular/platform-server/init';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
diff --git a/integration/typings_test_ts40/include-all.ts b/integration/typings_test_ts40/include-all.ts
index 7bf19f646c..86b57f2789 100644
--- a/integration/typings_test_ts40/include-all.ts
+++ b/integration/typings_test_ts40/include-all.ts
@@ -27,6 +27,7 @@ import * as platformBrowserDynamicTesting from '@angular/platform-browser-dynami
import * as platformBrowserAnimations from '@angular/platform-browser/animations';
import * as platformBrowserTesting from '@angular/platform-browser/testing';
import * as platformServer from '@angular/platform-server';
+import * as platformServerInit from '@angular/platform-server/init';
import * as platformServerTesting from '@angular/platform-server/testing';
import * as router from '@angular/router';
import * as routerTesting from '@angular/router/testing';
@@ -56,6 +57,7 @@ export default {
platformBrowserDynamicTesting,
platformBrowserAnimations,
platformServer,
+ platformServerInit,
platformServerTesting,
router,
routerTesting,
diff --git a/integration/typings_test_ts41/include-all.ts b/integration/typings_test_ts41/include-all.ts
index 7bf19f646c..86b57f2789 100644
--- a/integration/typings_test_ts41/include-all.ts
+++ b/integration/typings_test_ts41/include-all.ts
@@ -27,6 +27,7 @@ import * as platformBrowserDynamicTesting from '@angular/platform-browser-dynami
import * as platformBrowserAnimations from '@angular/platform-browser/animations';
import * as platformBrowserTesting from '@angular/platform-browser/testing';
import * as platformServer from '@angular/platform-server';
+import * as platformServerInit from '@angular/platform-server/init';
import * as platformServerTesting from '@angular/platform-server/testing';
import * as router from '@angular/router';
import * as routerTesting from '@angular/router/testing';
@@ -56,6 +57,7 @@ export default {
platformBrowserDynamicTesting,
platformBrowserAnimations,
platformServer,
+ platformServerInit,
platformServerTesting,
router,
routerTesting,
diff --git a/packages/bazel/src/ng_package/ng_package.bzl b/packages/bazel/src/ng_package/ng_package.bzl
index f0a07a848e..a73c066640 100644
--- a/packages/bazel/src/ng_package/ng_package.bzl
+++ b/packages/bazel/src/ng_package/ng_package.bzl
@@ -105,6 +105,7 @@ WELL_KNOWN_GLOBALS = {p: _global_name(p) for p in [
"@angular/forms",
"@angular/core/testing",
"@angular/core",
+ "@angular/platform-server/init",
"@angular/platform-server/testing",
"@angular/platform-server",
"@angular/common/testing",
diff --git a/packages/platform-server/BUILD.bazel b/packages/platform-server/BUILD.bazel
index 85f6bbb88f..eade038378 100644
--- a/packages/platform-server/BUILD.bazel
+++ b/packages/platform-server/BUILD.bazel
@@ -30,6 +30,7 @@ ng_package(
name = "npm_package",
srcs = [
"package.json",
+ "//packages/platform-server/init:package.json",
"//packages/platform-server/testing:package.json",
],
entry_point = ":index.ts",
@@ -44,6 +45,7 @@ ng_package(
],
deps = [
":platform-server",
+ "//packages/platform-server/init",
"//packages/platform-server/testing",
],
)
diff --git a/packages/platform-server/init/BUILD.bazel b/packages/platform-server/init/BUILD.bazel
new file mode 100644
index 0000000000..a3dcc6c667
--- /dev/null
+++ b/packages/platform-server/init/BUILD.bazel
@@ -0,0 +1,18 @@
+load("//tools:defaults.bzl", "ng_module")
+
+package(default_visibility = ["//visibility:public"])
+
+exports_files(["package.json"])
+
+ng_module(
+ name = "init",
+ srcs = glob(
+ [
+ "*.ts",
+ "src/**/*.ts",
+ ],
+ ),
+ deps = [
+ "//packages/platform-server",
+ ],
+)
diff --git a/packages/platform-server/init/PACKAGE.md b/packages/platform-server/init/PACKAGE.md
new file mode 100644
index 0000000000..e503f53f09
--- /dev/null
+++ b/packages/platform-server/init/PACKAGE.md
@@ -0,0 +1,15 @@
+Initializes the server environment for rendering an Angular application.
+
+For example, it provides shims (such as DOM globals) for the server environment.
+
+The initialization happens as a [side effect of importing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#import_a_module_for_its_side_effects_only) the entry point (i.e. there are no specific exports):
+
+```ts
+import '@angular/platform-server/init';
+```
+
+
+
+ The import must come before any imports (direct or transitive) that rely on DOM built-ins being available.
+
+
diff --git a/packages/platform-server/init/index.ts b/packages/platform-server/init/index.ts
new file mode 100644
index 0000000000..1f364dbd88
--- /dev/null
+++ b/packages/platform-server/init/index.ts
@@ -0,0 +1,14 @@
+/**
+ * @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
+ */
+
+// This file is not used to build this module. It is only used during editing
+// by the TypeScript language service and during build for verifcation. `ngc`
+// replaces this file with production index.ts when it rewrites private symbol
+// names.
+
+export * from './public_api';
diff --git a/packages/platform-server/init/package.json b/packages/platform-server/init/package.json
new file mode 100644
index 0000000000..55674a97d9
--- /dev/null
+++ b/packages/platform-server/init/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "@angular/platform-server/init",
+ "sideEffects": true
+}
diff --git a/packages/platform-server/init/public_api.ts b/packages/platform-server/init/public_api.ts
new file mode 100644
index 0000000000..51cfd93d5a
--- /dev/null
+++ b/packages/platform-server/init/public_api.ts
@@ -0,0 +1,14 @@
+/**
+ * @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
+ */
+
+/**
+ * @module
+ * @description
+ * Entry point for all public APIs of this package.
+ */
+export * from './src/init';
diff --git a/packages/platform-server/init/src/init.ts b/packages/platform-server/init/src/init.ts
new file mode 100644
index 0000000000..9005b79073
--- /dev/null
+++ b/packages/platform-server/init/src/init.ts
@@ -0,0 +1,17 @@
+/**
+ * @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
+ */
+
+/**
+ * @module
+ * @description
+ * Entry point for all initialization APIs of the platform-server package.
+ */
+
+import {applyShims} from './shims';
+
+applyShims();
diff --git a/packages/platform-server/init/src/shims.ts b/packages/platform-server/init/src/shims.ts
new file mode 100644
index 0000000000..3440e360ac
--- /dev/null
+++ b/packages/platform-server/init/src/shims.ts
@@ -0,0 +1,16 @@
+/**
+ * @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 {setDomTypes} from '../../src/domino_adapter';
+
+/**
+ * Apply the necessary shims to make DOM globals (such as `Element`, `HTMLElement`, etc.) available
+ * on the environment.
+ */
+export function applyShims(): void {
+ setDomTypes();
+}
diff --git a/packages/platform-server/init/test/BUILD.bazel b/packages/platform-server/init/test/BUILD.bazel
new file mode 100644
index 0000000000..aeee41bd84
--- /dev/null
+++ b/packages/platform-server/init/test/BUILD.bazel
@@ -0,0 +1,25 @@
+load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
+load("//tools/circular_dependency_test:index.bzl", "circular_dependency_test")
+
+circular_dependency_test(
+ name = "circular_deps_test",
+ entry_point = "angular/packages/platform-server/init/index.js",
+ deps = ["//packages/platform-server/init"],
+)
+
+ts_library(
+ name = "test_lib",
+ testonly = True,
+ srcs = glob(["**/*.ts"]),
+ deps = [
+ "//packages/platform-server/init",
+ ],
+)
+
+jasmine_node_test(
+ name = "test",
+ bootstrap = ["//tools/testing:node_no_angular_es5"],
+ deps = [
+ ":test_lib",
+ ],
+)
diff --git a/packages/platform-server/init/test/shims_spec.ts b/packages/platform-server/init/test/shims_spec.ts
new file mode 100644
index 0000000000..3bc8b90d22
--- /dev/null
+++ b/packages/platform-server/init/test/shims_spec.ts
@@ -0,0 +1,41 @@
+/**
+ * @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 {applyShims} from '../src/shims';
+
+describe('applyShims()', () => {
+ if (isBrowser) return; // NODE only
+
+ const domino = require('domino');
+ const globalClone = {...global};
+
+ afterEach(() => {
+ // Un-patch `global`.
+ const currentProps = Object.keys(global) as (keyof NodeJS.Global)[];
+ for (const prop of currentProps) {
+ if (globalClone.hasOwnProperty(prop)) {
+ (global as any)[prop] = globalClone[prop];
+ } else {
+ delete (global as any)[prop];
+ }
+ }
+ });
+
+ it('should load `domino.impl` onto `global`', () => {
+ expect(global).not.toEqual(jasmine.objectContaining(domino.impl));
+
+ applyShims();
+ expect(global).toEqual(jasmine.objectContaining(domino.impl));
+ });
+
+ it('should define `KeyboardEvent` on `global`', () => {
+ expect((global as any).KeyboardEvent).not.toBe((domino.impl as any).Event);
+
+ applyShims();
+ expect((global as any).KeyboardEvent).toBe((domino.impl as any).Event);
+ });
+});
diff --git a/packages/platform-server/package.json b/packages/platform-server/package.json
index 6803eae500..e6e0eda4b0 100644
--- a/packages/platform-server/package.json
+++ b/packages/platform-server/package.json
@@ -25,7 +25,15 @@
"ng-update": {
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
},
- "sideEffects": false,
+ "sideEffects": [
+ "./bundles/platform-server-init.umd.js",
+ "./bundles/platform-server-init.umd.min.js",
+ "./esm2015/init/src/init.js",
+ "./fesm2015/init.js",
+ "./__ivy_ngcc__/bundles/platform-server-init.umd.js",
+ "./__ivy_ngcc__/esm2015/init/src/init.js",
+ "./__ivy_ngcc__/fesm2015/init.js"
+ ],
"engines": {
"node": ">=8.0"
},
diff --git a/packages/platform-server/src/domino_adapter.ts b/packages/platform-server/src/domino_adapter.ts
index 232c644e5a..54256a2c19 100644
--- a/packages/platform-server/src/domino_adapter.ts
+++ b/packages/platform-server/src/domino_adapter.ts
@@ -14,8 +14,8 @@ function _notImplemented(methodName: string) {
return new Error('This method is not implemented in DominoAdapter: ' + methodName);
}
-function setDomTypes() {
- // Make all Domino types available as types in the global env.
+export function setDomTypes() {
+ // Make all Domino types available in the global env.
Object.assign(global, domino.impl);
(global as any)['KeyboardEvent'] = domino.impl.Event;
}
diff --git a/test-main.js b/test-main.js
index 7cc5f3323d..b935f6bf39 100644
--- a/test-main.js
+++ b/test-main.js
@@ -27,7 +27,7 @@ System.config({
'domino': 'dist/all/@angular/empty.js',
'url': 'dist/all/@angular/empty.js',
'xhr2': 'dist/all/@angular/empty.js',
- '@angular/platform-server/src/domino_adapter': 'dist/all/empty.js',
+ '@angular/platform-server/src/domino_adapter': 'dist/all/@angular/empty.js',
'angular-in-memory-web-api': 'dist/all/@angular/misc/angular-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
},
@@ -64,6 +64,7 @@ System.config({
'@angular/platform-browser': {main: 'index.js', defaultExtension: 'js'},
'@angular/platform-browser-dynamic/testing': {main: 'index.js', defaultExtension: 'js'},
'@angular/platform-browser-dynamic': {main: 'index.js', defaultExtension: 'js'},
+ '@angular/platform-server/init': {main: 'index.js', defaultExtension: 'js'},
'@angular/platform-server/testing': {main: 'index.js', defaultExtension: 'js'},
'@angular/platform-server': {main: 'index.js', defaultExtension: 'js'},
'@angular/private/testing': {main: 'index.js', defaultExtension: 'js'},