├── .github └── dotnet-new.jpg ├── .gitignore ├── AngularWebpackVisualStudio.sln ├── CHANGELOG.md ├── LICENSE ├── README.md ├── appveyor.yml ├── docs ├── HMR.md └── LAZY_LOADING.md ├── src └── AngularWebpackVisualStudio │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .template.config │ └── template.json │ ├── .vscode │ ├── launch.json │ └── tasks.json │ ├── AngularWebpackVisualStudio.csproj │ ├── Controllers │ └── ThingsController.cs │ ├── Models │ └── Thing.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Repositories │ └── Things │ │ ├── IThingsRepository.cs │ │ └── ThingsRepository.cs │ ├── Startup.cs │ ├── angularApp │ ├── app │ │ ├── about │ │ │ ├── about.module.ts │ │ │ ├── about.routes.ts │ │ │ └── components │ │ │ │ ├── about.component.html │ │ │ │ └── about.component.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.constants.ts │ │ ├── app.module.ts │ │ ├── app.routes.ts │ │ ├── core │ │ │ ├── core.module.ts │ │ │ └── services │ │ │ │ └── thing-data.service.ts │ │ ├── home │ │ │ ├── components │ │ │ │ ├── home.component.html │ │ │ │ └── home.component.ts │ │ │ ├── home.module.ts │ │ │ └── home.routes.ts │ │ ├── models │ │ │ └── thing.ts │ │ └── shared │ │ │ ├── components │ │ │ ├── customfooter │ │ │ │ ├── customfooter.component.html │ │ │ │ └── customfooter.component.ts │ │ │ └── navigation │ │ │ │ ├── navigation.component.html │ │ │ │ └── navigation.component.ts │ │ │ └── shared.module.ts │ ├── images │ │ ├── RobertoSimonetti.jpg │ │ ├── damienbod.jpg │ │ └── fabianGosebrink.jpg │ ├── index.html │ ├── main-aot.ts │ ├── main.ts │ ├── polyfills.ts │ ├── styles.scss │ ├── styles │ │ └── app.scss │ ├── tests │ │ └── components │ │ │ └── home.component.spec.ts │ └── vendor.ts │ ├── appsettings.json │ ├── config │ ├── spec.bundle.js │ ├── webpack.dev.js │ ├── webpack.helpers.js │ ├── webpack.prod.js │ └── webpack.test.js │ ├── favicon.ico │ ├── karma.conf.js │ ├── package-lock.json │ ├── package.json │ ├── tsconfig-aot.json │ ├── tsconfig.json │ ├── web.config │ ├── webpack.config.js │ └── wwwroot │ └── favicon.ico └── tests └── AngularWebpackVisualStudio_Tests ├── AngularWebpackVisualStudio_Tests.csproj ├── Properties └── launchSettings.json └── ThingsController_Tests.cs /.github/dotnet-new.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/.github/dotnet-new.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | # ========================= 255 | # Operating System Files 256 | # ========================= 257 | 258 | # OSX 259 | # ========================= 260 | 261 | .DS_Store 262 | .AppleDouble 263 | .LSOverride 264 | 265 | # Thumbnails 266 | ._* 267 | 268 | # Files that might appear in the root of a volume 269 | .DocumentRevisions-V100 270 | .fseventsd 271 | .Spotlight-V100 272 | .TemporaryItems 273 | .Trashes 274 | .VolumeIcon.icns 275 | 276 | # Directories potentially created on remote AFP share 277 | .AppleDB 278 | .AppleDesktop 279 | Network Trash Folder 280 | Temporary Items 281 | .apdisk 282 | 283 | # Windows 284 | # ========================= 285 | 286 | # Windows image file caches 287 | Thumbs.db 288 | ehthumbs.db 289 | 290 | # Folder config file 291 | Desktop.ini 292 | 293 | # Recycle Bin used on file shares 294 | $RECYCLE.BIN/ 295 | 296 | # Windows Installer files 297 | *.cab 298 | *.msi 299 | *.msm 300 | *.msp 301 | 302 | # Windows shortcuts 303 | *.lnk 304 | 305 | # Angular 2 306 | # ========================= 307 | 308 | # AoT compilation files 309 | aot/ 310 | 311 | # TypeScript compilation files 312 | **/angularApp/app/**/*.js 313 | **/angularApp/app/**/*.map 314 | **/angularApp/app/*.js 315 | **/angularApp/app/*.map 316 | **/angularApp/*.js 317 | **/angularApp/*.map 318 | **/angularApp/tests/**/*.js 319 | **/angularApp/tests/**/*.map 320 | Angular2WebpackVisualStudio/src/Angular2WebpackVisualStudio/wwwroot/ 321 | src/Angular2WebpackVisualStudio/wwwroot/assets 322 | src/Angular2WebpackVisualStudio/wwwroot/dist 323 | src/AngularWebpackVisualStudio/wwwroot/dist/ 324 | src/AngularWebpackVisualStudio/wwwroot/index.html 325 | src/AngularWebpackVisualStudio/wwwroot/ 326 | -------------------------------------------------------------------------------- /AngularWebpackVisualStudio.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2005 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AngularWebpackVisualStudio", "src\AngularWebpackVisualStudio\AngularWebpackVisualStudio.csproj", "{40085317-5EE8-4719-A90B-22BD9685B7A7}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{23B1A0C4-07DB-4A9C-9FDE-7CF33321DE87}" 9 | ProjectSection(SolutionItems) = preProject 10 | appveyor.yml = appveyor.yml 11 | CHANGELOG.md = CHANGELOG.md 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{262E4648-178C-4184-A629-47B09F3C426D}" 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AngularWebpackVisualStudio_Tests", "tests\AngularWebpackVisualStudio_Tests\AngularWebpackVisualStudio_Tests.csproj", "{B51B6236-C279-42C0-B7CE-234F6D5690BD}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|x64 = Debug|x64 23 | Debug|x86 = Debug|x86 24 | Release|Any CPU = Release|Any CPU 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|x64.ActiveCfg = Debug|Any CPU 32 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|x64.Build.0 = Debug|Any CPU 33 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|x86.ActiveCfg = Debug|Any CPU 34 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Debug|x86.Build.0 = Debug|Any CPU 35 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|x64.ActiveCfg = Release|Any CPU 38 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|x64.Build.0 = Release|Any CPU 39 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|x86.ActiveCfg = Release|Any CPU 40 | {40085317-5EE8-4719-A90B-22BD9685B7A7}.Release|x86.Build.0 = Release|Any CPU 41 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|x64.ActiveCfg = Debug|Any CPU 44 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|x64.Build.0 = Debug|Any CPU 45 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|x86.ActiveCfg = Debug|Any CPU 46 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Debug|x86.Build.0 = Debug|Any CPU 47 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|x64.ActiveCfg = Release|Any CPU 50 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|x64.Build.0 = Release|Any CPU 51 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|x86.ActiveCfg = Release|Any CPU 52 | {B51B6236-C279-42C0-B7CE-234F6D5690BD}.Release|x86.Build.0 = Release|Any CPU 53 | EndGlobalSection 54 | GlobalSection(SolutionProperties) = preSolution 55 | HideSolutionNode = FALSE 56 | EndGlobalSection 57 | GlobalSection(NestedProjects) = preSolution 58 | {B51B6236-C279-42C0-B7CE-234F6D5690BD} = {262E4648-178C-4184-A629-47B09F3C426D} 59 | EndGlobalSection 60 | GlobalSection(ExtensibilityGlobals) = postSolution 61 | SolutionGuid = {EE6C6335-BC22-4B5E-89DB-377E431A14DB} 62 | EndGlobalSection 63 | EndGlobal 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Webpack Visual Studio Changelog 2 | For a fresh start, consider running these commands 3 | * `rimraf node_modules && del package-lock.json` 4 | * `npm install` 5 | 6 | Readme 7 | 8 | 9 | # 2021-03-14 Version 8.0.1 10 | * Update to Angular 11.2.5, .NET 5 11 | 12 | 13 | # 2020-12-13 Version 8.0.0 14 | * Update to Angular 11.0.4, .NET 5 15 | 16 | 17 | # 2020-09-15 Version 7.0.1 18 | * Update to Angular 10.1.1 19 | * 20 | 21 | 22 | # 2020-06-26 Version 7.0.0 23 | * Update to Angular 10.0.0 24 | 25 | 26 | # 2020-05-03 Version 6.0.2 27 | * Update to Angular 9.1.4 28 | 29 | 30 | # 2020-03-22 Version 6.0.1 31 | * Update to Angular 9.0.7 32 | 33 | 34 | 35 | # 2020-02-10 Version 6.0.0 36 | * Update to Angular 9 37 | * Update .NET Core 3.1.1 38 | * Move to eslint 39 | 40 | 41 | # 2020-01-02 Version 5.0.26 42 | * npm audit fix 43 | * Update .NET Core 3.1 44 | 45 | 46 | # 2019-11-17 Version 5.0.25 47 | * Angular 8.2.14 48 | 49 | 50 | # 2019-09-24 Version 5.0.24 51 | * ASP.NET Core 3.0 52 | * Angular 8.2.7 53 | 54 | 55 | # 2019-09-01 Version 5.0.23 56 | * Angular 8.2.4 57 | 58 | 59 | # 2019-07-30 Version 5.0.22 60 | * Angular 8.1.3 61 | 62 | 63 | # 2019-03-29 Version 5.0.21 64 | * Angular 8.0.0, typescript 3.4 65 | 66 | 67 | # 2019-03-29 Version 5.0.19 68 | * Angular 7.2.11 69 | * updated breaking changes from clean-webpack-plugin 70 | 71 | 72 | # 2019-02-24 Version 5.0.18 73 | * Angular 7.2.9 74 | 75 | 76 | # 2019-02-24 Version 5.0.17 77 | * Angular 7.2.6 78 | 79 | 80 | # 2019-02-06 Version 5.0.16 81 | * Angular 7.2.4 82 | * build fix production build 83 | 84 | 85 | 86 | # 2019-01-30 Version 5.0.15 87 | * Angular 7.2.2 88 | 89 | 90 | # 2019-01-09 Version 5.0.14 91 | * Angular 7.2.0 92 | 93 | 94 | # 2018-12-04 Version 5.0.13 95 | * .NET Core 2.2 96 | * Angular 7.1.1 97 | 98 | 99 | 100 | # 2018-11-22 Version 5.0.12 101 | * Angular 7.1.0 102 | 103 | 104 | # 2018-10-25 Version 5.0.10 105 | * Fixed tslint warnings, and build warnings 106 | 107 | 108 | # 2018-10-20 109 | * Updated packages, angular 7.0.0 110 | 111 | 112 | # 2018-10-14 113 | * Updated packages, angular 6.1.10 114 | * added a default build script to the npm 115 | 116 | 117 | # 2018-09-21 118 | * Updated packages, angular 6.1.8 119 | 120 | 121 | # 2018-09-07 122 | * Updated packages, angular 6.1.7 123 | 124 | 125 | # 2018-08-18 126 | * Updated packages, angular 6.1.3 127 | 128 | 129 | # 2018-08-01 130 | * Updated packages, angular 6.1.0, .NET Core 2.1.2 131 | 132 | 133 | # 2018-07-09 134 | * Updated packages, angular 6.0.7, .NET Core 2.1.1 135 | 136 | 137 | # 2018-05-31 138 | * Updated packages, angular 6.0.3, .NET Core 2.1.0 139 | 140 | 141 | # 2018-05-04 142 | * Updated packages, angular 6.0.0, .NET 2.0.7 143 | 144 | 145 | # 2018-03-14 146 | * Updated packages, angular 5.2.8, .NET 2.0.6 147 | 148 | 149 | 150 | # 2018-02-23 151 | * Updated packages 152 | 153 | 154 | # 2017-11-02 155 | * Updated Angular 5 156 | 157 | 158 | # ...coming soon 159 | * Updated Angular 5 160 | 161 | 162 | # 2017-10-15 163 | * Updated Angular 4.4.5 164 | 165 | 166 | # 2017-10-02 167 | * Updated Angular 4.4.4 168 | 169 | 170 | # 2017-09-16 171 | * Updated Angular 4.4.1 172 | * support for dotnet templates 173 | 174 | 175 | # 2017-08-15 176 | * Update ASP.NET Core 2.0 177 | 178 | 179 | # 2017-07-20 180 | * Release 1.0.0: Angular 4.3.1, typescript 2.4.2, webpack 3.3.0 181 | * Updated versions 182 | 183 | 184 | # 2017-07-15 185 | * Updating angular 4.3.0 186 | * Updated to Webpack 3 187 | * @ngtools/webpack 188 | 189 | 190 | # 2017-06-23 191 | * Updating angular 4.2.4 192 | 193 | 194 | # 2017-06-13 195 | * Updating angular 4.2.2 196 | 197 | 198 | # 2017-06-10 199 | * Updating angular 4.2.1 200 | * Updating dotnet packages 201 | 202 | 203 | # 2017-05-26 204 | * Updating angular 4.1.3 205 | * Updating dotnet packages 206 | 207 | 208 | # 2017-05-17 209 | * Updating angular 4.1.2 210 | 211 | 212 | # 2017-04-30 213 | * Updating angular 4.1.0 214 | 215 | 216 | 217 | # 2017-04.10 218 | * Added Angular test 219 | 220 | 221 | # 2017-04.08 222 | * Updated angular 4.0.1 223 | * Added XUnit test for API 224 | 225 | 226 | # 2017-03.24 227 | * Updated angular 4.0.0 228 | 229 | 230 | # 2017-03.18 231 | * Updated to 2.4.10 and 4.0.0-rc.4 232 | 233 | 234 | # 2017-03.03 235 | * Updated to 2.4.9 and 4.0.0-rc.2 236 | 237 | 238 | # 2017-02.16 239 | * Updated typescript, awesome-typescript-loader and @types/node 240 | 241 | 242 | # 2017-02.05 243 | * Updated npm packages 244 | 245 | 246 | # 2017-02.01 247 | * Added support for Hot Module Replacement 248 | 249 | 250 | # 2017-01-18 251 | * Updated to Webpack 2.2.0 252 | 253 | 254 | # 2017-01-14 255 | * Support and documentation for Angular 2 lazy loading 256 | * Updated to Angular 2.4.3 257 | * Updated to webpack 2.2.0-rc.4 258 | * Updated npm packages for build 259 | 260 | 261 | # 2017-01-04 262 | * Added tslint 263 | 264 | 265 | # 2017-01-01 266 | * Updated to Angular 2.4.1 267 | * Updated to webpack 2.2.0-rc.3 268 | * Added new npm scripts to replace webpack task runner 269 | * Added VS2017 version 270 | 271 | 272 | # 2016-12-31 273 | * New Design 274 | * Better ASP.NET Core WebAPI with CRUD operations 275 | * Added Forms to talk to the WebAPI 276 | * Added favicon 277 | * Updated readme.md 278 | * Introduced Modules with own routing and better folder structure 279 | * Happy new year everybody 280 | 281 | 282 | # 2016-12-20 283 | * Updated to Angular 2.4.0 284 | 285 | 286 | # 2016-11-16 287 | * Updated to Angular 2.2.0 288 | 289 | 290 | # 2016-10-24 291 | * Using AoT 292 | * Using Tree shaking 293 | * Updated to webpack 2 294 | * switches to @types ==> removed tsd & typings 295 | 296 | 297 | # 2016-10-16 298 | * Updated to Angular 2.1.0 299 | * typings 300 | * Webpack SASS build 301 | 302 | 303 | # 2016-10-01 304 | * Updated to Angular 2.0.1 305 | * typings 306 | 307 | 308 | # 2016-09-15 309 | * Updated to Angular2 release and ASP.NET Core 1.0.1 310 | 311 | 312 | # 2016-09-03 313 | * Updated to Angular2 RC.6 314 | 315 | 316 | # 2016-08-12 317 | * Updated to Angular2 RC.5 318 | * Split webpack file 319 | 320 | 321 | # 2016-07-02 322 | * Updated to Angular2 RC.4 323 | 324 | 325 | # 2016-06-29 326 | * Updated to ASP.NET Core RTM 327 | 328 | 329 | # 2016-06-26 330 | * Updated to Angular 2 rc.3 331 | * New routing 332 | 333 | 334 | # 2016-06-17 335 | * Updated to Angular 2 RC.2 336 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Damien Bowden, Roberto Simonetti, Fabian Gosebrink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Visual Studio Webpack Starter 2 | [![Build status](https://ci.appveyor.com/api/projects/status/3x6y01a8312x6o2p?svg=true)](https://ci.appveyor.com/project/damienbod/angular2webpackvisualstudio) 3 | 4 | >Template for [Webpack](https://webpack.js.org/concepts/), [Visual Studio](https://www.visualstudio.com/), [ASP.NET Core](https://docs.microsoft.com/en-us/dotnet/core/) and [Angular](https://angular.io/). Both the client and the server side of the application are implemented inside one ASP.NET Core project which makes it easier to deploy. 5 | 6 | ![vs_webpack_angular2](https://damienbod.files.wordpress.com/2016/06/vs_webpack_angular2.png?w=600) 7 | 8 | ## Features 9 | - Angular [AoT compilation](https://angular.io/guide/aot-compiler) 10 | - Angular [Lazy-loading modules with the router](https://angular.io/guide/ngmodule#lazy-loading-modules-with-the-router) 11 | - Angular [Style Guide](https://angular.io/guide/styleguide) 12 | - Webpack [Hot Module Replacement](https://webpack.js.org/guides/hot-module-replacement/) 13 | - Webpack [DevServer](https://webpack.js.org/configuration/dev-server/) 14 | - Development & Production builds 15 | - SASS, CSS 16 | - Testing client using _Jasmine_ and _Karma_ 17 | - Testing server usign _xUnit_ 18 | - _Yarn_ & _npm 5_ 19 | 20 | ## Authors 21 | Fabian GosebrinkDamien BowdenRoberto Simonetti 22 | 23 | _[Fabian Gosebrink](https://twitter.com/FabianGosebrink), [Damien Bowden](https://twitter.com/damien_bod), [Roberto Simonetti](https://twitter.com/robisim74)_ 24 | 25 | Blogs: 26 | - [damienbod.com](https://damienbod.com/2016/06/12/asp-net-core-angular2-with-webpack-and-visual-studio/) 27 | - [offering.solutions](http://offering.solutions//blog/articles/2016/06/12/asp-net-core-angular-2-webpack-visual-studio/) 28 | 29 | ## Table of contents 30 | * [Project structure](#1) 31 | * [Installing](#2) 32 | * [Running](#3) 33 | * [Commands](#3.1) 34 | * [Development](#3.2) 35 | * [Production](#3.3) 36 | * [Testing](#4) 37 | * [Dotnet Template](#5) 38 | * [Notes](#6) 39 | * [Links](#7) 40 | 41 | ## Project structure 42 | - **src** 43 | - **AngularWebpackVisualStudio** _ASP.NET Core Web API project_ 44 | - **.template.config** _Folder containing the template information about the dotnet new template_ 45 | - **wwwroot** _Root for Angular application deployment_ 46 | - **angularApp** _Angular application_ 47 | - **main.ts** _Entry point for JiT compilation_ 48 | - **main-aot.ts** _Entry point for AoT compilation_ 49 | - **tests** _Client tests_ 50 | - **config** _Folder for configuration files_ 51 | - **webpack.dev.js** _webpack configuration file for development_ 52 | - **webpack.prod.js** _webpack configuration file for production_ 53 | - **webpack.test.js** _webpack configuration file for testing_ 54 | - **spec.bundle.js** _Used for client testing_ 55 | - **Controllers** _Folder for API controllers_ 56 | - **Models** _Folder for models_ 57 | - **Startup.cs** _Web API configuration_ 58 | - **package.json** _Packages for Angular app_ 59 | - **karma.conf.js** _Karma configuration for client testing_ 60 | - **tsconfig.json** & **tsconfig-aot.json** _TypeScript & ngc compiler options_ 61 | - **webpack.config.js** _Webpack configuration file for development & production of Angular app_ 62 | - **tests** 63 | - **AngularWebpackVisualStudio_Tests** _API tests_ 64 | 65 | ## Installing 66 | Requirements: 67 | - At least [.NET Core 2.0.0](https://www.microsoft.com/net/download/core) 68 | - At least _node 6.9_ and _npm 4_ 69 | 70 | #### Yarn 71 | You can use this template also with [yarn](https://yarnpkg.com/en/docs/install). 72 | 73 | #### Visual Studio 74 | The installed _nodejs_ on your system needs to be used inside Visual Studio and not the _nodejs_ from Visual Studio. You need to set the path of your node before the VS node. 75 | 76 | In Visual Studio: _Tools -> Options -> Projects and Solutions -> Web Package Management -> External Web Tools_ 77 | 78 | Move the _$(Path)_ option above the Visual Studio one. 79 | 80 | #### NPM Task Runner 81 | The _NPM Task Runner_ can be used to build the client application from inside Visual Studio. This task runner can be downloaded from: 82 | 83 | https://marketplace.visualstudio.com/items?itemName=MadsKristensen.NPMTaskRunner 84 | 85 | ## Running 86 | The ASP.NET Core application contains both the server side API services and also hosts the Angular client application. The source code for the Angular application is implemented in the _angularApp_ folder. Webpack is then used to deploy the application, using the development build or a production build, which deploys the application to the wwwroot folder. This makes it easy to deploy the application using the standard tools from Visual Studio with the standard configurations. 87 | 88 | ### Commands 89 | The npm scripts are used to build, watch the client application as required. The scripts can be run from the command line or the _NPM Task Runner_. 90 | 91 | The _watch-webpack-dev_ npm script automatically starts in Visual Studio because it has been added to the _package.json_: 92 | ``` 93 | "-vs-binding": { "ProjectOpened": [ "watch-webpack-dev" ] } 94 | ``` 95 | 96 | All available commands are the following: 97 | ``` 98 | "start": "concurrently \"webpack-dev-server --env=dev --open --hot --inline --port 8080\" \"dotnet run\" ", 99 | "webpack-dev": "webpack --env=dev", 100 | "webpack-production": "webpack --env=prod", 101 | "build-dev": "npm run webpack-dev", 102 | "build-production": "npm run webpack-production", 103 | "watch-webpack-dev": "webpack --env=dev --watch --color", 104 | "watch-webpack-production": "npm run build-production --watch --color", 105 | "publish-for-iis": "npm run build-production && dotnet publish -c Release", 106 | "test": "karma start", 107 | "test-ci": "karma start --single-run --browsers ChromeHeadless", 108 | "lint": "tslint ./angularApp" 109 | ``` 110 | 111 | ### Development 112 | For the Angular app, we use _JiT compilation_. 113 | ``` 114 | npm run build-dev 115 | ``` 116 | #### Watch for development 117 | ``` 118 | npm run watch-webpack-dev 119 | ``` 120 | #### Hot Module Replacement 121 | ``` 122 | npm start 123 | ``` 124 | 125 | ### Production 126 | For the Angular app, we use _AoT compilation_, tree shaking & minification. 127 | ``` 128 | npm run webpack-production 129 | ``` 130 | 131 | ## Testing 132 | The _xUnit_ test for ASP.NET Core API is in _tests/AngularWebpackVisualStudio_Tests_ folder: 133 | ``` 134 | dotnet test 135 | ``` 136 | or from Visual Studio: _Test -> Run -> All Tests_ 137 | 138 | See this link for more details on _xUnit_ testing in ASP.NET Core: https://docs.microsoft.com/it-it/dotnet/articles/core/testing/unit-testing-with-dotnet-test 139 | 140 | The Angular test is in _angularApp/tests_ folder. It uses _Karma_ test runner and _Jasmine_ test framework: 141 | ``` 142 | npm test 143 | ``` 144 | 145 | runs the tests and watches for development. If you want to run the tests with a headless browser only one single time just type 146 | ``` 147 | npm run test-ci 148 | ``` 149 | 150 | See this link for more details on Angular testing: https://angular.io/guide/testing 151 | 152 | ## Dotnet Template 153 | To install a template for this package we prepared a `template.json` to do that. 154 | 155 | Just run `dotnet new --install ` where is the path to the folder where the `.template.config` folder lives. 156 | 157 | After that you should see the template when running `dotnet new` on commandline 158 | 159 | ![dotnetnew](.github/dotnet-new.jpg "dotnetnew") 160 | 161 | Now you can use the temaplte with `dotnet new angularwebapi` 162 | 163 | 164 | ## Notes 165 | The Webpack configuration could also build all of the scss and css files to a separate _app.css_ or _app."hash".css_ which could be loaded as a single file in the distribution. Some of the vendor js and css could also be loaded directly in the html header using the _index.html_ file and not included in the Webpack build. 166 | 167 | ## Links 168 | - [Lazy Loading](https://github.com/damienbod/Angular2WebpackVisualStudio/tree/master/docs/LAZY_LOADING.md) 169 | - [Hot Module Replacement](https://github.com/damienbod/Angular2WebpackVisualStudio/tree/master/docs/HMR.md) 170 | 171 | - [Building production ready Angular apps with Visual Studio and ASP.NET Core](https://damienbod.com/2017/01/01/building-production-ready-angular-apps-with-visual-studio-and-asp-net-core/) 172 | 173 | ## License 174 | MIT 175 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2019 2 | init: 3 | - git config --global core.autocrlf true 4 | environment: 5 | nodejs_version: "12" 6 | install: 7 | - ECHO %APPVEYOR_BUILD_WORKER_IMAGE% 8 | - ps: Install-Product node $env:nodejs_version 9 | - cmd: choco install dotnetcore-sdk --pre 10 | - dotnet --version 11 | - dotnet restore 12 | - choco install googlechrome --ignore-checksums 13 | build_script: 14 | - dotnet build 15 | - npm -g install npm@latest 16 | - cd src\AngularWebpackVisualStudio 17 | - npm install 18 | - npm run build-production 19 | - npm run build-dev 20 | before_build: 21 | - appveyor-retry dotnet restore -v Minimal 22 | test_script: 23 | - npm run test-ci 24 | - cd C:\projects\angular2webpackvisualstudio\tests\AngularWebpackVisualStudio_Tests 25 | - dotnet test 26 | -------------------------------------------------------------------------------- /docs/HMR.md: -------------------------------------------------------------------------------- 1 | # Hot Module Replacement 2 | 3 | This article shows how HMR, or Hot Module Replacement can be used together with Angular and Webpack. 4 | 5 | Code VS2017 angular 4.x 6 | 7 | 13 | 14 | ## package.json npm file 15 | 16 | The webpack-dev-server from Kees Kluskens is added to the devDependencies in the npm package.json file. The webpack-dev-server package implements and supports the HMR feature. 17 | ```javascript 18 | "devDependencies": { 19 | ... 20 | "webpack": "^3.2.0", 21 | "webpack-dev-server": "^2.5.1", 22 | }, 23 | ``` 24 | 25 | In the scripts section of the package.json, the start command is configured to start the dotnet server and also the webpack-dev-server with the --hot and the --inline parameters. 26 | 27 | See the webpack-dev-server documentation for more information about the possible parameters. 28 | 29 | The dotnet server is only required because this demo application uses a Web API service implemented in ASP.NET Core. 30 | 31 | ```javascript 32 | "start": "concurrently \"webpack-dev-server --hot --inline --port 8080\" \"dotnet run\" " 33 | ``` 34 | 35 | ## webpack dev configuration 36 | 37 | The devServer is added to the module.exports in the webpack.dev.js. This configures the webpack-dev-server as required. The webpack-dev-server configuration can be set here as well as the command line options, so you as a developer can decide which is better for you. 38 | ```javascript 39 | devServer: { 40 | historyApiFallback: true, 41 | contentBase: path.join(__dirname, '/wwwroot/'), 42 | watchOptions: { 43 | aggregateTimeout: 300, 44 | poll: 1000 45 | } 46 | }, 47 | ``` 48 | 49 | The output in the module.exports also needs to be configured correctly for the webpack-dev-server to work correctly. If the './' path is used in the path option of the output section, the webpack-dev-server will not start. 50 | ```javascript 51 | output: { 52 | path: __dirname + '/wwwroot/', 53 | filename: 'dist/[name].bundle.js', 54 | chunkFilename: 'dist/[id].chunk.js', 55 | publicPath: '/' 56 | }, 57 | ``` 58 | 59 | ## Running the application 60 | 61 | Build the application using the webpack dev build. This can be done in the command line. Before building, you need to install all the npm packages using npm install. 62 | ```javascript 63 | $ npm run build-dev 64 | ``` 65 | 66 | The npm script build-dev is defined in the package.json file and uses the webpack-dev script which does a development build. 67 | ```javascript 68 | "build-dev": "npm run webpack-dev", 69 | "webpack-dev": "set NODE_ENV=development && webpack", 70 | ``` 71 | 72 | Now the server can be started using the start script. 73 | ```javascript 74 | $ npm start 75 | ``` 76 | 77 | hmr_angular_01 78 | 79 | The application is now running on localhost with port 8080 as defined. 80 | 81 | http://localhost:8080/home 82 | 83 | If for example, the color is changed in the app.scss, the bundles will be reloaded in the browser without refreshing. 84 | hmr_angular2_03 85 | 86 | ## Links 87 | 88 | https://webpack.js.org/concepts/hot-module-replacement/ 89 | 90 | https://webpack.js.org/configuration/dev-server/#devserver 91 | 92 | https://github.com/webpack/webpack-dev-server 93 | 94 | https://www.sitepoint.com/beginners-guide-to-webpack-2-and-module-bundling/ 95 | 96 | https://medium.com/@rajaraodv/webpack-hot-module-replacement-hmr-e756a726a07 97 | -------------------------------------------------------------------------------- /docs/LAZY_LOADING.md: -------------------------------------------------------------------------------- 1 | 2 | # Angular Lazy Loading with Webpack 3 3 | 4 | This documentation shows how Angular lazy loading can be supported using Webpack 3 for both JIT and AOT builds. The Webpack loader angular-router-loader from Brandon Roberts is used to implement this. 5 | 6 | A big thanks to Roberto Simonetti for his help in this. 7 | 8 | 9 | Code VS2017 angular 4.x 10 | 11 | 12 | 18 | 19 | ## First create an Angular module 20 | 21 | In this example, the about module will be lazy loaded when the user clicks on the about tab. The about.module.ts is the entry point for this feature. The module has its own component and routing. 22 | The app will now be setup to lazy load the AboutModule. 23 | 24 | ```javascript 25 | import { NgModule } from '@angular/core'; 26 | import { CommonModule } from '@angular/common'; 27 | 28 | import { AboutRoutes } from './about.routes'; 29 | import { AboutComponent } from './components/about.component'; 30 | 31 | @NgModule({ 32 | imports: [ 33 | CommonModule, 34 | AboutRoutes 35 | ], 36 | 37 | declarations: [ 38 | AboutComponent 39 | ], 40 | 41 | }) 42 | 43 | export class AboutModule { } 44 | ``` 45 | 46 | ## Add the angular-router-loader Webpack loader to the packages.json file 47 | 48 | To add lazy loading to the app, the angular-router-loader npm package needs to be added to the packages.json npm file in the devDependencies. 49 | 50 | ```javascript 51 | "devDependencies": { 52 | "@types/node": "8.0.12", 53 | "angular2-template-loader": "^0.6.0", 54 | "angular-router-loader": "^0.5.0", 55 | ``` 56 | 57 | ## Configure the Angular routing 58 | 59 | The lazy loading routing can be added to the app.routes.ts file. The loadChildren defines the module and the class name of the module which can be lazy loaded. It is also possible to pre-load lazy load modules if required. 60 | 61 | ```javascript 62 | import { Routes, RouterModule } from '@angular/router'; 63 | 64 | export const routes: Routes = [ 65 | { path: '', redirectTo: 'home', pathMatch: 'full' }, 66 | { 67 | path: 'about', loadChildren: './modules/about/about.module#AboutModule', 68 | } 69 | ]; 70 | 71 | export const AppRoutes = RouterModule.forRoot(routes); 72 | 73 | ``` 74 | 75 | ## Update the tsconfig-aot.json and tsconfig.json files 76 | 77 | Now the tsconfig.json for development JIT builds and the tsconfig-aot.json for AOT production builds need to be configured to load the AboutModule module. 78 | 79 | AOT production build 80 | 81 | The files property contains all the module entry points as well as the app entry file. The angularCompilerOptions property defines the folder where the AOT will be built into. This must match the configuration in the Webpack production config file. 82 | 83 | ```javascript 84 | { 85 | "compilerOptions": { 86 | "target": "es5", 87 | "module": "es2015", 88 | "moduleResolution": "node", 89 | "sourceMap": false, 90 | "emitDecoratorMetadata": true, 91 | "experimentalDecorators": true, 92 | "removeComments": true, 93 | "noImplicitAny": true, 94 | "suppressImplicitAnyIndexErrors": true, 95 | "skipLibCheck": true, 96 | "lib": [ 97 | "es2015", 98 | "dom" 99 | ] 100 | }, 101 | "angularCompilerOptions": { 102 | "genDir": "./aot", 103 | "entryModule": "./angularApp/app/app.module#AppModule", 104 | "skipMetadataEmit": true 105 | }, 106 | "compileOnSave": false, 107 | "buildOnSave": false 108 | } 109 | ``` 110 | 111 | JIT development build 112 | 113 | The modules and entry points are also defined for the JIT build. 114 | 115 | ```javascript 116 | { 117 | "compilerOptions": { 118 | "target": "es5", 119 | "module": "es2015", 120 | "moduleResolution": "node", 121 | "sourceMap": true, 122 | "emitDecoratorMetadata": true, 123 | "experimentalDecorators": true, 124 | "removeComments": true, 125 | "noImplicitAny": true, 126 | "skipLibCheck": true, 127 | "lib": [ 128 | "es2015", 129 | "dom" 130 | ], 131 | "typeRoots": [ 132 | "./node_modules/@types/" 133 | ] 134 | }, 135 | "exclude": [ 136 | "node_modules", 137 | "angularApp/main-aot.ts" 138 | ], 139 | "awesomeTypescriptLoaderOptions": { 140 | "useWebpackText": true 141 | }, 142 | "compileOnSave": false, 143 | "buildOnSave": false 144 | } 145 | 146 | 147 | ``` 148 | 149 | ## Configure Webpack to chunk and use the router lazy loading 150 | 151 | Now the webpack configuration needs to be updated for the lazy loading. 152 | 153 | AOT production build 154 | 155 | The webpack.prod.js file requires that the chunkFilename property is set in the output, so that webpack chunks the lazy load modules. 156 | 157 | ```javascript 158 | output: { 159 | path: './wwwroot/', 160 | filename: 'dist/[name].[hash].bundle.js', 161 | chunkFilename: 'dist/[id].[hash].chunk.js', 162 | publicPath: '/' 163 | }, 164 | ``` 165 | 166 | The angular-router-loader is added to the loaders. The genDir folder defined here must match the definition in tsconfig-aot.json. 167 | 168 | ```javascript 169 | module: { 170 | rules: [ 171 | { 172 | test: /\.ts$/, 173 | loaders: [ 174 | 'awesome-typescript-loader', 175 | 'angular-router-loader?aot=true&genDir=aot/' 176 | ] 177 | }, 178 | ``` 179 | 180 | JIT development build 181 | 182 | The webpack.dev.js file requires that the chunkFilename property is set in the output, so that webpack chunks the lazy load modules. 183 | 184 | ```javascript 185 | output: { 186 | path: './wwwroot/', 187 | filename: 'dist/[name].bundle.js', 188 | chunkFilename: 'dist/[id].chunk.js', 189 | publicPath: '/' 190 | }, 191 | ``` 192 | 193 | The angular-router-loader is added to the loaders. 194 | 195 | ```javascript 196 | module: { 197 | rules: [ 198 | { 199 | test: /\.ts$/, 200 | loaders: [ 201 | 'awesome-typescript-loader', 202 | 'angular-router-loader', 203 | 'angular2-template-loader', 204 | 'source-map-loader', 205 | 'tslint-loader' 206 | ] 207 | }, 208 | ``` 209 | 210 | ## Build and run 211 | 212 | Now the application can be built using the npm build scripts and the dotnet command tool. 213 | 214 | Open a command line in the root of the src files. Install the npm packages: 215 | 216 | ```javascript 217 | npm install 218 | ``` 219 | 220 | Now build the production build. The build-production does a ngc build, and then a webpack production build. 221 | 222 | ```javascript 223 | npm run build-production 224 | ``` 225 | 226 | You can see that Webpack creates an extra chunked file for the About Module. 227 | 228 | lazyloadingwebpack_01 229 | 230 | Then start the application. The server is implemented using ASP.NET Core 1.1. 231 | 232 | ```javascript 233 | dotnet run 234 | ``` 235 | 236 | When the application is started, the AboutModule is not loaded. 237 | 238 | lazyloadingwebpack_02 239 | 240 | When the about tab is clicked, the chunked AboutModule is loaded. 241 | 242 | lazyloadingwebpack_03 243 | 244 | Absolutely fantastic. You could also pre-load the modules if required. See this blog. 245 | 246 | Links: 247 | 248 | https://github.com/brandonroberts/angular-router-loader 249 | 250 | https://www.npmjs.com/package/angular-router-loader 251 | 252 | https://vsavkin.com/angular-router-preloading-modules-ba3c75e424cb 253 | 254 | https://webpack.github.io/docs/ 255 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | .template.config 5 | # don't lint nyc coverage output 6 | bin 7 | obj 8 | wwwroot 9 | config -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | parserOptions: { 5 | tsconfigRootDir: __dirname, 6 | project: ['./tsconfig.json', './tsconfig-aot.json'], 7 | }, 8 | plugins: [ 9 | '@typescript-eslint', 10 | ], 11 | extends: [ 12 | 'eslint:recommended', 13 | 'plugin:@typescript-eslint/eslint-recommended', 14 | 'plugin:@typescript-eslint/recommended', 15 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', 16 | ], 17 | }; -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Damien Bowden, Roberto Simonetti, Fabian Gosebrink", 3 | "classifications": [ "Web", "SPA", "Angular" ], 4 | "name": "ASP.NET Core with Angular and Webpack", 5 | "identity": "AngularWebpackVisualStudio", 6 | "shortName": "angularwebapi", 7 | "tags": { 8 | "language": "C#" 9 | }, 10 | "sourceName": "AngularWebpackVisualStudio", 11 | "preferNameDirectory" : "true" 12 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (web)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}\\bin\\Debug\\netcoreapp1.1\\Angular2WebpackVisualStudio.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false, 13 | "internalConsoleOptions": "openOnSessionStart", 14 | "launchBrowser": { 15 | "enabled": true, 16 | "args": "${auto-detect-url}", 17 | "windows": { 18 | "command": "cmd.exe", 19 | "args": "/C start ${auto-detect-url}" 20 | }, 21 | "osx": { 22 | "command": "open" 23 | }, 24 | "linux": { 25 | "command": "xdg-open" 26 | } 27 | }, 28 | "env": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | }, 31 | "sourceFileMap": { 32 | "/Views": "${workspaceRoot}/Views" 33 | } 34 | }, 35 | { 36 | "name": ".NET Core Attach", 37 | "type": "coreclr", 38 | "request": "attach", 39 | "processId": "${command.pickProcess}" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [ 10 | "${workspaceRoot}\\project.json" 11 | ], 12 | "isBuildCommand": true, 13 | "problemMatcher": "$msCompile" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/AngularWebpackVisualStudio.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net5.0 4 | 4.0 5 | 8.0.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Controllers/ThingsController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using AngularWebpackVisualStudio.Models; 3 | using AngularWebpackVisualStudio.Repositories.Things; 4 | using Microsoft.AspNetCore.JsonPatch; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace AngularWebpackVisualStudio.Controller 8 | { 9 | [Route("api/[controller]")] 10 | public class ThingsController : Microsoft.AspNetCore.Mvc.Controller 11 | { 12 | private readonly IThingsRepository _thingsRepository; 13 | 14 | public ThingsController(IThingsRepository thingsRepository) 15 | { 16 | _thingsRepository = thingsRepository; 17 | } 18 | 19 | [HttpGet] 20 | public IActionResult Get() 21 | { 22 | return Ok(_thingsRepository.GetAll()); 23 | } 24 | 25 | [HttpPost] 26 | public IActionResult Add([FromBody] Thing thing) 27 | { 28 | if (thing == null) 29 | { 30 | return BadRequest(); 31 | } 32 | 33 | if (!ModelState.IsValid) 34 | { 35 | return BadRequest(ModelState); 36 | } 37 | 38 | Thing newThing = _thingsRepository.Add(thing); 39 | 40 | return CreatedAtRoute("GetSingleThing", new { id = newThing.Id }, newThing); 41 | } 42 | 43 | [HttpPatch("{id:int}")] 44 | public IActionResult PartiallyUpdate(int id, [FromBody] JsonPatchDocument patchDoc) 45 | { 46 | if (patchDoc == null) 47 | { 48 | return BadRequest(); 49 | } 50 | 51 | Thing existingEntity = _thingsRepository.GetSingle(id); 52 | 53 | if (existingEntity == null) 54 | { 55 | return NotFound(); 56 | } 57 | 58 | Thing thing = existingEntity; 59 | patchDoc.ApplyTo(thing, ModelState); 60 | 61 | if (!ModelState.IsValid) 62 | { 63 | return BadRequest(ModelState); 64 | } 65 | 66 | Thing updatedThing = _thingsRepository.Update(id, thing); 67 | 68 | return Ok(updatedThing); 69 | } 70 | 71 | [HttpGet] 72 | [Route("{id:int}", Name = "GetSingleThing")] 73 | public IActionResult Single(int id) 74 | { 75 | Thing thing = _thingsRepository.GetSingle(id); 76 | 77 | if (thing == null) 78 | { 79 | return NotFound(); 80 | } 81 | 82 | return Ok(thing); 83 | } 84 | 85 | [HttpDelete] 86 | [Route("{id:int}")] 87 | public IActionResult Remove(int id) 88 | { 89 | Thing thing = _thingsRepository.GetSingle(id); 90 | 91 | if (thing == null) 92 | { 93 | return NotFound(); 94 | } 95 | 96 | _thingsRepository.Delete(id); 97 | return NoContent(); 98 | } 99 | 100 | [HttpPut] 101 | [Route("{id:int}")] 102 | public IActionResult Update(int id, [FromBody] Thing thing) 103 | { 104 | var thingToCheck = _thingsRepository.GetSingle(id); 105 | 106 | if (thingToCheck == null) 107 | { 108 | return NotFound(); 109 | } 110 | 111 | if (id != thing.Id) 112 | { 113 | return BadRequest("Ids do not match"); 114 | } 115 | 116 | if (!ModelState.IsValid) 117 | { 118 | return BadRequest(ModelState); 119 | } 120 | 121 | Thing updatedThing = _thingsRepository.Update(id, thing); 122 | 123 | return Ok(updatedThing); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Models/Thing.cs: -------------------------------------------------------------------------------- 1 | namespace AngularWebpackVisualStudio.Models 2 | { 3 | public class Thing 4 | { 5 | public int Id { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | 5 | namespace AngularWebpackVisualStudio 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | CreateHostBuilder(args).Build().Run(); 12 | } 13 | 14 | public static IHostBuilder CreateHostBuilder(string[] args) => 15 | Host.CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(webBuilder => 17 | { 18 | webBuilder.UseStartup(); 19 | }); 20 | } 21 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:5000/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "index.html", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "Angular2WebpackVisualStudio": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "http://localhost:5000/", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Repositories/Things/IThingsRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using AngularWebpackVisualStudio.Models; 3 | 4 | namespace AngularWebpackVisualStudio.Repositories.Things 5 | { 6 | public interface IThingsRepository 7 | { 8 | Thing GetSingle(int id); 9 | Thing Add(Thing item); 10 | void Delete(int id); 11 | Thing Update(int id, Thing item); 12 | ICollection GetAll(); 13 | int Count(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Repositories/Things/ThingsRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using AngularWebpackVisualStudio.Models; 6 | 7 | namespace AngularWebpackVisualStudio.Repositories.Things 8 | { 9 | public class ThingsRepository : IThingsRepository 10 | { 11 | private readonly ConcurrentDictionary _storage = new ConcurrentDictionary(); 12 | 13 | public Thing GetSingle(int id) 14 | { 15 | Thing thing; 16 | return _storage.TryGetValue(id, out thing) ? thing : null; 17 | } 18 | 19 | public Thing Add(Thing item) 20 | { 21 | item.Id = !GetAll().Any() ? 1 : GetAll().Max(x => x.Id) + 1; 22 | 23 | if (_storage.TryAdd(item.Id, item)) 24 | { 25 | return item; 26 | } 27 | 28 | throw new Exception("Item could not be added"); 29 | } 30 | 31 | public void Delete(int id) 32 | { 33 | Thing thing; 34 | if (!_storage.TryRemove(id, out thing)) 35 | { 36 | throw new Exception("Item could not be removed"); 37 | } 38 | } 39 | 40 | public Thing Update(int id, Thing item) 41 | { 42 | _storage.TryUpdate(id, item, GetSingle(id)); 43 | return item; 44 | } 45 | 46 | public ICollection GetAll() 47 | { 48 | return _storage.Values; 49 | } 50 | 51 | public int Count() 52 | { 53 | return _storage.Count; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using AngularWebpackVisualStudio.Repositories.Things; 8 | 9 | namespace AngularWebpackVisualStudio 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddCors(options => 23 | { 24 | options.AddPolicy("AllowAllOrigins", 25 | builder => 26 | { 27 | builder 28 | .AllowAnyOrigin() 29 | .AllowAnyHeader() 30 | .AllowAnyMethod(); 31 | }); 32 | }); 33 | 34 | services.AddSingleton(); 35 | services.AddControllersWithViews(); 36 | } 37 | 38 | public void Configure(IApplicationBuilder app) 39 | { 40 | app.UseCors("AllowAllOrigins"); 41 | 42 | var angularRoutes = new[] { 43 | "/home", 44 | "/about" 45 | }; 46 | 47 | app.Use(async (context, next) => 48 | { 49 | if (context.Request.Path.HasValue && null != angularRoutes.FirstOrDefault( 50 | (ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase))) 51 | { 52 | context.Request.Path = new PathString("/"); 53 | } 54 | 55 | await next(); 56 | }); 57 | 58 | app.UseDefaultFiles(); 59 | app.UseStaticFiles(); 60 | 61 | app.UseRouting(); 62 | 63 | app.UseEndpoints(endpoints => 64 | { 65 | endpoints.MapControllerRoute( 66 | name: "default", 67 | pattern: "{controller=Home}/{action=Index}/{id?}"); 68 | }); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/about/about.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AboutRoutes } from './about.routes'; 5 | import { AboutComponent } from './components/about.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | AboutRoutes 11 | ], 12 | 13 | declarations: [ 14 | AboutComponent 15 | ], 16 | 17 | }) 18 | 19 | export class AboutModule { } 20 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/about/about.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule, Routes } from '@angular/router'; 2 | 3 | import { AboutComponent } from './components/about.component'; 4 | 5 | const routes: Routes = [ 6 | { path: '', component: AboutComponent } 7 | ]; 8 | 9 | export const AboutRoutes = RouterModule.forChild(routes); 10 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/about/components/about.component.html: -------------------------------------------------------------------------------- 1 | 
2 |

