Client: add basic aot support

This commit is contained in:
Chocobozzz 2017-01-13 12:16:00 +01:00
parent 80deae8d19
commit c16ce1de8e
30 changed files with 292 additions and 106 deletions

2
client/.gitignore vendored
View File

@ -1,2 +1,4 @@
/dist/
/node_modules
/compiled
/stats.json

8
client/config/empty.js Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
NgProbeToken: {},
HmrState: function () {},
_createConditionalRootRenderer: function (rootRenderer, extraTokens, coreTokens) {
return rootRenderer
},
__platform_browser_private__: {}
}

View File

@ -1,13 +1,17 @@
const path = require('path')
// Helper functions
const ROOT = path.resolve(__dirname, '..')
console.log('root directory:', root() + '\n')
const EVENT = process.env.npm_lifecycle_event || ''
function hasProcessFlag (flag) {
return process.argv.join('').indexOf(flag) > -1
}
function hasNpmFlag (flag) {
return EVENT.includes(flag)
}
function isWebpackDevServer () {
return process.argv[1] && !!(/webpack-dev-server$/.exec(process.argv[1]))
}
@ -18,5 +22,6 @@ function root (args) {
}
exports.hasProcessFlag = hasProcessFlag
exports.hasNpmFlag = hasNpmFlag
exports.isWebpackDevServer = isWebpackDevServer
exports.root = root

View File

View File

