├── README.md ├── package.json ├── postcss.config.js ├── src ├── app │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ngfactory.ts │ ├── app.module.ts │ ├── modules │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.ts │ │ │ └── home.module.ts │ │ ├── lazy │ │ │ ├── lazy.component.html │ │ │ ├── lazy.component.ts │ │ │ └── lazy.module.ts │ │ └── shared │ │ │ ├── components │ │ │ └── page-not-found │ │ │ │ ├── page-not-found.component.html │ │ │ │ └── page-not-found.component.ts │ │ │ └── shared.module.ts │ ├── ng-main-aot.ts │ ├── ng-main.ts │ ├── ng-polyfills.ts │ └── ng-routing.module.ts ├── assets │ ├── base.less │ └── themes │ │ └── base │ │ ├── images │ │ ├── icons │ │ │ └── cross.svg │ │ └── other-images │ │ │ └── panda.png │ │ └── styles │ │ ├── blocks │ │ └── app-component.less │ │ └── common │ │ ├── colors.less │ │ ├── common.less │ │ ├── fonts.less │ │ ├── normalize.less │ │ └── vars.less └── index.html ├── tsconfig.json ├── tslint.json ├── webpack-prod-server.js └── webpack.config.js /README.md: -------------------------------------------------------------------------------- 1 | Link to the guide https://habrahabr.ru/company/netcracker/blog/337540/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-project", 3 | "version": "1.0.0", 4 | "description": "angular scaffolding", 5 | "author": "maxim1006", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@angular/animations": "^4.3.6", 9 | "@angular/common": "^4.3.6", 10 | "@angular/compiler": "^4.3.6", 11 | "@angular/compiler-cli": "^4.3.6", 12 | "@angular/core": "^4.3.6", 13 | "@angular/forms": "^4.3.6", 14 | "@angular/http": "^4.3.6", 15 | "@angular/platform-browser": "^4.3.6", 16 | "@angular/platform-browser-dynamic": "^4.3.6", 17 | "@angular/router": "^4.3.6", 18 | "@angularclass/hmr": "^2.1.1", 19 | "@angularclass/hmr-loader": "^3.0.2", 20 | "core-js": "^2.5.0", 21 | "reflect-metadata": "^0.1.8", 22 | "rxjs": "^5.4.3", 23 | "typescript": "2.3.4", 24 | "zone.js": "^0.8.17" 25 | }, 26 | "devDependencies": { 27 | "@ngtools/webpack": "^1.6.2", 28 | "@types/es6-shim": "^0.31.35", 29 | "@types/jasmine": "2.2.34", 30 | "@types/node": "^7.0.43", 31 | "angular-router-loader": "^0.6.0", 32 | "angular2-template-loader": "^0.6.2", 33 | "autoprefixer": "^6.3.7", 34 | "awesome-typescript-loader": "^3.2.3", 35 | "copy-webpack-plugin": "^4.0.1", 36 | "css-loader": "^0.28.5", 37 | "css-to-string-loader": "^0.1.2", 38 | "es6-shim": "^0.35.1", 39 | "hammerjs": "^2.0.8", 40 | "html-webpack-plugin": "^2.29.0", 41 | "less": "^2.7.2", 42 | "less-loader": "^4.0.3", 43 | "on-build-webpack": "^0.1.0", 44 | "postcss-loader": "^1.3.3", 45 | "raw-loader": "^0.5.1", 46 | "rimraf": "^2.6.1", 47 | "style-loader": "^0.17.0", 48 | "tslint": "^5.7.0", 49 | "url-loader": "^0.5.8", 50 | "webpack": "^3.5.5", 51 | "webpack-dev-server": "^2.7.1" 52 | }, 53 | "scripts": { 54 | "serve": "webpack-dev-server --config ./webpack.config.js --profile --watch --progress --open", 55 | "hmr": "webpack-dev-server --config ./webpack.config.js --profile --watch --progress --open", 56 | "prod": "npm run aot", 57 | "prodServer": "webpack-dev-server --config ./webpack.config.js --open", 58 | "clean": "rimraf ./dist", 59 | "aot": "webpack", 60 | "test": "karma start" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer')({ 4 | browsers: [ 5 | 'last 2 versions' 6 | ], 7 | cascade: true 8 | }) 9 | ] 10 | }; -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | Hello app 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, HostBinding, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-component', 5 | templateUrl: './app.component.html' 6 | }) 7 | export class AppComponent implements OnInit { 8 | @HostBinding('class') classes = 'app-component'; 9 | 10 | constructor() {} 11 | 12 | ngOnInit() { 13 | } 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/app.module.ngfactory.ts: -------------------------------------------------------------------------------- 1 | export abstract class AppModuleNgFactory{} -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | require("style-loader!../assets/base.less"); 2 | 3 | import {BrowserModule, HammerGestureConfig} from "@angular/platform-browser"; 4 | import {NgRoutingModule} from "./ng-routing.module"; 5 | import {AppComponent} from "./app.component"; 6 | import {createInputTransfer, createNewHosts, removeNgStyles} from "@angularclass/hmr"; 7 | import {ApplicationRef, NgModule} from "@angular/core"; 8 | import {HomeModule} from "./modules/home/home.module"; 9 | 10 | 11 | export class MyHammerConfig extends HammerGestureConfig { 12 | overrides = { 13 | 'swipe': {velocity: 0.4, threshold: 20} // override default settings 14 | } 15 | } 16 | 17 | @NgModule({ 18 | declarations: [ 19 | AppComponent, 20 | ], 21 | imports: [ 22 | BrowserModule, 23 | HomeModule, 24 | NgRoutingModule 25 | ], 26 | providers: [ 27 | ], 28 | bootstrap: [ 29 | AppComponent 30 | ] 31 | }) 32 | 33 | export class AppModule { 34 | constructor(public appRef: ApplicationRef) {} 35 | hmrOnInit(store) { 36 | if (!store || !store.state) return; 37 | 38 | if ('restoreInputValues' in store) { 39 | store.restoreInputValues(); 40 | } 41 | 42 | this.appRef.tick(); 43 | delete store.state; 44 | delete store.restoreInputValues; 45 | } 46 | hmrOnDestroy(store) { 47 | let cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement); 48 | store.disposeOldHosts = createNewHosts(cmpLocation); 49 | store.state = {data: 'yolo'}; 50 | store.restoreInputValues = createInputTransfer(); 51 | removeNgStyles(); 52 | } 53 | hmrAfterDestroy(store) { 54 | store.disposeOldHosts(); 55 | delete store.disposeOldHosts; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/app/modules/home/home.component.html: -------------------------------------------------------------------------------- 1 |

