diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Asp2017.sln b/Asp2017.sln new file mode 100644 index 00000000..1a8d0744 --- /dev/null +++ b/Asp2017.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2002 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Asp2017", "Asp2017.csproj", "{6D840EA5-1645-48F5-8484-49EA0B3CEA08}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6D840EA5-1645-48F5-8484-49EA0B3CEA08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D840EA5-1645-48F5-8484-49EA0B3CEA08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D840EA5-1645-48F5-8484-49EA0B3CEA08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D840EA5-1645-48F5-8484-49EA0B3CEA08}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DE657E62-6B86-42DB-AF34-1799BE789EFF} + EndGlobalSection +EndGlobal diff --git a/ClientApp/app/app.component.html b/ClientApp/app/app.component.html index a3e3bf9b..53921664 100644 --- a/ClientApp/app/app.component.html +++ b/ClientApp/app/app.component.html @@ -2,5 +2,5 @@
- -
+ + \ No newline at end of file diff --git a/ClientApp/app/app.component.scss b/ClientApp/app/app.component.scss index 481063dc..78209cff 100644 --- a/ClientApp/app/app.component.scss +++ b/ClientApp/app/app.component.scss @@ -1,10 +1,11 @@ -$navbar-default-bg: #312312; +$navbar-default-bg: #312312; $light-orange: #ff8c00; $navbar-default-color: $light-orange; /* Import Bootstrap & Fonts */ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; @import "http://github.com/~bootstrap-sass/assets/stylesheets/bootstrap"; +@import "http://github.com/~@angular/material/prebuilt-themes/indigo-pink.css"; diff --git a/ClientApp/app/app.module.browser.ts b/ClientApp/app/app.module.browser.ts index ac318d44..4d19bad4 100644 --- a/ClientApp/app/app.module.browser.ts +++ b/ClientApp/app/app.module.browser.ts @@ -1,4 +1,4 @@ -import { NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { APP_BASE_HREF } from '@angular/common'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; diff --git a/ClientApp/app/app.module.ts b/ClientApp/app/app.module.ts index 1c492f1d..c54da476 100644 --- a/ClientApp/app/app.module.ts +++ b/ClientApp/app/app.module.ts @@ -25,6 +25,19 @@ import { UserService } from './shared/user.service'; // import { ConnectionResolver } from './shared/route.resolver'; import { ORIGIN_URL } from './shared/constants/baseurl.constants'; import { TransferHttpModule } from '../modules/transfer-http/transfer-http.module'; +import { MyNewComponentComponent } from './components/my-new-component/my-new-component.component'; +import { ImageListComponent } from './components/image-list/image-list.component'; + +// New Imports +import { + MatRadioModule, + MatSlideToggleModule, + MatGridListModule, + MatTableModule, + MatCardModule +} from '@angular/material'; + +import { ServicesComponent } from './components/services/services.component'; export function createTranslateLoader(http: Http, baseHref) { // Temporary Azure hack @@ -45,12 +58,20 @@ export function createTranslateLoader(http: Http, baseHref) { HomeComponent, // ChatComponent, NotFoundComponent, - NgxBootstrapComponent + NgxBootstrapComponent, + MyNewComponentComponent, + ImageListComponent, + ServicesComponent ], imports: [ CommonModule, HttpModule, FormsModule, + MatRadioModule, + MatSlideToggleModule, + MatGridListModule, + MatTableModule, + MatCardModule, Ng2BootstrapModule.forRoot(), // You could also split this up if you don't want the Entire Module imported TransferHttpModule, // Our Http TransferData method diff --git a/ClientApp/app/components/image-list/image-list.component.html b/ClientApp/app/components/image-list/image-list.component.html new file mode 100644 index 00000000..7cab4c74 --- /dev/null +++ b/ClientApp/app/components/image-list/image-list.component.html @@ -0,0 +1,19 @@ + + +
+ Shiba Inu + Dog Breed +
+ Photo of a Shiba Inu + +

+ The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan. + A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally + bred for hunting. +

