.Net Core 可以不用開啟慢吞吞的 IDE,即可快速建立專案。本篇全程使用 VScode,手把手教你如何用 .NET Core 2.0 MVC + vue-cli 起始一個 SPA 專案。當然, HMR (Hot Module Replacement) 神器也會一併附上啦。

首先,這裡先澄清一點,就是 .NET Coretemplate 內建有 ASP.NET Core with Vue.js。因為是套裝,裡面還包含 Bootstrap, Typescript 等等,畢竟不是每個專案都會用到這些,所以本篇專注在如何結合 .NET CoreVue ,那些依專案選用的項目就不會在這裡提到。

起始 .NET Core 2.0 MVC 專案

  1. 安裝 .NET Command Line Interface

  2. 新增一個 Core MVC 專案

1
dotnet new 'ASP.NET Core Web App (Model-View-Controller)'
  1. 刪除不必要的檔案

因為我們是 SPA 不需要用到 MVC 其他頁面的功能,所以將多餘的頁面和樣式去除。參考如下的資料夾結構。

刪除多餘頁面和樣式後的檔案

  • HomeController.cs 刪除多餘的 Controller,只保留 IndexError
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using dotnet_core_vue_cli.Models;

namespace dotnet_core_vue_cli.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}

public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
  • Index.cshtml 多餘的 HTML 刪除
1
2
3
4
@{
ViewData["Title"] = "Home Page";
}
<h1>TEST</h1>
  • _Layout.cshtml 修改內容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - dotnet_core_vue_cli</title>

<environment include="Development">
<!-- 這邊放 Development 的 CSS -->
<!-- <link rel="stylesheet" href="~/css/xxx.css" asp-append-version="true"/> -->
</environment>
<environment exclude="Development">
<!-- 這邊放 Production 的 CSS -->
</environment>
</head>
<body>
@RenderBody()

<environment include="Development">
<!-- 這邊放 Development 的 JS -->
<!-- <script src="~/js/xxx.js" asp-append-version="true"></script> -->
</environment>
<environment exclude="Development">
<!-- 這邊放 Production 的 JS -->
</environment>

@RenderSection("Scripts", required: false)
</body>
</html>

現在來測試跑看看專案有沒有成功~

執行

1
dotnet run

用瀏覽器看 http://localhost:5000 就會跑出剛剛在 Index.cshtml 改寫的 TEST 字樣囉~

http://localhost:5000

安裝 vue-cli 模板

  1. 安裝全域 vue-cli
1
npm install -g vue-cli
  1. 起始一個簡易的 vue + webpack 專案
1
vue init webpack-simple

按照 vue-cli 的指示回覆操作如下圖。

vue-cli

執行

1
npm install

測試 Node 有沒有安裝成功 Vue 專案

1
npm run dev

用瀏覽器看 http://localhost:8080 如果有成功出現如下面畫面就是安裝成功 vue 的專案囉~

http://localhost:8080

誒~你有沒有注意到奇怪的地方啊?!我們跑 vue 的時候是用 node server 執行,但是真正專案要在 .NET server 執行。所以怎麼把這兩者結合呢?主要原理就是:在 Development 時把 node server 當作是前端產生靜態資源 (JS, Css, images…) 的工具; Production 的部分就把產出過後的靜態資源給 .NET server 使用。廢話不多說,我們就來趕緊試試看吧。

結合 .NET CoreVue

  1. 修改 webpack.config.js,將靜態檔案產生在 wwwroot 資料夾中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
......
module.exports = {
entry: {
main: './src/main.js'
},
output: {
path: path.resolve(__dirname, './wwwroot'),
publicPath: '/wwwroot/',
filename: 'js/build.js'
},
module: {
rules: [
......
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
publicPath: '/',
outputPath: 'imgs/',
name: '[name].[ext]?[hash]'
}
}
]
},
......
}
......
  1. 修改 cshtml 加入對應的 jshtml
  • _Layout.cshtml 修改內容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - dotnet_core_vue_cli</title>

<environment include="Development">
<!-- 這邊放 Development 的 CSS -->
<!-- <link rel="stylesheet" href="~/css/xxx.css" asp-append-version="true"/> -->
</environment>
<environment exclude="Development">
<!-- 這邊放 Production 的 CSS -->
</environment>
</head>
<body>
@RenderBody()

<environment include="Development">
<!-- 這邊放 Development 的 JS -->
<script src="~/js/build.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<!-- 這邊放 Production 的 JS -->
<script src="~/js/build.js" asp-append-version="true"></script>
</environment>

@RenderSection("Scripts", required: false)
</body>
</html>
  • 接著修改 Index.cshtml
1
2
3
4
@{
ViewData["Title"] = "Home Page";
}
<div id="app"></div>

測試跑跑看 .NET server 有沒有成功?

先產生靜態檔案

1
npm run build

再啟動伺服器

1
dotnet run

成功就會出現之前一樣的畫面囉~

http://localhost:5000

設定 HMRvue router 的 fallback

接著才是重頭戲~如魔法般的 HMR 功能登場!!!

如果還不太知道什麼是 HMR 的,就 google 一下囉~

  1. 安裝 aspnet-webpack, webpack-hot-middleware
1
npm i -D aspnet-webpack
1
npm i -D webpack-hot-middleware
  1. 新增 ASP.NET Core SPA Services
1
dotnet add package Microsoft.AspNetCore.SpaServices --version 2.0.1 
  1. 修改 Startup.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Microsoft.AspNetCore.SpaServices.Webpack;

......
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// [HMR] http://www.c-sharpcorner.com/article/using-hot-module-replacement-feature-of-webpack-in-asp-net-core/
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
......
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

// Use Vue Router must add fallback route
// Help to navigate directly
// https://stu.ratcliffe.io/2017/07/20/vuejs-serverside-rendering-with-aspnet-core
routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
});
}
......
  1. package.json 指令加上 HMR
1
2
3
4
5
6
7
8
9
{
......
"scripts": {
"hmr": "cross-env ASPNETCORE_ENVIRONMENT=Development NODE_ENV=development dotnet run",
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
......
}

執行

1
npm run hmr

成功的話就會從 Chrome 開發者工具看到 HMR 連結成功囉~

http://localhost:5000

今天的範例在 github,下回見~

參考資料