From abec1f733ed965e74ecafe389a92b183c1e0460f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 14 Dec 2016 00:01:01 +0100 Subject: [PATCH] AOT --- src/Squidex/Startup.cs | 2 +- src/Squidex/app-config/webpack.config.js | 2 +- src/Squidex/app-config/webpack.run.prod.js | 29 ++++++++++----- src/Squidex/app/app.routes.ts | 6 ++-- .../pages/clients/client.component.ts | 4 +-- .../pages/clients/clients-page.component.ts | 4 +-- .../contributors-page.component.ts | 2 +- .../angular/autocomplete.component.ts | 4 +-- .../app/framework/angular/http-utils.ts | 2 +- .../framework/angular/image-drop.directive.ts | 2 +- .../shared/components/app-form.component.ts | 4 +-- .../shell/pages/home/home-page.component.html | 2 +- src/Squidex/app/vendor.ts | 16 --------- src/Squidex/package.json | 33 ++++++++---------- src/Squidex/tsconfig.json | 6 ++-- .../{app => wwwroot}/images/loader.gif | Bin src/Squidex/{app => wwwroot}/images/logo.png | Bin src/Squidex/wwwroot/index.html | 2 +- src/Squidex/wwwroot/loader.gif | Bin 26181 -> 0 bytes 19 files changed, 56 insertions(+), 64 deletions(-) rename src/Squidex/{app => wwwroot}/images/loader.gif (100%) rename src/Squidex/{app => wwwroot}/images/logo.png (100%) delete mode 100644 src/Squidex/wwwroot/loader.gif diff --git a/src/Squidex/Startup.cs b/src/Squidex/Startup.cs index 0f34095de..6cab95e64 100644 --- a/src/Squidex/Startup.cs +++ b/src/Squidex/Startup.cs @@ -150,7 +150,7 @@ namespace Squidex private void MapAndUseFrontend(IApplicationBuilder app) { - if (Environment.IsDevelopment()) + if (!Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseWebpackProxy(); diff --git a/src/Squidex/app-config/webpack.config.js b/src/Squidex/app-config/webpack.config.js index 7efee6811..35bf88e71 100644 --- a/src/Squidex/app-config/webpack.config.js +++ b/src/Squidex/app-config/webpack.config.js @@ -48,7 +48,7 @@ module.exports = { loaders: ['awesome-typescript', 'angular2-router-loader', 'angular2-template-loader', 'tslint'] }, { test: /\.html$/, - loader: 'html' + loader: 'raw' }, { test: /\.(woff|woff2|ttf|eot)(\?.*$|$)/, loader: 'file?name=assets/[name].[hash].[ext]' diff --git a/src/Squidex/app-config/webpack.run.prod.js b/src/Squidex/app-config/webpack.run.prod.js index 5c65d3884..b4365c48f 100644 --- a/src/Squidex/app-config/webpack.run.prod.js +++ b/src/Squidex/app-config/webpack.run.prod.js @@ -1,12 +1,13 @@  var webpack = require('webpack'), webpackMerge = require('webpack-merge'), ExtractTextPlugin = require('extract-text-webpack-plugin'), + AotPlugin = require('@ngtools/webpack').AotPlugin, runConfig = require('./webpack.run.base.js'), helpers = require('./helpers'); var ENV = process.env.NODE_ENV = process.env.ENV = 'production'; -helpers.removeLoaders(runConfig, ['scss', 'png']); +helpers.removeLoaders(runConfig, ['scss', 'ts']); module.exports = webpackMerge(runConfig, { devtool: 'source-map', @@ -61,9 +62,9 @@ module.exports = webpackMerge(runConfig, { test: /\.scss$/, exclude: helpers.root('app', 'theme'), loaders: ['raw', helpers.root('app-config', 'clean-css-loader'), 'sass'] - }, { - test: /\.(png|jpe?g|gif|svg|ico)(\?.*$|$)/, - loaders: ['file?hash=sha512&digest=hex&name=assets/[name].[hash].[ext]', 'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'] + }, { + test: /\.ts/, + loaders: ['@ngtools/webpack'] } ] }, @@ -79,10 +80,22 @@ module.exports = webpackMerge(runConfig, { */ new ExtractTextPlugin('[name].[hash].css'), - new webpack.optimize.UglifyJsPlugin({ - mangle: { - screw_ie8: true, keep_fnames: true - } + new webpack.optimize.UglifyJsPlugin({ + beautify: false, + mangle: { + screw_ie8: true, + keep_fnames: true + }, + compress: { + warnings: false, + screw_ie8: true + }, + comments: false + }), + + new AotPlugin({ + tsConfigPath: './tsconfig.json', + entryModule: 'app/app.module#AppModule' }), ] }); \ No newline at end of file diff --git a/src/Squidex/app/app.routes.ts b/src/Squidex/app/app.routes.ts index d1f8334f3..b8d5bbf3a 100644 --- a/src/Squidex/app/app.routes.ts +++ b/src/Squidex/app/app.routes.ts @@ -22,8 +22,6 @@ import { MustBeNotAuthenticatedGuard } from './shared'; -import { SqxFeatureAppsModule } from './features/apps'; - export const routes: Routes = [ { path: '', @@ -36,7 +34,7 @@ export const routes: Routes = [ children: [ { path: '', - loadChildren: () => SqxFeatureAppsModule + loadChildren: './features/apps/module#SqxFeatureAppsModule' }, { path: ':appName', component: AppAreaComponent, @@ -53,7 +51,7 @@ export const routes: Routes = [ loadChildren: './features/media/module#SqxFeatureMediaModule' }, { path: 'schemas', - loadChildren: './features/schemas/module#SqxFeatureSchemaModule' + loadChildren: './features/schemas/module#SqxFeatureSchemasModule' }, { path: 'settings', loadChildren: './features/settings/module#SqxFeatureSettingsModule' diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.ts b/src/Squidex/app/features/settings/pages/clients/client.component.ts index 74eb0af45..5a8eb3f51 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/client.component.ts @@ -6,7 +6,7 @@ */ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { AccessTokenDto, @@ -56,7 +56,7 @@ export class ClientComponent { return this.client.secret; } - public renameForm = + public renameForm: FormGroup = this.formBuilder.group({ name: [''] }); diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index f47d5c6ed..313ff77a9 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -6,7 +6,7 @@ */ import { Component, OnInit } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AppClientDto, @@ -32,7 +32,7 @@ function rename(client: AppClientDto, name: string) { export class ClientsPageComponent extends AppComponentBase implements OnInit { public appClients: ImmutableArray; - public createForm = + public createForm: FormGroup = this.formBuilder.group({ name: ['', [ diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts index c2057eab0..3ce695750 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts @@ -23,7 +23,7 @@ import { UsersService } from 'shared'; -class UsersDataSource implements AutocompleteSource { +export class UsersDataSource implements AutocompleteSource { constructor( private readonly usersService: UsersService, private readonly component: ContributorsPageComponent diff --git a/src/Squidex/app/framework/angular/autocomplete.component.ts b/src/Squidex/app/framework/angular/autocomplete.component.ts index 714b2053a..f3310cb2a 100644 --- a/src/Squidex/app/framework/angular/autocomplete.component.ts +++ b/src/Squidex/app/framework/angular/autocomplete.component.ts @@ -33,9 +33,7 @@ const NOOP = () => { }; export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => { - return AutocompleteComponent; - }), + useExisting: forwardRef(() => AutocompleteComponent), multi: true }; diff --git a/src/Squidex/app/framework/angular/http-utils.ts b/src/Squidex/app/framework/angular/http-utils.ts index 637692353..dbf127a13 100644 --- a/src/Squidex/app/framework/angular/http-utils.ts +++ b/src/Squidex/app/framework/angular/http-utils.ts @@ -49,7 +49,7 @@ export class ErrorDto { } } -export function handleError(message: string, error: Response | any) { +export function handleError(message: string, error: Response | any): Observable { let result = new ErrorDto(500, message); if (error instanceof Response && error.status !== 500) { diff --git a/src/Squidex/app/framework/angular/image-drop.directive.ts b/src/Squidex/app/framework/angular/image-drop.directive.ts index 447252c6d..b974cb5ae 100644 --- a/src/Squidex/app/framework/angular/image-drop.directive.ts +++ b/src/Squidex/app/framework/angular/image-drop.directive.ts @@ -124,6 +124,6 @@ function isFunction(obj: any): boolean { return !!(obj && obj.constructor && obj.call && obj.apply); }; -interface DragDropEvent extends MouseEvent { +export interface DragDropEvent extends MouseEvent { readonly dataTransfer: DataTransfer; } \ No newline at end of file diff --git a/src/Squidex/app/shared/components/app-form.component.ts b/src/Squidex/app/shared/components/app-form.component.ts index 0657cf4b5..01110eb29 100644 --- a/src/Squidex/app/shared/components/app-form.component.ts +++ b/src/Squidex/app/shared/components/app-form.component.ts @@ -6,7 +6,7 @@ */ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FormBuilder, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { fadeAnimation } from 'framework'; @@ -34,7 +34,7 @@ export class AppFormComponent implements OnInit { public cancelled = new EventEmitter(); public creationError = ''; - public createForm = + public createForm: FormGroup = this.formBuilder.group({ name: ['', [ diff --git a/src/Squidex/app/shell/pages/home/home-page.component.html b/src/Squidex/app/shell/pages/home/home-page.component.html index 12604b098..2e769ac67 100644 --- a/src/Squidex/app/shell/pages/home/home-page.component.html +++ b/src/Squidex/app/shell/pages/home/home-page.component.html @@ -1,5 +1,5 @@
- + diff --git a/src/Squidex/app/vendor.ts b/src/Squidex/app/vendor.ts index 458ac1155..59e747af5 100644 --- a/src/Squidex/app/vendor.ts +++ b/src/Squidex/app/vendor.ts @@ -5,21 +5,5 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -/* tslint:disable ordered-imports */ - -// Angular 2 -import '@angular/platform-browser'; -import '@angular/platform-browser-dynamic'; -import '@angular/core'; -import '@angular/common'; -import '@angular/http'; -import '@angular/forms'; -import '@angular/router'; - -// Additional libs -import 'rxjs'; -import 'moment'; -import 'oidc-client'; - // Bootstrap import 'theme/vendor.scss'; \ No newline at end of file diff --git a/src/Squidex/package.json b/src/Squidex/package.json index 9fdc68792..74c4364a8 100644 --- a/src/Squidex/package.json +++ b/src/Squidex/package.json @@ -9,33 +9,31 @@ "test:coverage": "karma start karma.coverage.conf.js", "test:clean": "rimraf _test-output", "dev": "cpx node_modules/oidc-client/dist/oidc-client.min.js wwwroot/scripts/ & webpack-dev-server --config app-config/webpack.run.dev.js --inline --hot --port 3000", - "build": "webpack --config app-config/webpack.run.prod.js --bail", + "build": "webpack --config app-config/webpack.run.prod.js --display-error-details", "build:copy": "cpx node_modules/oidc-client/dist/oidc-client.min.js wwwroot/scripts/", "build:clean": "rimraf wwwroot/build" }, "dependencies": { - "@angular/common": "^2", - "@angular/compiler": "^2", - "@angular/core": "^2", - "@angular/forms": "^2", - "@angular/http": "^2", - "@angular/platform-browser": "^2", - "@angular/platform-browser-dynamic": "^2", - "@angular/router": "^3", - "babel-polyfill": "^6.16.0", + "@angular/common": "2.2.3", + "@angular/compiler": "2.2.3", + "@angular/core": "2.2.3", + "@angular/forms": "2.2.3", + "@angular/http": "2.2.3", + "@angular/platform-browser": "2.2.3", + "@angular/platform-browser-dynamic": "2.2.3", + "@angular/router": "3.2.3", "bootstrap": "^4.0.0-alpha.2", "core-js": "^2.4.1", - "moment": "^2.17.0", + "moment": "^2.17.1", "mousetrap": "^1.6.0", "oidc-client": "^1.2.2", - "reflect-metadata": "^0.1.8", "rxjs": "5.0.0-beta.12", "zone.js": "^0.6.23" }, "devDependencies": { - "@angular/compiler-cli": "^2.2.3", - "@ngtools/webpack": "^1.1.6", - "@types/core-js": "^0.9.34", + "@angular/compiler-cli": "2.2.3", + "@ngtools/webpack": "^1.1.9", + "@types/core-js": "^0.9.35", "@types/jasmine": "^2.5.38", "@types/mousetrap": "^1.5.32", "@types/node": "^6.0.51", @@ -43,13 +41,12 @@ "angular2-template-loader": "^0.6.0", "awesome-typescript-loader": "^2.2.4", "cpx": "^1.5.0", - "css-loader": "^0.26.0", + "css-loader": "^0.26.1", "exports-loader": "^0.6.3", "extract-text-webpack-plugin": "^2.0.0-beta.4", "file-loader": "^0.9.0", "html-loader": "^0.4.4", "html-webpack-plugin": "^2.24.1", - "image-webpack-loader": "^3.0.0", "istanbul-instrumenter-loader": "^0.2.0", "jasmine-core": "^2.5.2", "karma": "^1.3.0", @@ -62,7 +59,7 @@ "karma-phantomjs-launcher": "^1.0.2", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^1.8.0", - "node-sass": "^3.13.0", + "node-sass": "^3.4.2", "null-loader": "^0.1.1", "phantomjs-prebuilt": "^2.1.13", "raw-loader": "^0.5.1", diff --git a/src/Squidex/tsconfig.json b/src/Squidex/tsconfig.json index 84b9ce9b1..c5fec859d 100644 --- a/src/Squidex/tsconfig.json +++ b/src/Squidex/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es5", - "module": "commonjs", + "module": "es2015", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, @@ -14,7 +14,9 @@ "suppressImplicitAnyIndexErrors": true, "baseUrl": ".", "paths": { - "*": ["*", "app/*"] + "framework": ["app/framework"], + "features": ["app/features"], + "shared": ["app/shared"] } } } \ No newline at end of file diff --git a/src/Squidex/app/images/loader.gif b/src/Squidex/wwwroot/images/loader.gif similarity index 100% rename from src/Squidex/app/images/loader.gif rename to src/Squidex/wwwroot/images/loader.gif diff --git a/src/Squidex/app/images/logo.png b/src/Squidex/wwwroot/images/logo.png similarity index 100% rename from src/Squidex/app/images/logo.png rename to src/Squidex/wwwroot/images/logo.png diff --git a/src/Squidex/wwwroot/index.html b/src/Squidex/wwwroot/index.html index b35ff0ddf..b7d53ffbe 100644 --- a/src/Squidex/wwwroot/index.html +++ b/src/Squidex/wwwroot/index.html @@ -36,7 +36,7 @@
- +
Loading awesomeness
diff --git a/src/Squidex/wwwroot/loader.gif b/src/Squidex/wwwroot/loader.gif deleted file mode 100644 index 0a8226a3bcbe84414a39319cf288334554024eb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26181 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 SC$Rklwx7WE6Zk*&1pWtbD}m?$