diff --git a/templates/VueSpa/.deployment b/templates/VueSpa/.deployment new file mode 100644 index 0000000..4ad366c --- /dev/null +++ b/templates/VueSpa/.deployment @@ -0,0 +1,2 @@ +[config] +SCM_SCRIPT_GENERATOR_ARGS=--aspNetCore project.json diff --git a/templates/VueSpa/ClientApp/boot-client.ts b/templates/VueSpa/ClientApp/boot-client.ts new file mode 100644 index 0000000..b86ea2a --- /dev/null +++ b/templates/VueSpa/ClientApp/boot-client.ts @@ -0,0 +1,11 @@ +import './css/site.css'; +import Vue from 'vue'; +import router from './router'; + +const App = require('./components/app/app.vue.html'); + +new Vue({ + el: 'app', + render: h => h(App, { props: {} }), + router: router +}); diff --git a/templates/VueSpa/ClientApp/components/app/app.ts b/templates/VueSpa/ClientApp/components/app/app.ts new file mode 100644 index 0000000..75eaa8d --- /dev/null +++ b/templates/VueSpa/ClientApp/components/app/app.ts @@ -0,0 +1,10 @@ +import Vue from 'vue'; +import { Component } from 'av-ts'; + +@Component({ + components: { + MenuComponent: require('../navmenu/navmenu.vue.html') + } +}) +export default class AppComponent extends Vue { +} diff --git a/templates/VueSpa/ClientApp/components/app/app.vue.html b/templates/VueSpa/ClientApp/components/app/app.vue.html new file mode 100644 index 0000000..65a2ff9 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/app/app.vue.html @@ -0,0 +1,15 @@ + + + diff --git a/templates/VueSpa/ClientApp/components/counter/counter.ts b/templates/VueSpa/ClientApp/components/counter/counter.ts new file mode 100644 index 0000000..76f9a92 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/counter/counter.ts @@ -0,0 +1,11 @@ +import Vue from 'vue'; +import { Component } from 'av-ts'; + +@Component +export default class CounterComponent extends Vue { + currentcount: number = 0; + + incrementCounter() { + this.currentcount++; + } +} diff --git a/templates/VueSpa/ClientApp/components/counter/counter.vue.html b/templates/VueSpa/ClientApp/components/counter/counter.vue.html new file mode 100644 index 0000000..570d1a2 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/counter/counter.vue.html @@ -0,0 +1,13 @@ + + + diff --git a/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts new file mode 100644 index 0000000..c648f02 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts @@ -0,0 +1,22 @@ +import Vue from 'vue'; +import { Component, Lifecycle } from 'av-ts'; + +interface WeatherForecast { + dateFormatted: string; + temperatureC: number; + temperatureF: number; + summary: string; +} + +@Component +export default class FetchDataComponent extends Vue { + forecasts: WeatherForecast[] = []; + + @Lifecycle mounted() { + fetch('/api/SampleData/WeatherForecasts') + .then(response => response.json() as Promise) + .then(data => { + this.forecasts = data; + }); + } +} diff --git a/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.vue.html b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.vue.html new file mode 100644 index 0000000..1b64774 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.vue.html @@ -0,0 +1,30 @@ + + + diff --git a/templates/VueSpa/ClientApp/components/home/home.vue.html b/templates/VueSpa/ClientApp/components/home/home.vue.html new file mode 100644 index 0000000..9e4b1ea --- /dev/null +++ b/templates/VueSpa/ClientApp/components/home/home.vue.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/templates/VueSpa/ClientApp/components/navmenu/navmenu.vue.html b/templates/VueSpa/ClientApp/components/navmenu/navmenu.vue.html new file mode 100644 index 0000000..33a6e50 --- /dev/null +++ b/templates/VueSpa/ClientApp/components/navmenu/navmenu.vue.html @@ -0,0 +1,35 @@ + diff --git a/templates/VueSpa/ClientApp/css/site.css b/templates/VueSpa/ClientApp/css/site.css new file mode 100644 index 0000000..b57445c --- /dev/null +++ b/templates/VueSpa/ClientApp/css/site.css @@ -0,0 +1,66 @@ +.main-nav li .glyphicon { + margin-right: 10px; +} + +/* Highlighting rules for nav menu items */ +.main-nav li a.router-link-active, +.main-nav li a.router-link-active:hover, +.main-nav li a.router-link-active:focus { + background-color: #4189C7; + color: white; +} + +/* Keep the nav menu independent of scrolling and on top of other items */ +.main-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1; +} + +@media (max-width: 767px) { + /* On small screens, the nav menu spans the full width of the screen. Leave a space for it. */ + body { + padding-top: 50px; + } +} + +@media (min-width: 768px) { + /* On small screens, convert the nav menu to a vertical sidebar */ + .main-nav { + height: 100%; + width: calc(25% - 20px); + } + .main-nav .navbar { + border-radius: 0px; + border-width: 0px; + height: 100%; + } + .main-nav .navbar-header { + float: none; + } + .main-nav .navbar-collapse { + border-top: 1px solid #444; + padding: 0px; + } + .main-nav .navbar ul { + float: none; + } + .main-nav .navbar li { + float: none; + font-size: 15px; + margin: 6px; + } + .main-nav .navbar li a { + padding: 10px 16px; + border-radius: 4px; + } + .main-nav .navbar a { + /* If a menu item's text is too long, truncate it */ + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/templates/VueSpa/ClientApp/router.ts b/templates/VueSpa/ClientApp/router.ts new file mode 100644 index 0000000..748b93d --- /dev/null +++ b/templates/VueSpa/ClientApp/router.ts @@ -0,0 +1,13 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; + +Vue.use(VueRouter); + +export default new VueRouter({ + mode: 'history', + routes: [ + { path: '/', component: require('./components/home/home.vue.html') }, + { path: '/counter', component: require('./components/counter/counter.vue.html') }, + { path: '/fetchdata', component: require('./components/fetchdata/fetchdata.vue.html') } + ] +}); diff --git a/templates/VueSpa/Controllers/HomeController.cs b/templates/VueSpa/Controllers/HomeController.cs new file mode 100644 index 0000000..9d75da8 --- /dev/null +++ b/templates/VueSpa/Controllers/HomeController.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace WebApplicationBasic.Controllers +{ + public class HomeController : Controller + { + public IActionResult Index() + { + return View(); + } + + public IActionResult Error() + { + return View(); + } + } +} diff --git a/templates/VueSpa/Controllers/SampleDataController.cs b/templates/VueSpa/Controllers/SampleDataController.cs new file mode 100644 index 0000000..0f1aa37 --- /dev/null +++ b/templates/VueSpa/Controllers/SampleDataController.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace WebApplicationBasic.Controllers +{ + [Route("api/[controller]")] + public class SampleDataController : Controller + { + private static string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + [HttpGet("[action]")] + public IEnumerable WeatherForecasts() + { + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + DateFormatted = DateTime.Now.AddDays(index).ToString("d"), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }); + } + + public class WeatherForecast + { + public string DateFormatted { get; set; } + public int TemperatureC { get; set; } + public string Summary { get; set; } + + public int TemperatureF + { + get + { + return 32 + (int)(TemperatureC / 0.5556); + } + } + } + } +} diff --git a/templates/VueSpa/Program.cs b/templates/VueSpa/Program.cs new file mode 100644 index 0000000..193f1e2 --- /dev/null +++ b/templates/VueSpa/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; + +namespace WebApplicationBasic +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup() + .Build(); + + host.Run(); + } + } +} diff --git a/templates/VueSpa/Startup.cs b/templates/VueSpa/Startup.cs new file mode 100644 index 0000000..e5d73ed --- /dev/null +++ b/templates/VueSpa/Startup.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.SpaServices.Webpack; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace WebApplicationBasic +{ + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddEnvironmentVariables(); + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services.AddMvc(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + loggerFactory.AddDebug(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions { + HotModuleReplacement = true + }); + } + else + { + app.UseExceptionHandler("/Home/Error"); + } + + app.UseStaticFiles(); + + app.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Home}/{action=Index}/{id?}"); + + routes.MapSpaFallbackRoute( + name: "spa-fallback", + defaults: new { controller = "Home", action = "Index" }); + }); + } + } +} diff --git a/templates/VueSpa/Views/Home/Index.cshtml b/templates/VueSpa/Views/Home/Index.cshtml new file mode 100644 index 0000000..693b74f --- /dev/null +++ b/templates/VueSpa/Views/Home/Index.cshtml @@ -0,0 +1,9 @@ +@{ + ViewData["Title"] = "Home Page"; +} + +Loading... + +@section scripts { + +} diff --git a/templates/VueSpa/Views/Shared/Error.cshtml b/templates/VueSpa/Views/Shared/Error.cshtml new file mode 100644 index 0000000..473b35d --- /dev/null +++ b/templates/VueSpa/Views/Shared/Error.cshtml @@ -0,0 +1,6 @@ +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

diff --git a/templates/VueSpa/Views/Shared/_Layout.cshtml b/templates/VueSpa/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000..a770ceb --- /dev/null +++ b/templates/VueSpa/Views/Shared/_Layout.cshtml @@ -0,0 +1,19 @@ + + + + + + @ViewData["Title"] - WebApplicationBasic + + + + + + + + @RenderBody() + + + @RenderSection("scripts", required: false) + + diff --git a/templates/VueSpa/Views/_ViewImports.cshtml b/templates/VueSpa/Views/_ViewImports.cshtml new file mode 100644 index 0000000..e7b4f83 --- /dev/null +++ b/templates/VueSpa/Views/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using WebApplicationBasic +@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers" +@addTagHelper "*, Microsoft.AspNetCore.SpaServices" diff --git a/templates/VueSpa/Views/_ViewStart.cshtml b/templates/VueSpa/Views/_ViewStart.cshtml new file mode 100644 index 0000000..820a2f6 --- /dev/null +++ b/templates/VueSpa/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/templates/VueSpa/VueSpa.csproj b/templates/VueSpa/VueSpa.csproj new file mode 100644 index 0000000..db423e2 --- /dev/null +++ b/templates/VueSpa/VueSpa.csproj @@ -0,0 +1,33 @@ + + + netcoreapp1.1 + true + false + + + + + + + + + + + + + + + + + + + + + + + %(DistFiles.Identity) + PreserveNewest + + + + \ No newline at end of file diff --git a/templates/VueSpa/VueSpa.xproj b/templates/VueSpa/VueSpa.xproj new file mode 100644 index 0000000..724c811 --- /dev/null +++ b/templates/VueSpa/VueSpa.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + true + + + + 85231b41-6998-49ae-abd2-5124c83dbef2 + VueSpa + .\obj + .\bin\ + v4.5.2 + + + 2.0 + + + \ No newline at end of file diff --git a/templates/VueSpa/appsettings.json b/templates/VueSpa/appsettings.json new file mode 100644 index 0000000..723c096 --- /dev/null +++ b/templates/VueSpa/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/templates/VueSpa/global.json b/templates/VueSpa/global.json new file mode 100644 index 0000000..5a3dc98 --- /dev/null +++ b/templates/VueSpa/global.json @@ -0,0 +1,3 @@ +{ + "sdk": { "version": "1.0.0-preview2-1-003177" } +} diff --git a/templates/VueSpa/package.json b/templates/VueSpa/package.json new file mode 100644 index 0000000..a8716eb --- /dev/null +++ b/templates/VueSpa/package.json @@ -0,0 +1,26 @@ +{ + "name": "WebApplicationBasic", + "version": "0.0.0", + "devDependencies": { + "@types/requirejs": "^2.1.28", + "aspnet-webpack": "^1.0.27", + "av-ts": "^0.7.1", + "awesome-typescript-loader": "^3.0.0", + "bootstrap": "^3.3.6", + "css-loader": "^0.25.0", + "event-source-polyfill": "^0.0.7", + "extract-text-webpack-plugin": "^2.0.0-rc", + "file-loader": "^0.9.0", + "isomorphic-fetch": "^2.2.1", + "jquery": "^3.1.1", + "style-loader": "^0.13.1", + "typescript": "^2.2.1", + "url-loader": "^0.5.7", + "vue": "^2.2.2", + "vue-loader": "^11.1.4", + "vue-router": "^2.3.0", + "vue-template-compiler": "^2.2.2", + "webpack": "^2.2.0", + "webpack-hot-middleware": "^2.12.2" + } +} diff --git a/templates/VueSpa/project.json b/templates/VueSpa/project.json new file mode 100644 index 0000000..32ca9b9 --- /dev/null +++ b/templates/VueSpa/project.json @@ -0,0 +1,79 @@ +{ + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.1.0", + "type": "platform" + }, + "Microsoft.AspNetCore.SpaServices": "1.1.0-*", + "Microsoft.AspNetCore.Diagnostics": "1.1.0", + "Microsoft.AspNetCore.Mvc": "1.1.0", + "Microsoft.AspNetCore.Razor.Tools": { + "version": "1.0.0-preview2-final", + "type": "build" + }, + "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.1.0", + "Microsoft.AspNetCore.StaticFiles": "1.1.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0", + "Microsoft.Extensions.Configuration.Json": "1.1.0", + "Microsoft.Extensions.Configuration.CommandLine": "1.1.0", + "Microsoft.Extensions.Logging": "1.1.0", + "Microsoft.Extensions.Logging.Console": "1.1.0", + "Microsoft.Extensions.Logging.Debug": "1.1.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0" + }, + + "tools": { + "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", + "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" + }, + + "frameworks": { + "netcoreapp1.1": { + "imports": [ + "dotnet5.6", + "portable-net45+win8" + ] + } + }, + + "buildOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true, + "compile": { + "exclude": ["node_modules"] + } + }, + + "runtimeOptions": { + "configProperties": { + "System.GC.Server": true + } + }, + + "publishOptions": { + "include": [ + "appsettings.json", + "Views", + "web.config", + "wwwroot" + ], + "exclude": [ + "wwwroot/dist/*.map" + ] + }, + + "scripts": { + "prepublish": [ + "npm install", + "node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod", + "node node_modules/webpack/bin/webpack.js --env.prod" + ], + "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] + }, + + "tooling": { + "defaultNamespace": "WebApplicationBasic" + } +} diff --git a/templates/VueSpa/template_gitignore b/templates/VueSpa/template_gitignore new file mode 100644 index 0000000..893db26 --- /dev/null +++ b/templates/VueSpa/template_gitignore @@ -0,0 +1,245 @@ +/Properties/launchSettings.json + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +bin/ +Bin/ +obj/ +Obj/ + +# Visual Studio 2015 cache/options directory +.vs/ +/wwwroot/dist/** + +# Workaround for https://github.com/aspnet/JavaScriptServices/issues/235 +!/wwwroot/dist/_placeholder.txt + +/yarn.lock + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +orleans.codegen.cs + +# Workaround for https://github.com/aspnet/JavaScriptServices/issues/235 +/node_modules/** +!/node_modules/_placeholder.txt + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/templates/VueSpa/tsconfig.json b/templates/VueSpa/tsconfig.json new file mode 100644 index 0000000..fb41fd3 --- /dev/null +++ b/templates/VueSpa/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "module": "es2015", + "moduleResolution": "node", + "target": "es5", + "sourceMap": true, + "skipDefaultLibCheck": true, + "types": ["requirejs"] + }, + "exclude": [ + "bin", + "node_modules" + ] +} diff --git a/templates/VueSpa/web.config b/templates/VueSpa/web.config new file mode 100644 index 0000000..a8d6672 --- /dev/null +++ b/templates/VueSpa/web.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/templates/VueSpa/webpack.config.js b/templates/VueSpa/webpack.config.js new file mode 100644 index 0000000..edf8881 --- /dev/null +++ b/templates/VueSpa/webpack.config.js @@ -0,0 +1,49 @@ +const path = require('path'); +const webpack = require('webpack'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; +const bundleOutputDir = './wwwroot/dist'; + +module.exports = (env) => { + const isDevBuild = !(env && env.prod); + return [{ + stats: { modules: false }, + entry: { 'main': './ClientApp/boot-client.ts' }, + resolve: { extensions: [ '.js', '.ts' ] }, + output: { + path: path.join(__dirname, bundleOutputDir), + filename: '[name].js', + publicPath: '/dist/' + }, + module: { + rules: [ + { test: /\.vue\.html$/, include: /ClientApp/, loader: 'vue-loader', options: { loaders: { js: 'awesome-typescript-loader?silent=true' } } }, + { test: /\.ts$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' }, + { test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader' }) }, + { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' } + ] + }, + plugins: [ + new CheckerPlugin(), + new webpack.DllReferencePlugin({ + context: __dirname, + manifest: require('./wwwroot/dist/vendor-manifest.json') + }), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(isDevBuild ? 'development' : 'production') + } + }) + ].concat(isDevBuild ? [ + // Plugins that apply in development builds only + new webpack.SourceMapDevToolPlugin({ + filename: '[file].map', // Remove this line if you prefer inline source maps + moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk + }) + ] : [ + // Plugins that apply in production builds only + new webpack.optimize.UglifyJsPlugin(), + new ExtractTextPlugin('site.css') + ]) + }]; +}; diff --git a/templates/VueSpa/webpack.config.vendor.js b/templates/VueSpa/webpack.config.vendor.js new file mode 100644 index 0000000..424295c --- /dev/null +++ b/templates/VueSpa/webpack.config.vendor.js @@ -0,0 +1,47 @@ +const path = require('path'); +const webpack = require('webpack'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); + +module.exports = (env) => { + const isDevBuild = !(env && env.prod); + const extractCSS = new ExtractTextPlugin('vendor.css'); + return [{ + stats: { modules: false }, + resolve: { + extensions: [ '.js' ] + }, + module: { + rules: [ + { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' }, + { test: /\.css(\?|$)/, use: extractCSS.extract({ use: 'css-loader' }) } + ] + }, + entry: { + vendor: [ + 'bootstrap', + 'bootstrap/dist/css/bootstrap.css', + 'event-source-polyfill', + 'isomorphic-fetch', + 'jquery', + 'vue', + 'vue-router' + ], + }, + output: { + path: path.join(__dirname, 'wwwroot', 'dist'), + publicPath: '/dist/', + filename: '[name].js', + library: '[name]_[hash]', + }, + plugins: [ + extractCSS, + new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) + new webpack.DllPlugin({ + path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'), + name: '[name]_[hash]' + }) + ].concat(isDevBuild ? [] : [ + new webpack.optimize.UglifyJsPlugin() + ]) + }]; +}; diff --git a/templates/VueSpa/wwwroot/favicon.ico b/templates/VueSpa/wwwroot/favicon.ico new file mode 100644 index 0000000..a3a7999 Binary files /dev/null and b/templates/VueSpa/wwwroot/favicon.ico differ diff --git a/templates/package-builder/src/build/build.ts b/templates/package-builder/src/build/build.ts index 031416b..107cc4e 100644 --- a/templates/package-builder/src/build/build.ts +++ b/templates/package-builder/src/build/build.ts @@ -27,7 +27,8 @@ const templates: { [key: string]: { dir: string, dotNetNewId: string, displayNam 'aurelia': { dir: '../../templates/AureliaSpa/', dotNetNewId: 'Aurelia', displayName: 'Aurelia' }, 'knockout': { dir: '../../templates/KnockoutSpa/', dotNetNewId: 'Knockout', displayName: 'Knockout.js' }, 'react-redux': { dir: '../../templates/ReactReduxSpa/', dotNetNewId: 'ReactRedux', displayName: 'React.js and Redux' }, - 'react': { dir: '../../templates/ReactSpa/', dotNetNewId: 'React', displayName: 'React.js' } + 'react': { dir: '../../templates/ReactSpa/', dotNetNewId: 'React', displayName: 'React.js' }, + 'vue': { dir: '../../templates/VueSpa/', dotNetNewId: 'Vue', displayName: 'Vue.js' } };