+
+ + + + +
\ No newline at end of file diff --git a/ClientApp/app/components/image-list/image-list.component.scss b/ClientApp/app/components/image-list/image-list.component.scss new file mode 100644 index 00000000..d24d7eb5 --- /dev/null +++ b/ClientApp/app/components/image-list/image-list.component.scss @@ -0,0 +1,8 @@ +.example-card { + max-width: 400px; +} + +.example-header-image { + background-image: url('http://material.angular.io/assets/img/examples/shiba1.jpg'); + background-size: cover; +} \ No newline at end of file diff --git a/ClientApp/app/components/image-list/image-list.component.ts b/ClientApp/app/components/image-list/image-list.component.ts new file mode 100644 index 00000000..924ef17a --- /dev/null +++ b/ClientApp/app/components/image-list/image-list.component.ts @@ -0,0 +1,19 @@ +import { Component, OnInit } from '@angular/core'; + +/** + * @title Radios with ngModel + */ + +@Component({ + selector: 'app-image-list', + templateUrl: './image-list.component.html', + styleUrls: ['./image-list.component.scss'] +}) +export class ImageListComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/ClientApp/app/components/my-new-component/my-new-component.component.html b/ClientApp/app/components/my-new-component/my-new-component.component.html new file mode 100644 index 00000000..2281a987 --- /dev/null +++ b/ClientApp/app/components/my-new-component/my-new-component.component.html @@ -0,0 +1,7 @@ + + + {{season}} + + +
Your favorite season is: {{favoriteSeason}}
+ diff --git a/ClientApp/app/components/my-new-component/my-new-component.component.scss b/ClientApp/app/components/my-new-component/my-new-component.component.scss new file mode 100644 index 00000000..f70c1b3b --- /dev/null +++ b/ClientApp/app/components/my-new-component/my-new-component.component.scss @@ -0,0 +1,12 @@ +.example-radio-group { + display: inline-flex; + flex-direction: column; +} + +.example-radio-button { + margin: 5px; +} + +.example-selected-value { + margin: 15px 0; +} diff --git a/ClientApp/app/components/my-new-component/my-new-component.component.ts b/ClientApp/app/components/my-new-component/my-new-component.component.ts new file mode 100644 index 00000000..5add9fc1 --- /dev/null +++ b/ClientApp/app/components/my-new-component/my-new-component.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; + +/** + * @title Radios with ngModel + */ +@Component({ + selector: 'app-my-new-component', + templateUrl: './my-new-component.component.html', + styleUrls: ['./my-new-component.component.scss'], +}) + +export class MyNewComponentComponent implements OnInit { + favoriteSeason: string; + + seasons = [ + 'Winter', + 'Spring', + 'Summer', + 'Autumn', + ]; + constructor() { } + + ngOnInit() { + } +} diff --git a/ClientApp/app/components/navmenu/navmenu.component.css b/ClientApp/app/components/navmenu/navmenu.component.css index 8d86aa03..c453a91c 100644 --- a/ClientApp/app/components/navmenu/navmenu.component.css +++ b/ClientApp/app/components/navmenu/navmenu.component.css @@ -34,6 +34,9 @@ li.link-active a:focus { font-size: 14px; background-color: #f1f1f1; } + + + .navbar-toggle { padding: 0px 5px; margin-top: 0px; @@ -50,6 +53,10 @@ li.link-active a:focus { background-color: white; } + .navbar { + background-color: #f1f1f1; + } + .navbar a { /* If a menu item's text is too long, truncate it */ white-space: nowrap; diff --git a/ClientApp/app/components/navmenu/navmenu.component.html b/ClientApp/app/components/navmenu/navmenu.component.html index bd6eadda..d8ed0630 100644 --- a/ClientApp/app/components/navmenu/navmenu.component.html +++ b/ClientApp/app/components/navmenu/navmenu.component.html @@ -8,7 +8,7 @@ - Angular 4 Universal & ASP.NET Core + Layers-N-Lashes
@@ -19,7 +19,7 @@ {{ 'HOME' | translate }} -
  • + + + + Name + {{service.name}} + + + + Description + {{service.description}} + + + + Price + {{ service.price | currency:'USD':true }} + + + + + diff --git a/ClientApp/app/components/services/services.component.scss b/ClientApp/app/components/services/services.component.scss new file mode 100644 index 00000000..ed85d209 --- /dev/null +++ b/ClientApp/app/components/services/services.component.scss @@ -0,0 +1,11 @@ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + min-width: 300px; +} + +.mat-table { + overflow: auto; + max-height: 500px; +} \ No newline at end of file diff --git a/ClientApp/app/components/services/services.component.ts b/ClientApp/app/components/services/services.component.ts new file mode 100644 index 00000000..59ebf47f --- /dev/null +++ b/ClientApp/app/components/services/services.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; +import {DataSource} from '@angular/cdk/collections'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/observable/of'; +import { CurrencyPipe } from '@angular/common'; + +@Component({ + selector: 'app-services', + + templateUrl: './services.component.html', + styleUrls: ['./services.component.scss'] +}) +export class ServicesComponent implements OnInit { + + displayedColumns = ['name', 'description', 'price']; + dataSource = new ExampleDataSource(); + constructor() { } + + ngOnInit() { + } + +} + + export interface Service { + name: string; + description: string; + price: number; + } + + const data: Service[] = [ + {name: 'Micro Blade', description: 'Hydrogen', price: 10.00}, + {name: 'Kids Cut', description: 'Helium', price: 10.00}, + {name: 'Eye Lash Extensions', description: 'Lithium', price: 10.00}, + {name: 'temp', description: 'Beryllium', price: 9.00}, + {name: 'temp', description: 'Boron', price: 10.81}, + {name: 'temp', description: 'Carbon', price: 12.01}, + {name: 'temp', description: 'Nitrogen', price: 14.00}, + ]; + + /** + * Data source to provide what data should be rendered in the table. The observable provided + * in connect should emit exactly the data that should be rendered by the table. If the data is + * altered, the observable should emit that new set of data on the stream. In our case here, + * we return a stream that contains only one set of data that doesn't change. + */ + export class ExampleDataSource extends DataSource { + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + return Observable.of(data); + } + + disconnect() {} + } diff --git a/ClientApp/app/containers/home/home.component.html b/ClientApp/app/containers/home/home.component.html index 06d801e7..8282e984 100644 --- a/ClientApp/app/containers/home/home.component.html +++ b/ClientApp/app/containers/home/home.component.html @@ -1,61 +1,21 @@ -

    {{ title }}

    - -
    - Enjoy the latest features from .NET Core & Angular 4.0! -
    For more info check the repo here: AspNetCore-Angular2-Universal repo -

    -
    +

    {{ title }}

    +

    {{ 'HOME_FEATURE_LIST_TITLE' | translate }}

    -
      -
    • ASP.NET Core 2.0 :: ( Visual Studio 2017 )
    • -
    • - Angular 4.* front-end UI framework -
        -
      • Angular **platform-server** (aka: Universal) - server-side rendering for SEO, deep-linking, and - incredible performance.
      • - -
      • AoT (Ahead-of-time) production compilation for even faster Prod builds.
      • -
      -
    • -
    • - The latest TypeScript 2.* features - -
    • -
    • - Webpack -
        - -
      • Hot Module Reloading/Replacement for an amazing development experience.
      • -
      • Tree-shaking
      • -
      -
    • - -
    • Bootstrap (ngx-bootstrap) : Bootstrap capable of being rendered even on the server.
    • -
    • Unit testing via karma & jasmine.
    • - -
    -

    {{ 'HOME_ISSUES_TITLE' | translate }}

    - -
    + + +
    diff --git a/ClientApp/app/containers/home/home.component.ts b/ClientApp/app/containers/home/home.component.ts index 3065c0b1..6c0ded9a 100644 --- a/ClientApp/app/containers/home/home.component.ts +++ b/ClientApp/app/containers/home/home.component.ts @@ -8,7 +8,7 @@ import { TranslateService } from '@ngx-translate/core'; }) export class HomeComponent implements OnInit { - title: string = 'Angular 4.0 Universal & ASP.NET Core 2.0 advanced starter-kit'; + title: string = 'Layers N Lashes'; // Use "constructor"s only for dependency injection constructor( diff --git a/ClientApp/boot.browser.ts b/ClientApp/boot.browser.ts index a7830543..c399e99d 100644 --- a/ClientApp/boot.browser.ts +++ b/ClientApp/boot.browser.ts @@ -2,6 +2,7 @@ import './polyfills/browser.polyfills'; import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module.browser'; +import 'hammerjs'; const rootElemTagName = 'app'; // Update this if you change your root component selector diff --git a/Startup.cs b/Startup.cs index 7736f9e9..0648b14e 100644 --- a/Startup.cs +++ b/Startup.cs @@ -54,7 +54,7 @@ public void ConfigureServices(IServiceCollection services) // Register the Swagger generator, defining one or more Swagger documents services.AddSwaggerGen(c => { - c.SwaggerDoc("v1", new Info { Title = "Angular 4.0 Universal & ASP.NET Core advanced starter-kit web API", Version = "v1" }); + c.SwaggerDoc("v1", new Info { Title = "Layers N Lashes", Version = "v1" }); }); } diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index b0796562..a9731e8b 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -1,7 +1,8 @@ -@Html.Raw(ViewData["SpaHtml"]) +@Html.Raw(ViewData["SpaHtml"]) @section scripts { } + diff --git a/app.json b/app.json new file mode 100644 index 00000000..edb6c994 --- /dev/null +++ b/app.json @@ -0,0 +1,20 @@ +{ + "name": "aspnetcore-angular2-universal", + "description": "Deploy Angular 2+ Universal & ASP.NET Core SPA Advanced Starter on Heroku", + "logo": "https://raw.githubusercontent.com/herokumx/herokumxnet/master/NETChatterGroup.png", + "keywords": [ "heroku", "asp.net-core", "angular2", "spa" ], + "env": { + "NPM_CONFIG_PRODUCTION": { + "description": "False as we need to install devDependencies on heroku instance (webpack, ...)", + "value": "true" + } + }, + "buildpacks": [ + { + "url": "heroku/nodejs" + }, + { + "url": "https://github.com/jincod/dotnetcore-buildpack" + } + ] +} diff --git a/package.json b/package.json index 9ebbf620..ca82f2e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,13 @@ { "name": "angular4-aspnetcore-universal", "version": "1.0.0-rc3", + "license": "UNLICENSED", + "repository": { + "type": "git", + "url": "https://github.com/tboneteen18/aspnetcore-angular2-universal.git" + }, "scripts": { + "start": "", "lint": "tslint -p tsconfig.json", "test": "npm run build:vendor && karma start ClientApp/test/karma.conf.js", "test:watch": "npm run test -- --auto-watch --no-single-run", @@ -15,21 +21,23 @@ "clean": "rimraf wwwroot/dist clientapp/dist" }, "dependencies": { - "@angular/animations": "^4.3.0", - "@angular/common": "^4.3.0", - "@angular/compiler": "^4.3.0", - "@angular/compiler-cli": "^4.3.0", - "@angular/core": "^4.3.0", - "@angular/forms": "^4.3.0", - "@angular/http": "^4.3.0", - "@angular/platform-browser": "^4.3.0", - "@angular/platform-browser-dynamic": "^4.3.0", - "@angular/platform-server": "^4.3.0", - "@angular/router": "^4.3.0", + "@angular/animations": "^4.4.6", + "@angular/cdk": "^2.0.0-beta.12", + "@angular/common": "^4.4.6", + "@angular/compiler": "^4.4.6", + "@angular/compiler-cli": "^4.4.6", + "@angular/core": "^4.4.6", + "@angular/forms": "^4.4.6", + "@angular/http": "^4.4.6", + "@angular/material": "^2.0.0-beta.12", + "@angular/platform-browser": "^4.4.6", + "@angular/platform-browser-dynamic": "^4.4.6", + "@angular/platform-server": "^4.4.6", + "@angular/router": "^4.4.6", "@nguniversal/aspnetcore-engine": "^1.0.0-beta.2", "@ngx-translate/core": "^6.0.1", "@ngx-translate/http-loader": "0.0.3", - "@types/node": "^7.0.12", + "@types/node": "^7.0.46", "angular2-router-loader": "^0.3.5", "angular2-template-loader": "^0.6.2", "aspnet-prerendering": "^3.0.1", @@ -44,6 +52,7 @@ "expose-loader": "^0.7.3", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", + "hammerjs": "^2.0.8", "html-loader": "^0.5.1", "isomorphic-fetch": "^2.2.1", "jquery": "^2.2.1", @@ -54,19 +63,19 @@ "preboot": "^5.0.0", "raw-loader": "^0.5.1", "rimraf": "^2.6.2", - "rxjs": "^5.4.3", + "rxjs": "^5.5.0", "sass-loader": "^6.0.6", "style-loader": "^0.18.2", "to-string-loader": "^1.1.5", "typescript": "2.5.2", "url-loader": "^0.5.7", - "webpack": "^3.6.0", - "webpack-hot-middleware": "^2.19.1", + "webpack": "^3.8.1", + "webpack-hot-middleware": "^2.20.0", "webpack-merge": "^4.1.0", "zone.js": "^0.8.17" }, "devDependencies": { - "@angular/cli": "^1.3.2", + "@angular/cli": "^1.4.9", "@ngtools/webpack": "^1.3.0", "@types/chai": "^3.4.34", "@types/jasmine": "^2.5.37", @@ -79,12 +88,12 @@ "karma-chrome-launcher": "^2.2.0", "karma-coverage": "^1.1.1", "karma-jasmine": "^1.1.0", - "karma-mocha-reporter": "^2.2.4", + "karma-mocha-reporter": "^2.2.5", "karma-phantomjs-launcher": "^1.0.4", "karma-remap-coverage": "^0.1.4", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^2.0.3", - "tslint": "^5.7.0", + "tslint": "^5.8.0", "webpack-bundle-analyzer": "^2.9.0" } } diff --git a/webpack.config.vendor.js b/webpack.config.vendor.js index 3e07b78b..600f1912 100644 --- a/webpack.config.vendor.js +++ b/webpack.config.vendor.js @@ -1,99 +1,101 @@ -const path = require('path'); -const webpack = require('webpack'); -const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const merge = require('webpack-merge'); -const treeShakableModules = [ - '@angular/animations', - '@angular/common', - '@angular/compiler', - '@angular/core', - '@angular/forms', - '@angular/http', - '@angular/platform-browser', - '@angular/platform-browser-dynamic', - '@angular/router', - 'ngx-bootstrap', - 'zone.js', -]; -const nonTreeShakableModules = [ - // 'bootstrap', - // 'bootstrap/dist/css/bootstrap.css', - 'core-js', - // 'es6-promise', - // 'es6-shim', - 'event-source-polyfill', - // 'jquery', -]; -const allModules = treeShakableModules.concat(nonTreeShakableModules); - -module.exports = (env) => { - console.log(`env = ${JSON.stringify(env)}`) - const extractCSS = new ExtractTextPlugin('vendor.css'); - const isDevBuild = !(env && env.prod); - const sharedConfig = { - stats: { modules: false }, - resolve: { extensions: [ '.js' ] }, - module: { - rules: [ - { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' } - ] - }, - output: { - publicPath: 'dist/', - filename: '[name].js', - library: '[name]_[hash]' - }, - plugins: [ - // new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) - new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580 - new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898 - new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100 - ] - }; - - const clientBundleConfig = merge(sharedConfig, { - entry: { - // To keep development builds fast, include all vendor dependencies in the vendor bundle. - // But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle. - vendor: isDevBuild ? allModules : nonTreeShakableModules - }, - output: { path: path.join(__dirname, 'wwwroot', 'dist') }, - module: { - rules: [ - { test: /\.css(\?|$)/, use: extractCSS.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) } - ] - }, - plugins: [ - extractCSS, - new webpack.DllPlugin({ - path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'), - name: '[name]_[hash]' - }) - ].concat(isDevBuild ? [] : [ - new webpack.optimize.UglifyJsPlugin() - ]) - }); - - const serverBundleConfig = merge(sharedConfig, { - target: 'node', - resolve: { mainFields: ['main'] }, - entry: { vendor: allModules.concat(['aspnet-prerendering']) }, - output: { - path: path.join(__dirname, 'ClientApp', 'dist'), - libraryTarget: 'commonjs2', - }, - module: { - rules: [ { test: /\.css(\?|$)/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] } ] - }, - plugins: [ - new webpack.DllPlugin({ - path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'), - name: '[name]_[hash]' - }) - ].concat(isDevBuild ? [] : [ - new webpack.optimize.UglifyJsPlugin() - ]) - }); - - return [clientBundleConfig, serverBundleConfig]; -} +const path = require('path'); +const webpack = require('webpack'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const merge = require('webpack-merge'); +const treeShakableModules = [ + '@angular/animations', + '@angular/common', + '@angular/compiler', + '@angular/core', + '@angular/forms', + '@angular/http', + '@angular/platform-browser', + '@angular/platform-browser-dynamic', + '@angular/router', + '@angular/material', + '@angular/cdk', + 'ngx-bootstrap', + 'zone.js', +]; +const nonTreeShakableModules = [ + // 'bootstrap', + // 'bootstrap/dist/css/bootstrap.css', + 'core-js', + // 'es6-promise', + // 'es6-shim', + 'event-source-polyfill', + // 'jquery', +]; +const allModules = treeShakableModules.concat(nonTreeShakableModules); + +module.exports = (env) => { + console.log(`env = ${JSON.stringify(env)}`) + const extractCSS = new ExtractTextPlugin('vendor.css'); + const isDevBuild = !(env && env.prod); + const sharedConfig = { + stats: { modules: false }, + resolve: { extensions: [ '.js' ] }, + module: { + rules: [ + { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' } + ] + }, + output: { + publicPath: 'dist/', + filename: '[name].js', + library: '[name]_[hash]' + }, + plugins: [ + // new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) + new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/11580 + new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, path.join(__dirname, './ClientApp')), // Workaround for https://github.com/angular/angular/issues/14898 + new webpack.IgnorePlugin(/^vertx$/) // Workaround for https://github.com/stefanpenner/es6-promise/issues/100 + ] + }; + + const clientBundleConfig = merge(sharedConfig, { + entry: { + // To keep development builds fast, include all vendor dependencies in the vendor bundle. + // But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle. + vendor: isDevBuild ? allModules : nonTreeShakableModules + }, + output: { path: path.join(__dirname, 'wwwroot', 'dist') }, + module: { + rules: [ + { test: /\.css(\?|$)/, use: extractCSS.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) } + ] + }, + plugins: [ + extractCSS, + new webpack.DllPlugin({ + path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'), + name: '[name]_[hash]' + }) + ].concat(isDevBuild ? [] : [ + new webpack.optimize.UglifyJsPlugin() + ]) + }); + + const serverBundleConfig = merge(sharedConfig, { + target: 'node', + resolve: { mainFields: ['main'] }, + entry: { vendor: allModules.concat(['aspnet-prerendering']) }, + output: { + path: path.join(__dirname, 'ClientApp', 'dist'), + libraryTarget: 'commonjs2', + }, + module: { + rules: [ { test: /\.css(\?|$)/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] } ] + }, + plugins: [ + new webpack.DllPlugin({ + path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'), + name: '[name]_[hash]' + }) + ].concat(isDevBuild ? [] : [ + new webpack.optimize.UglifyJsPlugin() + ]) + }); + + return [clientBundleConfig, serverBundleConfig]; +}