@ -1,17 +1,20 @@
const webpack = require('webpack')
const helpers = require('./helpers')
/*
* Webpack Plugins
*/
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin
const AssetsPlugin = require('assets-webpack-plugin')
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin')
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin')
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin')
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
const ngcWebpack = require('ngc-webpack')
const WebpackNotifierPlugin = require('webpack-notifier')
/*
@ -29,7 +32,8 @@ const METADATA = {
* See: http://webpack.github.io/docs/configuration.html#cli
*/
module.exports = function (options) {
var isProd = options.env === 'production'
const isProd = options.env === 'production'
const AOT = isProd
return {
@ -49,9 +53,10 @@ module.exports = function (options) {
* See: http://webpack.github.io/docs/configuration.html#entry
*/
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'main': './src/main.ts'
'polyfills': './src/polyfills.browser.ts',
'main': AOT
? './src/main.browser.aot.ts'
: './src/main.browser.ts'
},
/*
@ -67,7 +72,7 @@ module.exports = function (options) {
*/
extensions: [ '.ts', '.js', '.json', '.scss' ],
modules: [helpers.root('src'), 'node_modules'],
modules: [ helpers.root('src'), helpers.root('node_modules') ],
alias: {
'video.js': 'video.js/dist/alt/video.novtt'
@ -90,10 +95,18 @@ module.exports = function (options) {
*/
{
test: /\.ts$/,
loaders: [
use: [
'@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
'awesome-typescript-loader',
'angular2-template-loader'
'awesome-typescript-loader?{configFileName: "tsconfig.webpack.json"}',
'angular2-template-loader',
{
loader: 'ng-router-loader',
options: {
loader: 'async-system',
genDir: 'compiled',
aot: AOT
}
}
],
exclude: [/\.(spec|e2e)\.ts$/]
},
@ -110,10 +123,11 @@ module.exports = function (options) {
{
test: /\.(sass|scss)$/,
loaders: ['css-to-string-loader', 'css-loader?sourceMap', 'resolve-url', 'sass-loader?sourceMap']
use: ['css-to-string-loader', 'css-loader?sourceMap', 'resolve-url-loader', 'sass-loader?sourceMap'],
exclude: [ helpers.root('src', 'styles') ]
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url?limit=10000&minetype=application/font-woff' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file' },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'url-loader?limit=10000&minetype=application/font-woff' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'file-loader' },
/* Raw loader support for *.html
* Returns file content as string
@ -148,7 +162,7 @@ module.exports = function (options) {
*
* See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
*/
new ForkCheckerPlugin(),
new CheckerPlugin(),
/*
* Plugin: CommonsChunkPlugin
@ -158,7 +172,20 @@ module.exports = function (options) {
* See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
* See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
*/
new webpack.optimize.CommonsChunkPlugin({
new CommonsChunkPlugin({
name: 'polyfills',
chunks: ['polyfills']
}),
// This enables tree shaking of the vendor modules
new CommonsChunkPlugin({
name: 'vendor',
chunks: ['main'],
minChunks: module => /node_modules\//.test(module.resource)
}),
// Specify the correct order the scripts will be injected in
new CommonsChunkPlugin({
name: ['polyfills', 'vendor'].reverse()
}),
@ -171,8 +198,11 @@ module.exports = function (options) {
*/
new ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('src') // location of your src
/angular(\\|\/)core(\\|\/)src(\\|\/)linker/,
helpers.root('src'), // location of your src
{
// your Angular Async Route paths relative to this root directory
}
),
/*
@ -255,6 +285,34 @@ module.exports = function (options) {
precision: 10
}
}
}),
// Fix Angular 2
new NormalModuleReplacementPlugin(
/facade(\\|\/)async/,
helpers.root('node_modules/@angular/core/src/facade/async.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)collection/,
helpers.root('node_modules/@angular/core/src/facade/collection.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)errors/,
helpers.root('node_modules/@angular/core/src/facade/errors.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)lang/,
helpers.root('node_modules/@angular/core/src/facade/lang.js')
),
new NormalModuleReplacementPlugin(
/facade(\\|\/)math/,
helpers.root('node_modules/@angular/core/src/facade/math.js')
),
new ngcWebpack.NgcWebpackPlugin({
disabled: !AOT,
tsConfig: helpers.root('tsconfig.webpack.json'),
resourceOverride: helpers.root('config/resource-override.js')
})
],
@ -270,7 +328,9 @@ module.exports = function (options) {
process: true,
module: false,
clearImmediate: false,
setImmediate: false
setImmediate: false,
setInterval: false,
setTimeout: false
}
}
}

View File

@ -1,6 +1,7 @@
const helpers = require('./helpers')
const webpackMerge = require('webpack-merge') // used to merge webpack configs
const commonConfig = require('./webpack.common.js') // the settings that are common to prod and dev
const path = require('path')
/**
* Webpack Plugins

View File

@ -9,14 +9,15 @@ const commonConfig = require('./webpack.common.js') // the settings that are com
/**
* Webpack Plugins
*/
// const ProvidePlugin = require('webpack/lib/ProvidePlugin')
const DefinePlugin = require('webpack/lib/DefinePlugin')
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const IgnorePlugin = require('webpack/lib/IgnorePlugin')
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin')
// const IgnorePlugin = require('webpack/lib/IgnorePlugin')
// const DedupePlugin = require('webpack/lib/optimize/DedupePlugin')
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin')
const ProvidePlugin = require('webpack/lib/ProvidePlugin')
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin')
const WebpackMd5Hash = require('webpack-md5-hash')
const V8LazyParseWebpackPlugin = require('v8-lazy-parse-webpack-plugin')
/**
* Webpack Constants
@ -154,22 +155,67 @@ module.exports = function (env) {
// comments: true, //debug
beautify: false, // prod
output: {
comments: false
}, // prod
mangle: {
screw_ie8: true,
keep_fnames: true
screw_ie8: true
}, // prod
compress: {
screw_ie8: true,
warnings: false
}, // prod
comments: false // prod
warnings: false,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true,
negate_iife: false // we need this for lazy v8
}
}),
new NormalModuleReplacementPlugin(
/angular2-hmr/,
helpers.root('config/modules/angular2-hmr-prod.js')
helpers.root('config/empty.js')
),
new NormalModuleReplacementPlugin(
/zone\.js(\\|\/)dist(\\|\/)long-stack-trace-zone/,
helpers.root('config/empty.js')
),
// AoT
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)upgrade/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)compiler/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /@angular(\\|\/)platform-browser-dynamic/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /dom(\\|\/)debug(\\|\/)ng_probe/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /dom(\\|\/)debug(\\|\/)by/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /src(\\|\/)debug(\\|\/)debug_node/,
// helpers.root('config/empty.js')
// ),
// new NormalModuleReplacementPlugin(
// /src(\\|\/)debug(\\|\/)debug_renderer/,
// helpers.root('config/empty.js')
// ),
/**
* Plugin: IgnorePlugin
* Description: Dont generate modules for requests matching the provided RegExp.
@ -228,7 +274,7 @@ module.exports = function (env) {
[/\*/, /(?:)/],
[/\[?\(?/, /(?:)/]
],
customAttrAssign: [/\)?]?=/]
customAttrAssign: [/\)?\]?=/]
},
// FIXME: Remove

View File

@ -20,6 +20,7 @@
"dependencies": {
"@angular/common": "~2.4.1",
"@angular/compiler": "~2.4.1",
"@angular/compiler-cli": "^2.4.3",
"@angular/core": "~2.4.1",
"@angular/forms": "~2.4.1",
"@angular/http": "~2.4.1",
@ -33,12 +34,13 @@
"@types/source-map": "^0.1.26",
"@types/uglify-js": "^2.0.27",
"@types/videojs": "0.0.30",
"@types/webpack": "^1.12.29",
"@types/webpack": "^2.0.0",
"angular-pipes": "^5.0.0",
"angular2-template-loader": "^0.6.0",
"assets-webpack-plugin": "^3.4.0",
"awesome-typescript-loader": "^2.2.1",
"bootstrap-loader": "^2.0.0-beta.11",
"awesome-typescript-loader": "~3.0.0-beta.17",
"bootstrap": "^3.3.6",
"bootstrap-loader": "2.0.0-beta.18",
"bootstrap-sass": "^3.3.6",
"copy-webpack-plugin": "^4.0.0",
"core-js": "^2.4.1",
@ -52,9 +54,11 @@
"intl": "^1.2.4",
"json-loader": "^0.5.4",
"ng2-bootstrap": "1.1.16-10",
"ng2-file-upload": "^1.1.0",
"ng2-file-upload": "^1.1.4-2",
"ng2-meta": "^2.0.0",
"node-sass": "^3.10.0",
"ng-router-loader": "^1.0.2",
"ngc-webpack": "^1.1.0",
"node-sass": "^4.1.1",
"normalize.css": "^5.0.0",
"raw-loader": "^0.5.1",
"reflect-metadata": "0.1.8",
@ -68,13 +72,14 @@
"ts-helpers": "^1.1.1",
"tslint": "3.15.1",
"tslint-loader": "^2.1.4",
"typescript": "~2.0.9",
"typescript": "~2.1.0",
"url-loader": "^0.5.7",
"v8-lazy-parse-webpack-plugin": "^0.3.0",
"video.js": "^5.11.9",
"videojs-dock": "^2.0.2",
"webpack": "2.1.0-beta.25",
"webpack": "2.2.0-rc.3",
"webpack-md5-hash": "0.0.5",
"webpack-merge": "^0.15.0",
"webpack-merge": "~2.3.1",
"webpack-notifier": "^1.3.0",
"webtorrent": "^0.98.0",
"zone.js": "~0.7.2"

View File

@ -1,4 +1,6 @@
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { AuthService } from '../core';
import { AuthHttp, RestExtractor } from '../shared';

View File

@ -1,5 +1,7 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Friend } from './friend.model';
import { AuthHttp, RestExtractor, ResultList } from '../../../shared';

View File

@ -1,3 +1,4 @@
import { setInterval } from 'timers'
import { Component, OnInit, OnDestroy } from '@angular/core';
import { RequestService, RequestStats } from '../shared';

View File

@ -1,5 +1,7 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { RequestStats } from './request-stats.model';
import { AuthHttp, RestExtractor } from '../../../shared';

View File

@ -1,4 +1,6 @@
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { AuthHttp, RestExtractor, ResultList, User } from '../../../shared';

View File

@ -1,7 +1,7 @@
import { Component, ViewContainerRef } from '@angular/core';
import { Router } from '@angular/router';
import { MetaService } from 'ng2-meta';
import { MetaService } from 'ng2-meta/src';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',

View File

@ -2,7 +2,8 @@ import { ApplicationRef, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { removeNgStyles, createNewHosts } from '@angularclass/hmr';
import { MetaModule, MetaConfig } from 'ng2-meta';
import { MetaModule, MetaConfig } from 'ng2-meta/src';
import 'bootstrap-loader';
import { ENV_PROVIDERS } from './environment';
import { AppRoutingModule } from './app-routing.module';

View File

@ -1,35 +1,35 @@
import { Injectable } from '@angular/core';
export type InternalStateType = {
[key: string]: any
};
@Injectable()
export class AppState {
_state = { };
constructor() { ; }
public _state: InternalStateType = { };
// already return a clone of the current state
get state() {
public get state() {
return this._state = this._clone(this._state);
}
// never allow mutation
set state(value) {
public set state(value) {
throw new Error('do not mutate the `.state` directly');
}
get(prop?: any) {
public get(prop?: any) {
// use our state getter for the clone
const state = this.state;
return state.hasOwnProperty(prop) ? state[prop] : state;
}
set(prop: string, value: any) {
public set(prop: string, value: any) {
// internally mutate our state
return this._state[prop] = value;
}
_clone(object) {
private _clone(object: InternalStateType) {
// simple object clone
return JSON.parse(JSON.stringify( object ));
}

View File

@ -3,6 +3,8 @@ import { Headers, Http, Response, URLSearchParams } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
// Do not use the barrel (dependency loop)
import { AuthStatus } from '../../shared/auth/auth-status.model';

View File

@ -4,19 +4,24 @@
import { enableDebugTools, disableDebugTools } from '@angular/platform-browser';
import { enableProdMode, ApplicationRef } from '@angular/core';
// Environment Providers
let PROVIDERS = [
let PROVIDERS: any[] = [
// common env directives
];
// Angular debug tools in the dev console
// https://github.com/angular/angular/blob/86405345b781a9dc2438c0fbe3e9409245647019/TOOLS_JS.md
let _decorateModuleRef = function identity(value) { return value; };
let _decorateModuleRef = function identity<T>(value: T): T { return value; };
if ('production' === ENV) {
// Production
disableDebugTools();
enableProdMode();
// Production
_decorateModuleRef = (modRef: any) => {
disableDebugTools();
return modRef;
};
PROVIDERS = [
...PROVIDERS,
// custom providers in production

View File

@ -80,12 +80,14 @@ export class AuthHttp extends Http {
}
}
export function useFactory(backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
return new AuthHttp(backend, defaultOptions, authService);
}
export const AUTH_HTTP_PROVIDERS = [
{
provide: AuthHttp,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) => {
return new AuthHttp(backend, defaultOptions, authService);
},
useFactory,
deps: [ XHRBackend, RequestOptions, AuthService ]
},
];

View File

@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Search } from '../../shared';
import { SortField } from './sort-field.type';

View File

@ -3,7 +3,7 @@
<div class="modal-content modal-lg">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hideModal()">
<button type="button" class="close" aria-label="Close" (click)="hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Magnet Uri</h4>

View File

@ -3,7 +3,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hideModal()">
<button type="button" class="close" aria-label="Close" (click)="hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Share</h4>

View File

@ -1,7 +1,8 @@
import { setInterval, setTimeout } from 'timers'
import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MetaService } from 'ng2-meta';
import { MetaService } from 'ng2-meta/src';
import * as videojs from 'video.js';
import { VideoMagnetComponent } from './video-magnet.component';

View File

@ -46,6 +46,16 @@ import * as _ from 'lodash'
// support NodeJS modules without type definitions
declare module '*';
/*
// for legacy tslint etc to understand rename 'modern-lru' with your package
// then comment out `declare module '*';`. For each new module copy/paste
// this method of creating an `any` module type definition
declare module 'modern-lru' {
let x: any;
export = x;
}
*/
// Extra variables that live on Global that will be replaced by webpack DefinePlugin
declare var ENV: string;
declare var HMR: boolean;
@ -56,8 +66,8 @@ interface SystemJS {
}
interface GlobalEnvironment {
ENV;
HMR;
ENV: string;
HMR: boolean;
SystemJS: SystemJS;
System: SystemJS;
}
@ -76,7 +86,6 @@ type AsyncRoutes = {
FactoryPromise
};
type IdleCallbacks = Es6PromiseLoader |
Function |
FactoryEs6PromiseLoader |
@ -98,7 +107,6 @@ interface WebpackModule {
};
}
interface WebpackRequire {
(id: string): any;
(paths: string[], callback: (...modules: any[]) => void): void;
@ -114,7 +122,6 @@ interface ErrorStackTraceLimit {
stackTraceLimit: number;
}
// Extend typings
interface NodeRequire extends WebpackRequire {}
interface ErrorConstructor extends ErrorStackTraceLimit {}

View File

@ -0,0 +1,23 @@
import { platformBrowser } from '@angular/platform-browser';
import { decorateModuleRef } from './app/environment';
/*
* App Module
* our top level module that holds all of our components
*/
import { AppModuleNgFactory } from '../compiled/src/app/app.module.ngfactory';
/*
* Bootstrap our Angular app with a top level NgModule
*/
export function main(): Promise<any> {
return platformBrowser()
.bootstrapModuleFactory(AppModuleNgFactory)
.then(decorateModuleRef)
.catch((err) => console.error(err));
}
export function bootstrapDomReady() {
document.addEventListener('DOMContentLoaded', main);
}
bootstrapDomReady();

View File

@ -1,4 +1,4 @@
@import '../video.js/dist/video-js.css';
@import '../../node_modules/video.js/dist/video-js.css';
body {
padding: 20px;

View File

@ -1,35 +0,0 @@
// For vendors for example jQuery, Lodash, angular2-jwt just import them here unless you plan on
// chunking vendors files for async loading. You would need to import the async loaded vendors
// at the entry point of the async loaded file. Also see custom-typings.d.ts as you also need to
// run `typings install x` where `x` is your module
// Angular 2
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/forms';
import '@angular/http';
import '@angular/router';
import '@angularclass/hmr';
// RxJS
import 'rxjs/Observable';
import 'rxjs/Subject';
import 'rxjs/ReplaySubject';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';
import 'bootstrap-loader';
import 'angular-pipes/src/math/bytes.pipe';
import 'ng2-file-upload';
import 'video.js';
import 'ng2-meta';
import 'ng2-bootstrap/pagination';
import 'ng2-bootstrap/dropdown';
import 'ng2-bootstrap/progressbar';
import 'ng2-bootstrap/modal';

View File

@ -0,0 +1,42 @@
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noEmitHelpers": true,
"strictNullChecks": false,
"baseUrl": "./src",
"paths": [
],
"lib": [
"dom",
"es6"
],
"types": [
"node",
"source-map",
"uglify-js",
"videojs",
"webpack"
]
},
"exclude": [
"node_modules",
"dist"
],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true,
"useWebpackText": true
},
"angularCompilerOptions": {
"genDir": "./compiled",
"skipMetadataEmit": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": { "rewriteTsconfig": false }
}