3 | {{message}} 4 |

5 |
-------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/about/components/about.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-about-component', 5 | templateUrl: './about.component.html' 6 | }) 7 | 8 | export class AboutComponent { 9 | 10 | message: string; 11 | 12 | constructor() { 13 | this.message = 'Hello from AboutComponent constructor'; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.component.html: -------------------------------------------------------------------------------- 1 |  2 |
3 | 4 |
5 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .navigationLinkButton:hover { 2 | cursor: pointer; 3 | } 4 | 5 | a { 6 | color: #03a9f4; 7 | } 8 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ViewEncapsulation } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-component', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'], 7 | encapsulation: ViewEncapsulation.None 8 | }) 9 | 10 | export class AppComponent { } 11 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.constants.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class Configuration { 5 | public Server = 'http://localhost:5000/'; 6 | } 7 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { AppRoutes } from './app.routes'; 6 | import { CoreModule } from './core/core.module'; 7 | import { HomeModule } from './home/home.module'; 8 | import { SharedModule } from './shared/shared.module'; 9 | 10 | @NgModule({ 11 | imports: [ 12 | BrowserModule, 13 | AppRoutes, 14 | SharedModule, 15 | CoreModule.forRoot(), 16 | HomeModule 17 | ], 18 | 19 | declarations: [ 20 | AppComponent 21 | ], 22 | 23 | bootstrap: [AppComponent], 24 | }) 25 | 26 | export class AppModule { } 27 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule, Routes } from '@angular/router'; 2 | 3 | export const routes: Routes = [ 4 | { path: '', redirectTo: 'home', pathMatch: 'full' }, 5 | { path: 'about', loadChildren: './about/about.module#AboutModule'} 6 | ]; 7 | 8 | export const AppRoutes = RouterModule.forRoot(routes); 9 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | 4 | import { Configuration } from '../app.constants'; 5 | import { ThingService } from './services/thing-data.service'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule 10 | ] 11 | }) 12 | 13 | export class CoreModule { 14 | static forRoot(): ModuleWithProviders { 15 | return { 16 | ngModule: CoreModule, 17 | providers: [ 18 | ThingService, 19 | Configuration 20 | ] 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/core/services/thing-data.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpHeaders } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | 5 | import { Configuration } from './../../app.constants'; 6 | import { Thing } from './../../models/thing'; 7 | 8 | @Injectable() 9 | export class ThingService { 10 | 11 | private actionUrl: string; 12 | private headers: HttpHeaders; 13 | 14 | constructor(private http: HttpClient, configuration: Configuration) { 15 | 16 | this.actionUrl = configuration.Server + 'api/things/'; 17 | 18 | this.headers = new HttpHeaders(); 19 | this.headers = this.headers.set('Content-Type', 'application/json'); 20 | this.headers = this.headers.set('Accept', 'application/json'); 21 | } 22 | 23 | getAll(): Observable { 24 | return this.http.get(this.actionUrl, { headers: this.headers }); 25 | } 26 | 27 | getSingle(id: number): Observable { 28 | return this.http.get(this.actionUrl + id, { headers: this.headers }); 29 | } 30 | 31 | add(thingToAdd: Thing): Observable { 32 | const toAdd = JSON.stringify({ name: thingToAdd.name }); 33 | 34 | return this.http.post(this.actionUrl, toAdd, { headers: this.headers }); 35 | } 36 | 37 | update(id: number, itemToUpdate: Thing): Observable { 38 | return this.http 39 | .put(this.actionUrl + id, JSON.stringify(itemToUpdate), { headers: this.headers }); 40 | } 41 | 42 | delete(id: number): Observable { 43 | return this.http.delete(this.actionUrl + id, { headers: this.headers }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/home/components/home.component.html: -------------------------------------------------------------------------------- 1 | 
2 |

3 | {{message}} 4 |

5 |
6 |
7 |
8 |
9 |
10 | 11 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 |
#Name 
{{i + 1}}{{thing.name}} 35 | 36 |
40 |
41 |
42 |
43 |
44 |
45 | No items found 46 |
47 |
48 |
-------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/home/components/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { ThingService } from './../../core/services/thing-data.service'; 4 | import { Thing } from './../../models/thing'; 5 | 6 | @Component({ 7 | selector: 'app-home-component', 8 | templateUrl: './home.component.html' 9 | }) 10 | export class HomeComponent implements OnInit { 11 | message: string; 12 | things: Thing[] = []; 13 | thing: Thing = new Thing(); 14 | 15 | constructor(private dataService: ThingService) { 16 | this.message = 'Things from the ASP.NET Core API'; 17 | } 18 | 19 | ngOnInit(): void { 20 | this.getAllThings(); 21 | } 22 | 23 | addThing(): void { 24 | this.dataService.add(this.thing).subscribe( 25 | () => { 26 | this.getAllThings(); 27 | this.thing = new Thing(); 28 | }, 29 | error => { 30 | console.log(error); 31 | } 32 | ); 33 | } 34 | 35 | deleteThing(thing: Thing): void { 36 | this.dataService.delete(thing.id).subscribe( 37 | () => { 38 | this.getAllThings(); 39 | }, 40 | error => { 41 | console.log(error); 42 | } 43 | ); 44 | } 45 | 46 | private getAllThings(): void { 47 | this.dataService 48 | .getAll() 49 | .subscribe( 50 | data => (this.things = data), 51 | error => console.log(error), 52 | () => console.log('Get all complete') 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { HttpClientModule } from '@angular/common/http'; 3 | import { NgModule } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | 6 | import { HomeComponent } from './components/home.component'; 7 | import { HomeRoutes } from './home.routes'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | FormsModule, 13 | HttpClientModule, 14 | HomeRoutes 15 | ], 16 | 17 | declarations: [ 18 | HomeComponent 19 | ], 20 | 21 | exports: [ 22 | HomeComponent 23 | ] 24 | }) 25 | 26 | export class HomeModule { } 27 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/home/home.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule, Routes } from '@angular/router'; 2 | 3 | import { HomeComponent } from './components/home.component'; 4 | 5 | const routes: Routes = [ 6 | { path: 'home', component: HomeComponent } 7 | ]; 8 | 9 | export const HomeRoutes = RouterModule.forChild(routes); 10 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/models/thing.ts: -------------------------------------------------------------------------------- 1 | export class Thing { 2 | public id = 0; 3 | public name = ''; 4 | } 5 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/shared/components/customfooter/customfooter.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/shared/components/customfooter/customfooter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-custom-footer', 5 | templateUrl: './customfooter.component.html' 6 | }) 7 | 8 | export class CustomFooterComponent { 9 | currentYear: number = new Date().getFullYear(); 10 | } 11 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/shared/components/navigation/navigation.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/shared/components/navigation/navigation.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-navigation', 5 | templateUrl: 'navigation.component.html' 6 | }) 7 | 8 | export class NavigationComponent { } 9 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | 5 | import { CustomFooterComponent } from './components/customfooter/customfooter.component'; 6 | import { NavigationComponent } from './components/navigation/navigation.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | RouterModule 12 | ], 13 | 14 | declarations: [ 15 | NavigationComponent, 16 | CustomFooterComponent 17 | ], 18 | 19 | exports: [ 20 | NavigationComponent, 21 | CustomFooterComponent 22 | ] 23 | }) 24 | 25 | export class SharedModule { } 26 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/images/RobertoSimonetti.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/src/AngularWebpackVisualStudio/angularApp/images/RobertoSimonetti.jpg -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/images/damienbod.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/src/AngularWebpackVisualStudio/angularApp/images/damienbod.jpg -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/images/fabianGosebrink.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/src/AngularWebpackVisualStudio/angularApp/images/fabianGosebrink.jpg -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Angular Webpack Template 8 | 9 | 10 | 11 | Loading... 12 | 13 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/main-aot.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import './styles.scss'; 3 | import 'zone.js'; 4 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 5 | // import { platformBrowser } from '@angular/platform-browser'; 6 | import { enableProdMode } from '@angular/core'; 7 | import { AppModule } from './app/app.module'; 8 | 9 | enableProdMode(); 10 | 11 | // Styles. 12 | // Enables Hot Module Replacement. 13 | declare var module: any; 14 | 15 | if (module.hot) { 16 | module.hot.accept(); 17 | } 18 | 19 | platformBrowserDynamic().bootstrapModule(AppModule); 20 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/main.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import './styles.scss'; 3 | import 'zone.js'; 4 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 5 | // import { platformBrowser } from '@angular/platform-browser'; 6 | 7 | import { AppModule } from './app/app.module'; 8 | 9 | // Styles. 10 | // Enables Hot Module Replacement. 11 | declare var module: any; 12 | 13 | if (module.hot) { 14 | module.hot.accept(); 15 | } 16 | 17 | platformBrowserDynamic().bootstrapModule(AppModule); 18 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/polyfills.ts: -------------------------------------------------------------------------------- 1 | import 'ie-shim'; // Internet Explorer 9 support. 2 | 3 | import 'core-js/es6/symbol'; 4 | import 'core-js/es6/object'; 5 | import 'core-js/es6/function'; 6 | import 'core-js/es6/parse-int'; 7 | import 'core-js/es6/parse-float'; 8 | import 'core-js/es6/number'; 9 | import 'core-js/es6/math'; 10 | import 'core-js/es6/string'; 11 | import 'core-js/es6/date'; 12 | import 'core-js/es6/array'; 13 | import 'core-js/es6/regexp'; 14 | import 'core-js/es6/map'; 15 | import 'core-js/es6/set'; 16 | import 'core-js/es6/weak-map'; 17 | import 'core-js/es6/weak-set'; 18 | import 'core-js/es6/typed'; 19 | import 'core-js/es6/reflect'; 20 | import 'core-js/es7/reflect'; 21 | 22 | import 'zone.js/dist/zone'; 23 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/styles.scss: -------------------------------------------------------------------------------- 1 | @import './styles/app.scss'; 2 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/styles/app.scss: -------------------------------------------------------------------------------- 1 | a { 2 | color: #03A9F4; 3 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/tests/components/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; 3 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 4 | import { FormsModule } from '@angular/forms'; 5 | 6 | import { Configuration } from '../../app/app.constants'; 7 | import { ThingService } from '../../app/core/services/thing-data.service'; 8 | import { HomeComponent } from '../../app/home/components/home.component'; 9 | 10 | describe('HomeComponent', () => { 11 | 12 | let fixture: ComponentFixture; 13 | let comp: HomeComponent; 14 | 15 | beforeEach(async () => { 16 | TestBed.configureTestingModule({ 17 | imports: [ 18 | FormsModule, 19 | HttpClientTestingModule 20 | ], 21 | providers: [ 22 | ThingService, 23 | Configuration 24 | ], 25 | declarations: [HomeComponent] 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(HomeComponent); 31 | comp = fixture.componentInstance; 32 | }); 33 | 34 | it('on init should get all things', async () => { 35 | const http = TestBed.get(HttpTestingController); 36 | const customConfiguration = TestBed.get(Configuration); 37 | const expectedResponse = [{ id: 1, name: 'NetCore' }]; 38 | 39 | const url = customConfiguration.Server + 'api/things/'; 40 | 41 | fixture.detectChanges(); 42 | 43 | http.expectOne(url).flush(expectedResponse); 44 | 45 | fixture.whenStable().then(() => { 46 | expect(comp.things).toEqual(expectedResponse); 47 | }); 48 | }) 49 | }); 50 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/angularApp/vendor.ts: -------------------------------------------------------------------------------- 1 | import 'jquery/dist/jquery'; 2 | import 'bootstrap/dist/css/bootstrap.css'; 3 | import 'bootstrap/dist/js/bootstrap.bundle.min.js'; 4 | 5 | import '../favicon.ico'; 6 | 7 | // Other vendors for example jQuery, Lodash or Bootstrap 8 | // You can import js, ts, css, sass, ... 9 | 10 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/config/spec.bundle.js: -------------------------------------------------------------------------------- 1 | Error.stackTraceLimit = Infinity; 2 | 3 | require('core-js'); 4 | require('zone.js/dist/zone'); 5 | require('zone.js/dist/long-stack-trace-zone'); 6 | require('zone.js/dist/proxy'); 7 | require('zone.js/dist/sync-test'); 8 | require('zone.js/dist/jasmine-patch'); 9 | require('zone.js/dist/async-test'); 10 | require('zone.js/dist/fake-async-test'); 11 | require('rxjs/Rx'); 12 | 13 | var testing = require('@angular/core/testing'); 14 | var browser = require('@angular/platform-browser-dynamic/testing'); 15 | 16 | testing.TestBed.initTestEnvironment( 17 | browser.BrowserDynamicTestingModule, 18 | browser.platformBrowserDynamicTesting() 19 | ); 20 | 21 | var testContext = require.context('../angularApp', true, /\.spec\.ts/); 22 | 23 | function requireAll(requireContext) { 24 | return requireContext.keys().map(requireContext); 25 | } 26 | 27 | var modules = requireAll(testContext); 28 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const rxPaths = require('rxjs/_esm5/path-mapping'); 3 | 4 | const webpack = require('webpack'); 5 | 6 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 7 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 8 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 9 | const FilterWarningsPlugin = require('webpack-filter-warnings-plugin'); 10 | 11 | const helpers = require('./webpack.helpers'); 12 | 13 | const ROOT = path.resolve(__dirname, '..'); 14 | 15 | console.log('@@@@@@@@@ USING DEVELOPMENT @@@@@@@@@@@@@@@'); 16 | 17 | module.exports = { 18 | mode: 'development', 19 | devtool: 'source-map', 20 | performance: { 21 | hints: false 22 | }, 23 | entry: { 24 | polyfills: './angularApp/polyfills.ts', 25 | vendor: './angularApp/vendor.ts', 26 | app: './angularApp/main.ts' 27 | }, 28 | 29 | output: { 30 | path: ROOT + '/wwwroot/', 31 | filename: 'dist/[name].bundle.js', 32 | chunkFilename: 'dist/[id].chunk.js', 33 | publicPath: '/' 34 | }, 35 | 36 | resolve: { 37 | extensions: ['.ts', '.js', '.json'], 38 | alias: rxPaths() 39 | }, 40 | 41 | devServer: { 42 | historyApiFallback: true, 43 | contentBase: path.join(ROOT, '/wwwroot/'), 44 | watchOptions: { 45 | aggregateTimeout: 300, 46 | poll: 1000 47 | } 48 | }, 49 | 50 | module: { 51 | rules: [ 52 | { 53 | test: /\.ts$/, 54 | use: [ 55 | 'awesome-typescript-loader', 56 | 'angular-router-loader', 57 | 'angular2-template-loader', 58 | 'source-map-loader' 59 | ] 60 | }, 61 | { 62 | test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/, 63 | use: 'file-loader?name=assets/[name]-[hash:6].[ext]' 64 | }, 65 | { 66 | test: /favicon.ico$/, 67 | use: 'file-loader?name=/[name].[ext]' 68 | }, 69 | { 70 | test: /\.css$/, 71 | use: ['style-loader', 'css-loader'] 72 | }, 73 | { 74 | test: /\.scss$/, 75 | include: path.join(ROOT, 'angularApp/styles'), 76 | use: ['style-loader', 'css-loader', 'sass-loader'] 77 | }, 78 | { 79 | test: /\.scss$/, 80 | exclude: path.join(ROOT, 'angularApp/styles'), 81 | use: ['raw-loader', 'sass-loader'] 82 | }, 83 | { 84 | test: /\.html$/, 85 | use: 'raw-loader' 86 | } 87 | ], 88 | exprContextCritical: false 89 | }, 90 | plugins: [ 91 | function () { 92 | this.plugin('watch-run', function (watching, callback) { 93 | console.log( 94 | '\x1b[33m%s\x1b[0m', 95 | `Begin compile at ${new Date().toTimeString()}` 96 | ); 97 | callback(); 98 | }); 99 | }, 100 | 101 | new webpack.optimize.ModuleConcatenationPlugin(), 102 | 103 | new webpack.ProvidePlugin({ 104 | $: 'jquery', 105 | jQuery: 'jquery', 106 | 'window.jQuery': 'jquery' 107 | }), 108 | 109 | // new webpack.optimize.CommonsChunkPlugin({ name: ['vendor', 'polyfills'] }), 110 | 111 | new CleanWebpackPlugin({ 112 | cleanOnceBeforeBuildPatterns: ['./wwwroot/dist', './wwwroot/assets'], 113 | root: ROOT 114 | }), 115 | 116 | new HtmlWebpackPlugin({ 117 | filename: 'index.html', 118 | inject: 'body', 119 | template: 'angularApp/index.html' 120 | }), 121 | 122 | new CopyWebpackPlugin([ 123 | { from: './angularApp/images/*.*', to: 'assets/', flatten: true } 124 | ]), 125 | 126 | new FilterWarningsPlugin({ 127 | exclude: /System.import/ 128 | }) 129 | ] 130 | }; 131 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/config/webpack.helpers.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | packageSort: function (packages) { 5 | // packages = ['polyfills', 'vendor', 'app'] 6 | var len = packages.length - 1; 7 | var first = packages[0]; 8 | var last = packages[len]; 9 | return function sort(a, b) { 10 | // polyfills always first 11 | if (a.names[0] === first) { 12 | return -1; 13 | } 14 | // main always last 15 | if (a.names[0] === last) { 16 | return 1; 17 | } 18 | // vendor before app 19 | if (a.names[0] !== first && b.names[0] === last) { 20 | return -1; 21 | } else { 22 | return 1; 23 | } 24 | }; 25 | } 26 | }; -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const rxPaths = require('rxjs/_esm5/path-mapping'); 3 | const webpack = require('webpack'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 6 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 7 | const webpackTools = require('@ngtools/webpack'); 8 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') 9 | .BundleAnalyzerPlugin; 10 | const helpers = require('./webpack.helpers'); 11 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 12 | const FilterWarningsPlugin = require('webpack-filter-warnings-plugin'); 13 | 14 | const ROOT = path.resolve(__dirname, '..'); 15 | 16 | console.log('@@@@@@@@@ USING PRODUCTION @@@@@@@@@@@@@@@'); 17 | 18 | module.exports = { 19 | mode: 'production', 20 | entry: { 21 | polyfills: './angularApp/polyfills.ts', 22 | vendor: './angularApp/vendor.ts', 23 | app: './angularApp/main-aot.ts', 24 | }, 25 | 26 | output: { 27 | path: ROOT + '/wwwroot/', 28 | filename: 'dist/[name].[hash].bundle.js', 29 | chunkFilename: 'dist/[id].[hash].chunk.js', 30 | publicPath: '/', 31 | }, 32 | 33 | resolve: { 34 | extensions: ['.ts', '.js', '.json'], 35 | alias: rxPaths(), 36 | }, 37 | 38 | devServer: { 39 | historyApiFallback: true, 40 | stats: 'minimal', 41 | outputPath: path.join(ROOT, 'wwwroot/'), 42 | }, 43 | 44 | module: { 45 | rules: [ 46 | { 47 | test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, 48 | use: '@ngtools/webpack', 49 | parser: { 50 | system: true, 51 | }, 52 | }, 53 | { 54 | test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/, 55 | use: 'file-loader?name=assets/[name]-[hash:6].[ext]', 56 | parser: { 57 | system: true, 58 | }, 59 | }, 60 | { 61 | test: /favicon.ico$/, 62 | use: 'file-loader?name=/[name].[ext]', 63 | parser: { 64 | system: true, 65 | }, 66 | }, 67 | { 68 | test: /\.css$/, 69 | use: ['style-loader', 'css-loader'], 70 | parser: { 71 | system: true, 72 | }, 73 | }, 74 | { 75 | test: /\.scss$/, 76 | include: path.join(ROOT, 'angularApp/styles'), 77 | use: ['style-loader', 'css-loader', 'sass-loader'], 78 | parser: { 79 | system: true, 80 | }, 81 | }, 82 | { 83 | test: /\.scss$/, 84 | exclude: path.join(ROOT, 'angularApp/styles'), 85 | use: ['raw-loader', 'sass-loader'], 86 | parser: { 87 | system: true, 88 | }, 89 | }, 90 | { 91 | test: /\.html$/, 92 | use: 'raw-loader', 93 | parser: { 94 | system: true, 95 | }, 96 | }, 97 | ], 98 | exprContextCritical: false, 99 | }, 100 | plugins: [ 101 | // new BundleAnalyzerPlugin({ 102 | // analyzerMode: 'static', 103 | // generateStatsFile: true 104 | // }), 105 | new webpackTools.AngularCompilerPlugin({ 106 | tsConfigPath: './tsconfig-aot.json', 107 | entryModule: './angularApp/app/app.module#AppModule', 108 | sourceMap: true, 109 | }), 110 | 111 | //new webpackTools.AngularCompilerPlugin({ 112 | // tsConfigPath: './tsconfig-aot.json', 113 | // entryModule: './angularApp/app/app.module#AppModule' 114 | //}), 115 | 116 | // new webpack.optimize.ModuleConcatenationPlugin(), 117 | 118 | new webpack.ProvidePlugin({ 119 | $: 'jquery', 120 | jQuery: 'jquery', 121 | 'window.jQuery': 'jquery', 122 | }), 123 | 124 | new CleanWebpackPlugin({ 125 | cleanOnceBeforeBuildPatterns: ['./wwwroot/dist', './wwwroot/assets'], 126 | root: ROOT 127 | }), 128 | new webpack.NoEmitOnErrorsPlugin(), 129 | 130 | // new UglifyJSPlugin({ 131 | // parallel: 2 132 | // }), 133 | 134 | // new webpack.optimize.CommonsChunkPlugin({ 135 | // name: ['vendor', 'polyfills'] 136 | // }), 137 | new HtmlWebpackPlugin({ 138 | filename: 'index.html', 139 | inject: 'body', 140 | template: 'angularApp/index.html', 141 | chunksSortMode: 'none', 142 | }), 143 | 144 | new CopyWebpackPlugin([ 145 | { from: './angularApp/images/*.*', to: 'assets/', flatten: true }, 146 | ]), 147 | 148 | new FilterWarningsPlugin({ 149 | exclude: /System.import/, 150 | }), 151 | ], 152 | }; 153 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/config/webpack.test.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const FilterWarningsPlugin = require('webpack-filter-warnings-plugin'); 4 | 5 | module.exports = { 6 | mode: 'development', 7 | devtool: 'inline-source-map', 8 | 9 | performance: { 10 | hints: false 11 | }, 12 | 13 | resolve: { 14 | extensions: ['.ts', '.js'] 15 | }, 16 | 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.ts$/, 21 | use: [ 22 | 'awesome-typescript-loader', 23 | 'angular2-template-loader', 24 | 'source-map-loader' 25 | ] 26 | }, 27 | { 28 | test: /\.css$/, 29 | use: ['style-loader', 'css-loader'] 30 | }, 31 | { 32 | test: /\.scss$/, 33 | include: path.join(__dirname, 'angularApp/styles'), 34 | use: ['style-loader', 'css-loader', 'sass-loader'] 35 | }, 36 | { 37 | test: /\.scss$/, 38 | exclude: path.join(__dirname, 'angularApp/styles'), 39 | use: ['raw-loader', 'sass-loader'] 40 | }, 41 | { 42 | test: /\.html$/, 43 | use: 'raw-loader' 44 | } 45 | ], 46 | exprContextCritical: false 47 | }, 48 | plugins: [ 49 | new FilterWarningsPlugin({ 50 | exclude: /System.import/ 51 | }) 52 | ] 53 | }; 54 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/src/AngularWebpackVisualStudio/favicon.ico -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration for Angular testing 2 | 3 | module.exports = function (config) { 4 | var webpackConfig = require('./config/webpack.test.js'); 5 | 6 | var process = require('process'); 7 | process.env.CHROME_BIN = require('puppeteer').executablePath(); 8 | 9 | var configuration = { 10 | 11 | // base path that will be used to resolve all patterns (eg. files, exclude) 12 | basePath: '', 13 | 14 | // frameworks to use 15 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 16 | frameworks: ['jasmine'], 17 | 18 | // list of files / patterns to load in the browser 19 | files: [ 20 | { pattern: './config/spec.bundle.js', watched: false } 21 | ], 22 | 23 | // list of files to exclude 24 | exclude: [ 25 | ], 26 | 27 | client: { 28 | clearContext: false 29 | }, 30 | 31 | // preprocess matching files before serving them to the browser 32 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 33 | preprocessors: { 34 | './config/spec.bundle.js': ['webpack', 'sourcemap'] 35 | }, 36 | 37 | // webpack 38 | webpack: webpackConfig, 39 | 40 | webpackServer: { 41 | noInfo: true 42 | }, 43 | 44 | 45 | // test results reporter to use 46 | // possible values: 'dots', 'progress' 47 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 48 | reporters: ['spec', 'kjhtml'], 49 | 50 | 51 | // web server port 52 | port: 9876, 53 | 54 | 55 | // enable / disable colors in the output (reporters and logs) 56 | colors: true, 57 | 58 | 59 | // level of logging 60 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 61 | logLevel: config.LOG_INFO, 62 | 63 | 64 | // enable / disable watching file and executing tests whenever any file changes 65 | autoWatch: true, 66 | 67 | 68 | // start these browsers 69 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 70 | browsers: ['Chrome', 'ChromeHeadless'], 71 | browserDisconnectTimeout: 10000, 72 | browserDisconnectTolerance: 3, 73 | browserNoActivityTimeout: 60000, 74 | flags: [ 75 | '--disable-web-security', 76 | '--disable-gpu', 77 | '--no-sandbox' 78 | ] 79 | 80 | 81 | }; 82 | 83 | config.set(configuration); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-webpack-visualstudio", 3 | "version": "8.0.1", 4 | "description": "An Angular VS template", 5 | "main": "wwwroot/index.html", 6 | "author": "", 7 | "license": "ISC", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/damienbod/Angular2WebpackVisualStudio.git" 11 | }, 12 | "scripts": { 13 | "start": "concurrently \"webpack-dev-server --env=dev --open --hot --inline --port 8080\" \"dotnet run\" ", 14 | "webpack-dev": "webpack --env=dev", 15 | "webpack-production": "webpack --env=prod", 16 | "build": "npm run webpack-dev", 17 | "build-dev": "npm run webpack-dev", 18 | "build-production": "npm run webpack-production", 19 | "watch-webpack-dev": "webpack --env=dev --watch --color", 20 | "watch-webpack-production": "npm run build-production --watch --color", 21 | "publish-for-iis": "npm run build-production && dotnet publish -c Release", 22 | "test": "karma start", 23 | "test-ci": "karma start --single-run --browsers ChromeHeadless", 24 | "lint": "eslint . --ext .ts" 25 | }, 26 | "dependencies": { 27 | "@angular/animations": "~11.2.5", 28 | "@angular/common": "~11.2.5", 29 | "@angular/compiler": "~11.2.5", 30 | "@angular/core": "~11.2.5", 31 | "@angular/forms": "~11.2.5", 32 | "@angular/platform-browser": "~11.2.5", 33 | "@angular/platform-browser-dynamic": "~11.2.5", 34 | "@angular/router": "~11.2.5", 35 | "@popperjs/core": "^2.9.1", 36 | "bootstrap": "4.6.0", 37 | "common-tags": "^1.8.0", 38 | "core-js": "^2.6.5", 39 | "ie-shim": "0.1.0", 40 | "rxjs": "~6.6.6", 41 | "rxjs-compat": "^6.6.6", 42 | "zone.js": "~0.11.4" 43 | }, 44 | "devDependencies": { 45 | "@angular-devkit/build-angular": "^0.1102.4", 46 | "@angular/cli": "~11.2.4", 47 | "@angular/compiler-cli": "~11.2.5", 48 | "@angular/language-service": "~11.2.5", 49 | "@ngtools/webpack": "^11.2.4", 50 | "@types/jasmine": "~3.6.6", 51 | "@types/jasminewd2": "~2.0.8", 52 | "@types/node": "12.11.1", 53 | "@typescript-eslint/eslint-plugin": "^4.14.1", 54 | "@typescript-eslint/eslint-plugin-tslint": "^4.14.1", 55 | "@typescript-eslint/parser": "^4.14.1", 56 | "angular-router-loader": "0.8.5", 57 | "angular2-template-loader": "^0.6.2", 58 | "awesome-typescript-loader": "^5.2.1", 59 | "clean-webpack-plugin": "2.0.2", 60 | "codelyzer": "^6.0.0", 61 | "concurrently": "^5.2.0", 62 | "copy-webpack-plugin": "^5.1.1", 63 | "css-loader": "^3.4.2", 64 | "eslint": "^7.18.0", 65 | "file-loader": "^3.0.1", 66 | "html-webpack-plugin": "^3.2.0", 67 | "jasmine-core": "~3.6.0", 68 | "jasmine-spec-reporter": "~6.0.0", 69 | "jquery": "^3.6.0", 70 | "json-loader": "^0.5.7", 71 | "karma": "~5.2.3", 72 | "karma-chrome-launcher": "~3.1.0", 73 | "karma-coverage-istanbul-reporter": "~3.0.3", 74 | "karma-jasmine": "~4.0.1", 75 | "karma-jasmine-html-reporter": "^1.5.4", 76 | "karma-sourcemap-loader": "^0.3.8", 77 | "karma-spec-reporter": "^0.0.32", 78 | "karma-webpack": "4.0.2", 79 | "node-sass": "^5.0.0", 80 | "protractor": "~7.0.0", 81 | "puppeteer": "^8.0.0", 82 | "raw-loader": "^1.0.0", 83 | "rimraf": "^3.0.2", 84 | "sass-loader": "^9.0.3", 85 | "source-map-loader": "^0.2.4", 86 | "style-loader": "^1.1.3", 87 | "toposort": "2.0.2", 88 | "ts-node": "~9.0.0", 89 | "typescript": "~4.0.5", 90 | "uglifyjs-webpack-plugin": "^2.2.0", 91 | "url-loader": "^1.1.2", 92 | "webpack": "^4.44.1", 93 | "webpack-bundle-analyzer": "^3.8.0", 94 | "webpack-cli": "3.3.12", 95 | "webpack-dev-server": "^3.11.0", 96 | "webpack-filter-warnings-plugin": "^1.2.1" 97 | }, 98 | "-vs-binding": { 99 | "ProjectOpened": [ 100 | "watch-webpack-dev" 101 | ] 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/tsconfig-aot.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "downlevelIteration": true, 5 | "experimentalDecorators": true, 6 | "module": "esnext", 7 | "moduleResolution": "node", 8 | "importHelpers": true, 9 | "target": "es2015", 10 | "sourceMap": true, 11 | "emitDecoratorMetadata": true, 12 | "removeComments": true, 13 | "skipLibCheck": true, 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ], 18 | "typeRoots": [ 19 | "./node_modules/@types/" 20 | ] 21 | }, 22 | "exclude": [ 23 | "node_modules", 24 | "./angularApp/main.ts", 25 | "angularApp/tests", 26 | "**/*.spec.ts", 27 | "**/*mock.ts" 28 | ], 29 | "angularCompilerOptions": { 30 | "fullTemplateTypeCheck": true, 31 | "strictInjectionParameters": true 32 | } 33 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": true, 10 | "skipLibCheck": true, 11 | "noUnusedLocals": false, 12 | "noUnusedParameters": true, 13 | "noImplicitAny": false, 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ], 18 | "typeRoots": [ 19 | "./node_modules/@types/" 20 | ] 21 | }, 22 | "exclude": [ 23 | "node_modules", 24 | "./angularApp/main-aot.ts", 25 | "**/*.spec.ts", 26 | "**/*mock.ts" 27 | ], 28 | "awesomeTypescriptLoaderOptions": { 29 | "useWebpackText": true 30 | }, 31 | "compileOnSave": false, 32 | "buildOnSave": false 33 | } 34 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/webpack.config.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | module.exports = function(env) { 4 | return require(`./config/webpack.${env}.js`) 5 | } -------------------------------------------------------------------------------- /src/AngularWebpackVisualStudio/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienbod/AngularWebpackVisualStudio/0fc0571920e94dcb2a6fe232e89e9baaa2bb0817/src/AngularWebpackVisualStudio/wwwroot/favicon.ico -------------------------------------------------------------------------------- /tests/AngularWebpackVisualStudio_Tests/AngularWebpackVisualStudio_Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp5.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/AngularWebpackVisualStudio_Tests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:18364/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "AngularWebpackVisualStudio_Tests": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:18365/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /tests/AngularWebpackVisualStudio_Tests/ThingsController_Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using AngularWebpackVisualStudio; 6 | using AngularWebpackVisualStudio.Models; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Mvc.Testing; 9 | using Microsoft.AspNetCore.TestHost; 10 | using Microsoft.Extensions.Hosting; 11 | using Newtonsoft.Json; 12 | using Xunit; 13 | 14 | namespace AngularWebpackVisualStudio_Tests 15 | { 16 | public class ThingsController_Tests : IClassFixture> 17 | { 18 | private readonly WebApplicationFactory _factory; 19 | 20 | public ThingsController_Tests(WebApplicationFactory factory) 21 | { 22 | _factory = factory; 23 | } 24 | 25 | //public ThingsController_Tests() 26 | //{ 27 | // var hostBuilder = new WebHostBuilder(); 28 | 29 | // // Arrange 30 | // var server = new TestServer(hostBuilder.UseStartup()); 31 | // _client = server.CreateClient(); 32 | //} 33 | 34 | [Fact] 35 | public async Task Should_Add_One_Thing_Then_Return_The_Result() 36 | { 37 | // Arrange 38 | var client = _factory.CreateClient(); 39 | 40 | Thing thing = new Thing 41 | { 42 | Id = 1, 43 | Name = "thingname" 44 | }; 45 | 46 | var jsonString = JsonConvert.SerializeObject(thing); 47 | var content = new StringContent(jsonString, Encoding.UTF8, "application/json"); 48 | var response = await client.PostAsync("/api/things", content); 49 | 50 | response.EnsureSuccessStatusCode(); 51 | 52 | var responseGet = await client.GetAsync("/api/things"); 53 | responseGet.EnsureSuccessStatusCode(); 54 | var resultsInString = await responseGet.Content.ReadAsStringAsync(); 55 | var restulsInThingsArray = JsonConvert.DeserializeObject(resultsInString); 56 | 57 | Assert.Single(restulsInThingsArray); 58 | } 59 | } 60 | } 61 | --------------------------------------------------------------------------------