diff --git a/integration/dynamic-compiler/e2e/app.e2e-spec.ts b/integration/dynamic-compiler/e2e/app.e2e-spec.ts
new file mode 100644
index 0000000000..654e76298f
--- /dev/null
+++ b/integration/dynamic-compiler/e2e/app.e2e-spec.ts
@@ -0,0 +1,19 @@
+import { AppPage } from './app.po';
+
+describe('dynamic-compiler App', () => {
+ let page: AppPage;
+
+ beforeEach(() => {
+ page = new AppPage();
+ });
+
+ it('should display welcome message', () => {
+ page.navigateTo();
+ expect(page.getParagraphText()).toEqual('Hello world!');
+ });
+
+ it('should display lazy-loaded component', () => {
+ page.navigateTo();
+ expect(page.getLazyLoadedText()).toEqual('Lazy-loaded component!');
+ });
+});
diff --git a/integration/dynamic-compiler/e2e/app.po.ts b/integration/dynamic-compiler/e2e/app.po.ts
new file mode 100644
index 0000000000..af43732cc6
--- /dev/null
+++ b/integration/dynamic-compiler/e2e/app.po.ts
@@ -0,0 +1,16 @@
+import {browser, by, element, protractor} from 'protractor';
+
+export class AppPage {
+ navigateTo() {
+ return browser.get('/');
+ }
+
+ getParagraphText() {
+ return element(by.css('app-root h1')).getText();
+ }
+
+ getLazyLoadedText() {
+ const el = element(by.css('app-root lazy-component'));
+ return browser.wait(protractor.ExpectedConditions.presenceOf(el)).then(() => el.getText(), err => el.getText());
+ }
+}
diff --git a/integration/dynamic-compiler/e2e/browser.config.json b/integration/dynamic-compiler/e2e/browser.config.json
new file mode 100644
index 0000000000..44f23aa009
--- /dev/null
+++ b/integration/dynamic-compiler/e2e/browser.config.json
@@ -0,0 +1,15 @@
+{
+ "open": false,
+ "logLevel": "silent",
+ "port": 8080,
+ "server": {
+ "baseDir": ".",
+ "routes": {
+ "/dist": "dist",
+ "/node_modules": "node_modules"
+ },
+ "middleware": {
+ "0": null
+ }
+ }
+}
diff --git a/integration/dynamic-compiler/e2e/protractor.config.js b/integration/dynamic-compiler/e2e/protractor.config.js
new file mode 100644
index 0000000000..9b7d88e741
--- /dev/null
+++ b/integration/dynamic-compiler/e2e/protractor.config.js
@@ -0,0 +1,16 @@
+exports.config = {
+ specs: [
+ '../dist/e2e/*.e2e-spec.js'
+ ],
+ capabilities: {
+ browserName: 'chrome',
+ chromeOptions: {
+ args: ['--no-sandbox'],
+ binary: process.env.CHROME_BIN,
+ }
+ },
+ directConnect: true,
+ baseUrl: 'http://localhost:8080/',
+ framework: 'jasmine',
+ useAllAngular2AppRoots: true
+};
diff --git a/integration/dynamic-compiler/e2e/tsconfig.json b/integration/dynamic-compiler/e2e/tsconfig.json
new file mode 100644
index 0000000000..2badee6f7a
--- /dev/null
+++ b/integration/dynamic-compiler/e2e/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "outDir": "../dist/e2e",
+ "types": ["jasmine"],
+ "skipLibCheck": true
+ }
+}
diff --git a/integration/dynamic-compiler/index.html b/integration/dynamic-compiler/index.html
new file mode 100644
index 0000000000..6c291a4a5f
--- /dev/null
+++ b/integration/dynamic-compiler/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration/dynamic-compiler/package.json b/integration/dynamic-compiler/package.json
new file mode 100644
index 0000000000..59b2de6980
--- /dev/null
+++ b/integration/dynamic-compiler/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "dynamic-compiler",
+ "version": "0.0.0",
+ "main": "index.js",
+ "scripts": {
+ "build": "npm run clean && npm run ngc && npm run rollup && npm run rollup:lazy && npm run es5 && npm run es5:lazy",
+ "clean": "rm -rf dist",
+ "es5": "tsc --target es5 --skipLibCheck --allowJs dist/bundle.es2015.js --out dist/bundle.js",
+ "es5:lazy": "tsc --target es5 --skipLibCheck --allowJs dist/lazy.bundle.es2015.js --out dist/lazy.bundle.js",
+ "ngc": "ngc -p tsconfig.json",
+ "rollup": "rollup -f iife -c rollup.config.js -o dist/bundle.es2015.js",
+ "rollup:lazy": "rollup -f cjs -c rollup.lazy.config.js -o dist/lazy.bundle.es2015.js",
+ "postinstall": "webdriver-manager update --gecko false",
+ "preprotractor": "tsc -p e2e",
+ "protractor": "protractor e2e/protractor.config.js",
+ "serve": "lite-server -c e2e/browser.config.json",
+ "test": "npm run build && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first"
+ },
+ "license": "MIT",
+ "devDependencies": {
+ "@types/jasmine": "file:../../node_modules/@types/jasmine",
+ "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
+ "concurrently": "3.4.0",
+ "lite-server": "2.2.2",
+ "protractor": "file:../../node_modules/protractor",
+ "rollup": "file:../../node_modules/rollup",
+ "rollup-plugin-commonjs": "file:../../node_modules/rollup-plugin-commonjs",
+ "rollup-plugin-node-resolve": "file:../../node_modules/rollup-plugin-node-resolve",
+ "typescript": "file:../../node_modules/typescript"
+ },
+ "dependencies": {
+ "@angular/animations": "file:../../dist/packages-dist/animations",
+ "@angular/common": "file:../../dist/packages-dist/common",
+ "@angular/compiler": "file:../../dist/packages-dist/compiler",
+ "@angular/core": "file:../../dist/packages-dist/core",
+ "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
+ "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic",
+ "@angular/platform-server": "file:../../dist/packages-dist/platform-server",
+ "core-js": "file:../../node_modules/core-js",
+ "rxjs": "file:../../node_modules/rxjs",
+ "systemjs": "file:../../node_modules/systemjs",
+ "zone.js": "file:../../node_modules/zone.js"
+ }
+}
diff --git a/integration/dynamic-compiler/rollup.config.js b/integration/dynamic-compiler/rollup.config.js
new file mode 100644
index 0000000000..99a80d844a
--- /dev/null
+++ b/integration/dynamic-compiler/rollup.config.js
@@ -0,0 +1,17 @@
+import nodeResolve from 'rollup-plugin-node-resolve';
+import commonjs from 'rollup-plugin-commonjs';
+
+export default {
+ entry: 'dist/src/main.js',
+ sourceMap: true,
+ treeshake: true,
+ moduleName: 'main',
+ plugins: [
+ commonjs({
+ include: 'node_modules/**'
+ }),
+ nodeResolve({
+ jsnext: true, main: true, module: true
+ })
+ ]
+};
diff --git a/integration/dynamic-compiler/rollup.lazy.config.js b/integration/dynamic-compiler/rollup.lazy.config.js
new file mode 100644
index 0000000000..d44ea0dd83
--- /dev/null
+++ b/integration/dynamic-compiler/rollup.lazy.config.js
@@ -0,0 +1,19 @@
+import nodeResolve from 'rollup-plugin-node-resolve';
+import commonjs from 'rollup-plugin-commonjs';
+
+// a real app should make a common bundle for libraries instead of bundling them
+// in both the main module & the lazy module, but we don't care about size here
+export default {
+ entry: 'dist/src/lazy.module.js',
+ sourceMap: true,
+ treeshake: true,
+ moduleName: 'lazy',
+ plugins: [
+ commonjs({
+ include: 'node_modules/**'
+ }),
+ nodeResolve({
+ jsnext: true, main: true, module: true
+ })
+ ]
+};
diff --git a/integration/dynamic-compiler/src/app.component.ts b/integration/dynamic-compiler/src/app.component.ts
new file mode 100644
index 0000000000..e54316da9b
--- /dev/null
+++ b/integration/dynamic-compiler/src/app.component.ts
@@ -0,0 +1,27 @@
+import {AfterViewInit, Compiler, Component, ViewChild, ViewContainerRef} from '@angular/core';
+
+declare var System: any;
+
+@Component({
+ selector: 'app-root',
+ template: `
+ Hello world!
+
+ `,
+})
+export class AppComponent implements AfterViewInit {
+ @ViewChild('vc', {read: ViewContainerRef}) container: ViewContainerRef;
+
+ constructor(private compiler: Compiler) {
+ }
+
+ ngAfterViewInit() {
+ System.import('./dist/lazy.bundle.js').then((module: any) => {
+ this.compiler.compileModuleAndAllComponentsAsync(module.LazyModule)
+ .then((compiled) => {
+ const factory = compiled.componentFactories[0];
+ this.container.createComponent(factory);
+ });
+ });
+ }
+}
diff --git a/integration/dynamic-compiler/src/app.module.ts b/integration/dynamic-compiler/src/app.module.ts
new file mode 100644
index 0000000000..0963654c95
--- /dev/null
+++ b/integration/dynamic-compiler/src/app.module.ts
@@ -0,0 +1,22 @@
+import {Compiler, COMPILER_OPTIONS, CompilerFactory, NgModule} from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import {JitCompilerFactory} from '@angular/platform-browser-dynamic';
+
+import { AppComponent } from './app.component';
+
+export function createCompiler(compilerFactory: CompilerFactory) {
+ return compilerFactory.createCompiler();
+}
+
+@NgModule({
+ imports: [BrowserModule],
+ bootstrap: [AppComponent],
+ declarations: [AppComponent],
+ providers: [
+ {provide: COMPILER_OPTIONS, useValue: {}, multi: true},
+ {provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
+ {provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory]}
+ ]
+})
+export class AppModule {}
+
diff --git a/integration/dynamic-compiler/src/lazy.module.ts b/integration/dynamic-compiler/src/lazy.module.ts
new file mode 100644
index 0000000000..876cf05f4a
--- /dev/null
+++ b/integration/dynamic-compiler/src/lazy.module.ts
@@ -0,0 +1,17 @@
+import {NgModule} from "@angular/core";
+import {Component} from '@angular/core';
+
+@Component({
+ selector: 'lazy-component',
+ template: 'Lazy-loaded component!'
+})
+export class LazyComponent {
+ constructor() {
+ }
+}
+
+@NgModule({
+ declarations: [LazyComponent]
+})
+export class LazyModule {
+}
diff --git a/integration/dynamic-compiler/src/main.ts b/integration/dynamic-compiler/src/main.ts
new file mode 100644
index 0000000000..7c5e5943c3
--- /dev/null
+++ b/integration/dynamic-compiler/src/main.ts
@@ -0,0 +1,8 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowser } from '@angular/platform-browser';
+
+import { AppModuleNgFactory } from './app.module.ngfactory';
+
+enableProdMode();
+
+platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
diff --git a/integration/dynamic-compiler/tsconfig.json b/integration/dynamic-compiler/tsconfig.json
new file mode 100644
index 0000000000..4adfea7714
--- /dev/null
+++ b/integration/dynamic-compiler/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "es2015",
+ "module": "es2015",
+ "moduleResolution": "node",
+ "declaration": false,
+ "removeComments": true,
+ "noLib": false,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "lib": ["es6", "es2015", "dom"],
+ "sourceMap": true,
+ "pretty": true,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitUseStrict": false,
+ "noFallthroughCasesInSwitch": true,
+ "outDir": "./dist",
+ "types": [
+ ]
+ },
+ "files": [
+ "src/main.ts",
+ "src/lazy.module.ts"
+ ]
+}
diff --git a/packages/platform-browser-dynamic/src/compiler_factory.ts b/packages/platform-browser-dynamic/src/compiler_factory.ts
index f19467a765..2160a147cf 100644
--- a/packages/platform-browser-dynamic/src/compiler_factory.ts
+++ b/packages/platform-browser-dynamic/src/compiler_factory.ts
@@ -150,8 +150,13 @@ export const COMPILER_PROVIDERS = [
{ provide: NgModuleResolver, deps: [CompileReflector]},
];
+/**
+ * @experimental
+ */
export class JitCompilerFactory implements CompilerFactory {
private _defaultOptions: CompilerOptions[];
+
+ /* @internal */
constructor(defaultOptions: CompilerOptions[]) {
const compilerOptions: CompilerOptions = {
useJit: true,
diff --git a/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts b/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts
index a97968ce93..654164134a 100644
--- a/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts
+++ b/packages/platform-browser-dynamic/src/platform-browser-dynamic.ts
@@ -15,6 +15,7 @@ import {CachedResourceLoader} from './resource_loader/resource_loader_cache';
export * from './private_export';
export {VERSION} from './version';
+export {JitCompilerFactory} from './compiler_factory';
/**
* @experimental
diff --git a/tools/public_api_guard/platform-browser-dynamic/platform-browser-dynamic.d.ts b/tools/public_api_guard/platform-browser-dynamic/platform-browser-dynamic.d.ts
index 414918714b..1b02d8e0e5 100644
--- a/tools/public_api_guard/platform-browser-dynamic/platform-browser-dynamic.d.ts
+++ b/tools/public_api_guard/platform-browser-dynamic/platform-browser-dynamic.d.ts
@@ -1,3 +1,8 @@
+/** @experimental */
+export declare class JitCompilerFactory implements CompilerFactory {
+ createCompiler(options?: CompilerOptions[]): Compiler;
+}
+
/** @stable */
export declare const platformBrowserDynamic: (extraProviders?: StaticProvider[] | undefined) => PlatformRef;