From 5c73f079f439165012fb95419a8ce803be4ea803 Mon Sep 17 00:00:00 2001
From: alexpods
Date: Tue, 2 Feb 2016 18:59:39 +0300
Subject: [PATCH] Global refactoring. Added support for serveral angular2
application.
---
constants.js | 40 +--
package.json | 2 +
src/.utils/run_browser.ts | 15 ++
src/.utils/run_worker_app.ts | 17 ++
src/.utils/run_worker_ui.ts | 20 ++
src/.utils/serve.ts | 154 +++++++++++
src/admin/app.ts | 7 +
src/admin/boot_browser.ts | 12 +
src/{server/ng.html => admin/index.html} | 1 -
src/admin/index.js | 24 ++
src/{server => }/app.ts | 19 +-
src/app/home.spec.ts | 54 ----
src/boot_browser.ts | 23 --
src/boot_worker.ts | 52 ----
src/boot_worker_app.ts | 34 ---
src/{app => main}/app.ts | 0
src/main/boot_browser.ts | 12 +
src/main/boot_server.ts | 13 +
src/main/boot_worker_app.ts | 22 ++
src/main/boot_worker_ui.ts | 15 ++
src/{app => main}/greeter.ts | 0
src/{app => main}/home.css | 0
src/{app => main}/home.html | 0
src/{app => main}/home.ts | 4 +-
src/main/index.html | 20 ++
src/main/index.js | 26 ++
src/{app => main}/workers.ts | 0
src/server/ng.ts | 64 -----
tools/build.js | 17 +-
tools/dev.js | 118 ++++-----
tools/prod.js | 16 +-
tsconfig.json | 9 +-
typings.d.ts | 54 ++--
webpack.config.js | 319 +++++++++++++----------
34 files changed, 677 insertions(+), 506 deletions(-)
create mode 100644 src/.utils/run_browser.ts
create mode 100644 src/.utils/run_worker_app.ts
create mode 100644 src/.utils/run_worker_ui.ts
create mode 100644 src/.utils/serve.ts
create mode 100644 src/admin/app.ts
create mode 100644 src/admin/boot_browser.ts
rename src/{server/ng.html => admin/index.html} (64%)
create mode 100644 src/admin/index.js
rename src/{server => }/app.ts (67%)
delete mode 100644 src/app/home.spec.ts
delete mode 100644 src/boot_browser.ts
delete mode 100644 src/boot_worker.ts
delete mode 100644 src/boot_worker_app.ts
rename src/{app => main}/app.ts (100%)
create mode 100644 src/main/boot_browser.ts
create mode 100644 src/main/boot_server.ts
create mode 100644 src/main/boot_worker_app.ts
create mode 100644 src/main/boot_worker_ui.ts
rename src/{app => main}/greeter.ts (100%)
rename src/{app => main}/home.css (100%)
rename src/{app => main}/home.html (100%)
rename src/{app => main}/home.ts (93%)
create mode 100644 src/main/index.html
create mode 100644 src/main/index.js
rename src/{app => main}/workers.ts (100%)
delete mode 100644 src/server/ng.ts
diff --git a/constants.js b/constants.js
index 7e94860..6af91b0 100644
--- a/constants.js
+++ b/constants.js
@@ -1,32 +1,34 @@
const fs = require('fs');
const path = require('path');
-exports.ROOT_DIR = path.resolve(__dirname);
-exports.SRC_DIR = path.resolve(exports.ROOT_DIR, 'src');
-exports.DIST_DIR = path.resolve(exports.ROOT_DIR, 'dist');
-exports.PUBLIC_DIR = path.resolve(exports.DIST_DIR, 'public');
-exports.PRIVATE_DIR = path.resolve(exports.DIST_DIR, 'private');
-exports.SERVER_DIR = path.resolve(exports.SRC_DIR, 'server');
+exports.ROOT_DIR = path.resolve(__dirname);
+exports.SRC_DIR = path.resolve(exports.ROOT_DIR, 'src');
+exports.DIST_DIR = path.resolve(exports.ROOT_DIR, 'dist');
+exports.PUBLIC_DIR = path.resolve(exports.DIST_DIR, 'public');
+exports.PRIVATE_DIR = path.resolve(exports.DIST_DIR, 'private');
+exports.MANIFESTS_DIR = path.resolve(exports.DIST_DIR, 'manifests');
+exports.SERVER_DIR = path.resolve(exports.SRC_DIR, 'server');
exports.HOST = process.env.HOST || 'localhost';
exports.PORT = +process.env.PORT || 3000;
-exports.HAS_SS = 'NG2_SS' in process.env ? process.env.NG2_SS === 'true' : true;
-exports.HAS_WW = 'NG2_WW' in process.env ? process.env.NG2_WW === 'true' : true;
+exports.SS = 'NG2_SS' in process.env ? process.env.NG2_SS === 'true' : true;
+exports.WW = 'NG2_WW' in process.env ? process.env.NG2_WW === 'true' : true;
-exports.VENDOR_NAME = 'vendor';
-exports.SERVER_NAME = 'server';
-exports.BROWSER_NAME = 'browser';
-exports.WORKER_NAME = 'worker';
-exports.WORKER_APP_NAME = 'worker_app';
+exports.APPS = [
+ { name: 'admin', path: path.resolve(exports.SRC_DIR, 'admin/index.js'), urlPrefix: '/admin' },
+ { name: 'main', path: path.resolve(exports.SRC_DIR, 'main/index.js'), urlPrefix: '/' }
+];
-exports.SERVER_SOURCE_PATH = path.resolve(exports.SRC_DIR, 'server/app.ts');
-exports.BROWSER_SOURCE_PATH = path.resolve(exports.SRC_DIR, 'boot_browser.ts');
-exports.WORKER_SOURCE_PATH = path.resolve(exports.SRC_DIR, 'boot_worker.ts');
-exports.WORKER_APP_SOURCE_PATH = path.resolve(exports.SRC_DIR, 'boot_worker_app.ts');
+exports.APPS_SERVER_BUNDLE_NAME = 'server';
+exports.APPS_BROWSER_BUNDLE_NAME = 'browser';
+exports.APPS_WORKER_UI_BUNDLE_NAME = 'worker_ui';
+exports.APPS_WORKER_APP_BUNDLE_NAME = 'worker_app';
-exports.VENDOR_DLL_MANIFEST_FILE = 'vendor-manifest.json';
-exports.VENDOR_DLL_MANIFEST_PATH = path.resolve(exports.PUBLIC_DIR, exports.VENDOR_DLL_MANIFEST_FILE);
+exports.VENDOR_BUNDLE_NAME = 'vendor';
+
+exports.MASTER_APP_BUNDLE_NAME = 'app';
+exports.MASTER_APP_SOURCE_PATH = path.resolve(exports.SRC_DIR, 'app.ts');
exports.PREBOOT = {
appRoot: 'app',
diff --git a/package.json b/package.json
index c2e1f43..0a9a242 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"prod": "node tools/prod.js",
"prebuild": "npm run clean:dist",
"build": "node tools/build.js",
+ "prebuild:watch": "npm run clean:dist",
"build:watch": "node tools/build.js --watch",
"lint": "node tools/lint.js",
"lint:watch": "node tools/lint.js --watch",
@@ -47,6 +48,7 @@
"dependencies": {
"angular2": "2.0.0-beta.3",
"angular2-universal-preview": "0.50.0",
+ "basic-auth-connect": "^1.0.0",
"css": "^2.2.1",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
diff --git a/src/.utils/run_browser.ts b/src/.utils/run_browser.ts
new file mode 100644
index 0000000..40daf28
--- /dev/null
+++ b/src/.utils/run_browser.ts
@@ -0,0 +1,15 @@
+import { Router } from 'angular2/router';
+
+document.addEventListener('DOMContentLoaded', function onDOMContentLoaded() {
+ const providers = [];
+
+ window[__APPS_BROWSER_BUNDLE_NAME__].main(providers).then(function(compRef) {
+ const injector = compRef.injector;
+ const router: Router = injector.getOptional(Router);
+
+ return Promise.resolve()
+ .then(() => router && ( router)._currentNavigation)
+ .then(() => new Promise(function(resolve) { setTimeout(resolve) }))
+ .then(() => document.dispatchEvent(new Event('BootstrapComplete')))
+ });
+});
\ No newline at end of file
diff --git a/src/.utils/run_worker_app.ts b/src/.utils/run_worker_app.ts
new file mode 100644
index 0000000..102adcf
--- /dev/null
+++ b/src/.utils/run_worker_app.ts
@@ -0,0 +1,17 @@
+import { Router } from 'angular2/router';
+
+const global = new Function('return this')();
+
+setTimeout(function() {
+ const providers = [];
+
+ global[__APPS_WORKER_APP_BUNDLE_NAME__].main(providers).then(function(compRef) {
+ const injector = compRef.injector;
+ const router: Router = injector.getOptional(Router);
+
+ return Promise.resolve()
+ .then(() => router && ( router)._currentNavigation)
+ .then(() => new Promise(function(resolve) { setTimeout(resolve) }))
+ .then(() => postMessage('APP_READY', undefined))
+ });
+}, 100);
diff --git a/src/.utils/run_worker_ui.ts b/src/.utils/run_worker_ui.ts
new file mode 100644
index 0000000..5616025
--- /dev/null
+++ b/src/.utils/run_worker_ui.ts
@@ -0,0 +1,20 @@
+import { Provider } from 'angular2/core';
+import { WebWorkerInstance, WORKER_SCRIPT } from 'angular2/platform/worker_render';
+
+document.addEventListener('DOMContentLoaded', function onDOMContentLoaded() {
+ const providers = [
+ new Provider(WORKER_SCRIPT, { useValue: window['__WORKER_SCRIPT_URL'] })
+ ];
+
+ const appRef = window[__APPS_WORKER_UI_BUNDLE_NAME__].main(providers);
+ const worker = appRef.injector.get(WebWorkerInstance).worker;
+
+ worker.addEventListener('message', function onAppReady(event) {
+ if (event.data === 'APP_READY') {
+ worker.removeEventListener('message', onAppReady, false);
+ URL.revokeObjectURL(window['__WORKER_SCRIPT_URL']);
+ delete window['__WORKER_SCRIPT_URL'];
+ setTimeout(function() { document.dispatchEvent(new Event('BootstrapComplete')) });
+ }
+ }, false);
+});
\ No newline at end of file
diff --git a/src/.utils/serve.ts b/src/.utils/serve.ts
new file mode 100644
index 0000000..90b2824
--- /dev/null
+++ b/src/.utils/serve.ts
@@ -0,0 +1,154 @@
+import { Request, Response } from 'express';
+import { resolve as resolvePath, relative as relativePath } from 'path';
+import { platform, Provider, ComponentRef, ExceptionHandler } from 'angular2/core';
+import { DOM } from 'angular2/src/platform/dom/dom_adapter';
+import { DOCUMENT } from 'angular2/platform/common_dom';
+import { ROUTER_PROVIDERS, APP_BASE_HREF, Router } from 'angular2/router';
+import { REQUEST_URL } from 'angular2-universal-preview';
+
+const {
+ createPrebootHTML,
+ getBrowserCode,
+ prebootConfigDefault
+} = require('angular2-universal-preview');
+
+const {
+ parseDocument,
+ serializeDocument
+} = require('angular2-universal-preview/dist/server/src/platform/document');
+
+const req = __non_webpack_require__;
+
+const VENDOR_PATH = req.resolve(__PUBLIC_DIR__ + '/' + __VENDOR_BUNDLE_NAME__);
+const VENDOR_URL = '/' + relativePath(__PUBLIC_DIR__, VENDOR_PATH);
+
+const WORKER_APP_LOADER_ORIGIN = 'window.location.origin';
+const WORKER_APP_READY_MESSAGE = 'APP_READY';
+
+function createBrowserScripts(browserUrl) {
+ return `
+
+
+ `;
+}
+
+function createWorkerScripts(workerUrl, workerAppUrl) {
+ return `
+
+
+
+ `
+}
+
+function createWorkerAppScripts(workerAppUrl) {
+ return `
+ var importScripts_ = this.importScripts;
+
+ this.importScripts = function importScripts() {
+ for (var i = 0, scripts = new Array(arguments.length); i < scripts.length; ++i) {
+ var script = arguments[i];
+ var origin = '" + ${WORKER_APP_LOADER_ORIGIN} + "';
+
+ if (script.indexOf('http:') !== 0 || script.indexOf('https:') !== 0) {
+ script = origin + (script[0] === '/' ? script : '/' + script);
+ }
+
+ scripts[i] = script;
+ }
+
+ return importScripts_.apply(this, scripts);
+ };
+
+ importScripts('${VENDOR_URL}', '${workerAppUrl}');
+ `;
+}
+
+export function serveUniversal(name, indexHtml, options: any = {}) {
+ let server, browserScripts = '', workerScripts = '', prebootHtml = '', prebootPromise = Promise.resolve();
+
+ if (options.server) {
+ const serverPath = typeof options.server === 'string'
+ ? options.server
+ : resolvePath(__PRIVATE_DIR__, name + '-' + __APPS_SERVER_BUNDLE_NAME__ + '.js');
+
+ server = req(serverPath);
+ }
+
+ if (options.browser) {
+ const browserPath = typeof options.browser === 'string'
+ ? options.browser
+ : resolvePath(__PUBLIC_DIR__, name + '-' + __APPS_BROWSER_BUNDLE_NAME__ + '.js');
+
+ const browserUrl = '/' + relativePath(__PUBLIC_DIR__, browserPath);
+
+ browserScripts = createBrowserScripts(browserUrl);
+ }
+
+ if (options.worker) {
+ const workerPaths = Array.isArray(options.worker)
+ ? options.worker
+ : [
+ resolvePath(__PUBLIC_DIR__, name + '-' + __APPS_WORKER_UI_BUNDLE_NAME__ + '.js'),
+ resolvePath(__PUBLIC_DIR__, name + '-' + __APPS_WORKER_APP_BUNDLE_NAME__+ '.js')
+ ];
+
+ const workerUrl = '/' + relativePath(__PUBLIC_DIR__, workerPaths[0]);
+ const workerAppUrl = '/' + relativePath(__PUBLIC_DIR__, workerPaths[1]);
+
+ workerScripts = createWorkerScripts(workerUrl, workerAppUrl);
+ }
+
+ const prebootOptions = options.preboot !== false
+ ? prebootConfigDefault(Object.assign({}, __PREBOOT__, options.preboot))
+ : false;
+
+ return (req: Request, res: Response, next: Function) => prebootPromise.then(() => Promise.resolve(indexHtml))
+ .then((html) => {
+ if (__SS__ && server) {
+ const REQUEST_PROVIDERS = [
+ new Provider(ExceptionHandler, { useFactory: () => new ExceptionHandler(DOM, true) }),
+ new Provider(DOCUMENT, { useValue: parseDocument(html) }),
+ new Provider(REQUEST_URL, { useValue: req.originalUrl }),
+ ];
+
+ return server.main(REQUEST_PROVIDERS, req).then(function(compRef) {
+ const injector = compRef.injector;
+ const router: Router = injector.getOptional(Router);
+
+ return Promise.resolve()
+ .then(() => router && ( router)._currentNavigation)
+ .then(() => new Promise(function(resolve) { setTimeout(resolve) }))
+ .then(() => serializeDocument(compRef.injector.get(DOCUMENT)))
+ });
+ }
+ return html;
+ })
+ .then((html) => {
+ if (prebootOptions && (workerScripts || browserScripts)) {
+ return getBrowserCode(prebootOptions).then((code) => {
+ const prebootHtml = createPrebootHTML(code, prebootOptions);
+
+ return html.replace('
Loading...
-