Welcome Home

2 | 3 | panda 4 | -------------------------------------------------------------------------------- /src/app/modules/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: 'home-component', 5 | templateUrl: 'home.component.html' 6 | }) 7 | export class HomeComponent { 8 | } -------------------------------------------------------------------------------- /src/app/modules/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from "@angular/core"; 2 | import {SharedModule} from "../shared/shared.module"; 3 | import {HomeComponent} from "./home.component"; 4 | 5 | @NgModule({ 6 | imports: [SharedModule], 7 | exports: [HomeComponent], 8 | declarations: [HomeComponent], 9 | }) 10 | export class HomeModule { 11 | 12 | } -------------------------------------------------------------------------------- /src/app/modules/lazy/lazy.component.html: -------------------------------------------------------------------------------- 1 |

Lazy component

-------------------------------------------------------------------------------- /src/app/modules/lazy/lazy.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: 'lazy-component', 5 | templateUrl: "./lazy.component.html" 6 | }) 7 | export class LazyComponent { 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/app/modules/lazy/lazy.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from "@angular/core"; 2 | import {SharedModule} from "../shared/shared.module"; 3 | import {LazyComponent} from "./lazy.component"; 4 | import {RouterModule, Routes} from "@angular/router"; 5 | 6 | 7 | const routes: Routes = [ 8 | {path: '', component: LazyComponent}, 9 | ]; 10 | 11 | 12 | @NgModule({ 13 | imports: [SharedModule, RouterModule.forChild(routes)], 14 | exports: [LazyComponent], 15 | declarations: [LazyComponent] 16 | }) 17 | export class LazyModule {} 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/modules/shared/components/page-not-found/page-not-found.component.html: -------------------------------------------------------------------------------- 1 | Page not found 404 -------------------------------------------------------------------------------- /src/app/modules/shared/components/page-not-found/page-not-found.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "page-not-found", 5 | templateUrl: "./page-not-found.component.html" 6 | }) 7 | 8 | export class PageNotFoundComponent implements OnInit { 9 | 10 | ngOnInit() {} 11 | 12 | } -------------------------------------------------------------------------------- /src/app/modules/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import {CommonModule} from "@angular/common"; 2 | import {NgModule} from "@angular/core"; 3 | import {PageNotFoundComponent} from "./components/page-not-found/page-not-found.component"; 4 | 5 | @NgModule({ 6 | imports: [CommonModule], 7 | exports: [CommonModule, PageNotFoundComponent], 8 | declarations: [PageNotFoundComponent] 9 | }) 10 | export class SharedModule {} -------------------------------------------------------------------------------- /src/app/ng-main-aot.ts: -------------------------------------------------------------------------------- 1 | import './ng-polyfills'; 2 | import {enableProdMode} from "@angular/core"; 3 | import {platformBrowser} from "@angular/platform-browser"; 4 | import {AppModuleNgFactory} from "./app.module.ngfactory"; 5 | 6 | console.log("******************You are in prod mode******************"); 7 | 8 | enableProdMode(); 9 | platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).catch(error=>console.log(error)); -------------------------------------------------------------------------------- /src/app/ng-main.ts: -------------------------------------------------------------------------------- 1 | import './ng-polyfills'; 2 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic"; 3 | import {AppModule} from "./app.module"; 4 | import {enableProdMode} from "@angular/core"; 5 | import {bootloader} from "@angularclass/hmr"; 6 | 7 | declare const Reflect: any; 8 | 9 | if (process.env.STATIC) { 10 | //console.log("******************You are in Dev mode******************"); 11 | platformBrowserDynamic().bootstrapModule(AppModule).then(():any => {}); 12 | } else if (process.env.HMR) { 13 | //console.log("******************You are in HMR mode******************"); 14 | bootloader(main); 15 | } 16 | 17 | export function main() { 18 | return platformBrowserDynamic() 19 | .bootstrapModule(AppModule) 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/app/ng-polyfills.ts: -------------------------------------------------------------------------------- 1 | import "core-js/es6"; 2 | import "core-js/es7/reflect"; 3 | import "zone.js/dist/zone"; 4 | import "reflect-metadata/Reflect"; 5 | import 'hammerjs/hammer'; 6 | 7 | -------------------------------------------------------------------------------- /src/app/ng-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule, Routes} from "@angular/router"; 2 | import {NgModule} from "@angular/core"; 3 | import {PageNotFoundComponent} from "./modules/shared/components/page-not-found/page-not-found.component"; 4 | import {HomeComponent} from "./modules/home/home.component"; 5 | 6 | 7 | 8 | const routes: Routes = [ 9 | {path: '', redirectTo: '/home', pathMatch: 'full'}, 10 | {path: 'home', component: HomeComponent}, 11 | {path: 'lazy', loadChildren: './modules/lazy/lazy.module#LazyModule'}, 12 | {path: '**', component: PageNotFoundComponent}, 13 | ]; 14 | 15 | 16 | 17 | @NgModule({ 18 | imports: [ 19 | RouterModule.forRoot(routes) 20 | ], 21 | exports: [ 22 | RouterModule 23 | ] 24 | }) 25 | export class NgRoutingModule { } 26 | -------------------------------------------------------------------------------- /src/assets/base.less: -------------------------------------------------------------------------------- 1 | // Common 2 | @import "themes/base/styles/common/normalize"; 3 | @import "themes/base/styles/common/colors"; 4 | @import "themes/base/styles/common/common"; 5 | @import "themes/base/styles/common/fonts"; 6 | @import "themes/base/styles/common/vars"; 7 | 8 | // Plugins 9 | //@import (less) "plugins/; 10 | 11 | // Blocks 12 | // (please, add new blocks in alphabetical order) 13 | @import "themes/base/styles/blocks/app-component"; 14 | -------------------------------------------------------------------------------- /src/assets/themes/base/images/icons/cross.svg: -------------------------------------------------------------------------------- 1 | Rectangle 12Created with Avocode. -------------------------------------------------------------------------------- /src/assets/themes/base/images/other-images/panda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxim1006/angular-project/274231aa3252a5ce98ce898dc92ec153da73a87a/src/assets/themes/base/images/other-images/panda.png -------------------------------------------------------------------------------- /src/assets/themes/base/styles/blocks/app-component.less: -------------------------------------------------------------------------------- 1 | .app-component { 2 | display: flex; 3 | flex-direction: column; 4 | flex-wrap: wrap; 5 | position: relative; 6 | color: @main; 7 | 8 | &:after { 9 | content: ''; 10 | position: absolute; 11 | top: 0; 12 | right: 0; 13 | width: 24px; 14 | height: 24px; 15 | background: url('../../images/icons/cross.svg'); 16 | } 17 | } -------------------------------------------------------------------------------- /src/assets/themes/base/styles/common/colors.less: -------------------------------------------------------------------------------- 1 | @main: #333; 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/themes/base/styles/common/common.less: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | 4 | &:before, 5 | &:after { 6 | box-sizing: border-box; 7 | } 8 | } 9 | 10 | body { 11 | font-family: @font-family; 12 | } 13 | 14 | ._margin_no { 15 | margin: 0 !important; 16 | } 17 | 18 | h1,h2,h3,h4,h5 { 19 | margin: 0; 20 | } 21 | 22 | ul, li { 23 | margin: 0; 24 | padding: 0; 25 | } 26 | 27 | p { 28 | margin: 0; 29 | } 30 | 31 | a { 32 | &, 33 | &:hover, 34 | &:focus, 35 | &:active { 36 | cursor: pointer; 37 | text-decoration: none; 38 | outline: none; 39 | } 40 | 41 | &, 42 | &:visited { 43 | } 44 | 45 | &:hover, 46 | &:focus, 47 | &:active { 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/assets/themes/base/styles/common/fonts.less: -------------------------------------------------------------------------------- 1 | @font-family: Helvetica, Arial, sans-serif; 2 | -------------------------------------------------------------------------------- /src/assets/themes/base/styles/common/normalize.less: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | 429 | 430 | input[type="text"] { 431 | border: none; 432 | 433 | &:focus, 434 | &:active { 435 | outline: none; 436 | } 437 | } 438 | 439 | button { 440 | border: none; 441 | background-color: transparent; 442 | 443 | &:focus, 444 | &:active { 445 | outline: none; 446 | } 447 | } 448 | 449 | -------------------------------------------------------------------------------- /src/assets/themes/base/styles/common/vars.less: -------------------------------------------------------------------------------- 1 | // Page 2 | @page-min-width: 320px; 3 | @page-max-width: 1240px; 4 | 5 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Landing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Loading... 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "declaration": false, 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "removeComments": false, 11 | "noImplicitAny": false, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "skipLibCheck": true, 14 | "lib": ["es6", "dom"], 15 | "outDir": "./dist/", 16 | "typeRoots": [ 17 | "./node_modules/@types/" 18 | ] 19 | }, 20 | "compileOnSave": false, 21 | "buildOnSave": false, 22 | "include": [ 23 | "./src/**/*" 24 | ], 25 | "exclude": [ 26 | "node_modules/**/*", 27 | "dist/*", 28 | "dist-serve/*", 29 | "node/*", 30 | "**/*.spec.ts" 31 | ], 32 | "awesomeTypescriptLoaderOptions": { 33 | "forkChecker": true, 34 | "useWebpackText": true, 35 | "useCache": true 36 | }, 37 | "angularCompilerOptions": { 38 | "genDir": ".", 39 | "skipMetadataEmit" : true 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-unused-variable": true, 4 | "curly": true, 5 | "no-console": [ 6 | true, 7 | "log", 8 | "error", 9 | "debug", 10 | "info" 11 | ], 12 | "no-debugger": true, 13 | "no-duplicate-variable": true, 14 | "no-eval": true, 15 | "no-invalid-this": true, 16 | "no-shadowed-variable": true, 17 | "no-unsafe-finally": true, 18 | "no-var-keyword": true, 19 | "triple-equals": [ 20 | true, 21 | "allow-null-check", 22 | "allow-undefined-check" 23 | ], 24 | "semicolon": [ 25 | true, 26 | "always", 27 | "ignore-interfaces" 28 | ], 29 | "variable-name": [ 30 | true, 31 | "ban-keywords", 32 | "check-format", 33 | "allow-leading-underscore" 34 | ] 35 | } 36 | } -------------------------------------------------------------------------------- /webpack-prod-server.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxim1006/angular-project/274231aa3252a5ce98ce898dc92ec153da73a87a/webpack-prod-server.js -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const webpack = require('webpack'); 6 | const WebpackOnBuildPlugin = require('on-build-webpack'); 7 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 8 | const AotPlugin = require('@ngtools/webpack').AotPlugin; 9 | 10 | 11 | 12 | const ENV = process.env.npm_lifecycle_event ? process.env.npm_lifecycle_event : ''; 13 | const isStatic = ENV === 'serve'; 14 | const isHmr = ENV === 'hmr'; 15 | const isProd = ENV === 'prod'; 16 | const isTest = ENV === 'test'; 17 | const isAot = ENV.includes('aot'); 18 | const isProdServer = ENV.includes('prodServer'); 19 | 20 | 21 | 22 | module.exports = function makeWebpackConfig() { 23 | 24 | console.log(`You are in ${ENV} mode`); 25 | 26 | let config = {}; 27 | 28 | if (isProdServer) { 29 | if (!fs.existsSync('./dist')) { 30 | throw "Can't find ./dist, please use 'npm run prod' to get it."; 31 | } 32 | } 33 | 34 | if (isHmr || isStatic) { 35 | config.devtool = 'inline-source-map'; 36 | } else { 37 | config.devtool = 'source-map'; 38 | } 39 | 40 | config.entry = { 41 | 'ng-app': './src/app/ng-main.ts' 42 | }; 43 | 44 | if (isAot) { 45 | config.entry['ng-app'] = './src/app/ng-main-aot.ts'; 46 | } 47 | 48 | config.output = isTest ? {} : { 49 | path: root('./dist'), 50 | filename: '[name].js' 51 | }; 52 | 53 | if (isProdServer) { 54 | config.entry = { 55 | 'server': './webpack-prod-server.js' 56 | }; 57 | config.output = {}; 58 | } 59 | 60 | config.resolve = { 61 | extensions: ['.ts', '.js', '.json', '.html', '.less', '.svg'] 62 | }; 63 | 64 | config.module = { 65 | rules: [ 66 | { 67 | test: /\.ts$/, 68 | use: isAot ? [{loader: '@ngtools/webpack'}] : [ 69 | { 70 | loader: 'awesome-typescript-loader?' 71 | }, 72 | { 73 | loader: 'angular2-template-loader' 74 | }, 75 | { 76 | loader: 'angular-router-loader' 77 | } 78 | ].concat(isHmr ? '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd : []), 79 | exclude: [/\.(spec|e2e|d)\.ts$/] 80 | }, 81 | { 82 | test: /\.html$/, loader: 'raw-loader', 83 | exclude: [/node_modules\/(?!(ng2-.+))/, root('src/index.html')] 84 | }, 85 | { 86 | test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 87 | loader: "url-loader?name=[name].[ext]&limit=10000&useRelativePath=true" 88 | }, 89 | { 90 | test: /\.less$/, 91 | use: [ 92 | {loader: "css-to-string-loader"}, 93 | {loader: "css-loader"}, 94 | {loader: "postcss-loader"}, 95 | {loader: "less-loader"} 96 | ] 97 | } 98 | ] 99 | }; 100 | 101 | 102 | 103 | if (isTest) { 104 | config.module.rules.push({ 105 | test: /\.ts$/, 106 | enforce: "post", 107 | include: path.resolve("src"), 108 | loader: "istanbul-instrumenter-loader", 109 | exclude: [/\.spec\.ts$/, /\.e2e\.ts$/, /node_modules/] 110 | }); 111 | } 112 | 113 | 114 | 115 | if (!isTest) { 116 | config.plugins = [ 117 | new webpack.NoEmitOnErrorsPlugin(), 118 | new webpack.DefinePlugin({ 119 | 'process.env': { 120 | 'STATIC': isStatic, 121 | 'HMR': isHmr, 122 | 'PROD': isProd, 123 | 'AOT': isAot 124 | } 125 | }), 126 | new WebpackOnBuildPlugin((stats) => { 127 | console.log('build is done'); 128 | }) 129 | ] 130 | .concat(isHmr ? new webpack.HotModuleReplacementPlugin() : []); 131 | } 132 | 133 | 134 | 135 | if (isAot) { 136 | config.plugins = [ 137 | new AotPlugin({ 138 | tsConfigPath: './tsconfig.json', 139 | entryModule: root('src/app/app.module.ts#AppModule') 140 | }), 141 | new webpack.optimize.UglifyJsPlugin({ 142 | compress: { 143 | warnings: false, 144 | screw_ie8: true, 145 | conditionals: true, 146 | unused: true, 147 | comparisons: true, 148 | sequences: true, 149 | dead_code: true, 150 | evaluate: true, 151 | if_return: true, 152 | join_vars: true 153 | }, 154 | output: { 155 | comments: false 156 | }, 157 | sourceMap: true 158 | }), 159 | new CopyWebpackPlugin([ 160 | {from: 'index.html', context: './src'}, 161 | {from: 'assets/themes/base/fonts/**/*', context: './src'}, 162 | {from: 'assets/themes/base/images/other-images/**/*', context: './src'} 163 | ]), 164 | new WebpackOnBuildPlugin((stats) => { 165 | console.log('build in aot is done'); 166 | }) 167 | ]; 168 | 169 | config.stats = { 170 | assets: true, 171 | chunks: false, 172 | children: false, 173 | errors: true, 174 | errorDetails: true, 175 | timings: true, 176 | warnings: true 177 | }; 178 | } 179 | 180 | 181 | 182 | config.devServer = { 183 | contentBase: isProdServer ? "./dist" : "./src", 184 | headers: { 185 | "Access-Control-Allow-Origin": "*", 186 | "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", 187 | "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization" 188 | }, 189 | historyApiFallback: true, 190 | compress: true, 191 | quiet: false, 192 | inline: isHmr || isStatic || isProdServer, 193 | hot: isHmr, 194 | stats: "minimal", 195 | port: 9000, 196 | overlay: { 197 | errors: true 198 | }, 199 | clientLogLevel: "none", 200 | watchOptions: { 201 | aggregateTimeout: 50, 202 | ignored: /node_modules/ 203 | } 204 | }; 205 | 206 | return config; 207 | }; 208 | 209 | 210 | 211 | function root(__path = '.') { 212 | return path.join(__dirname, __path); 213 | } 214 | --------------------------------------------------------------------------------