之前有寫過一篇 .NET core 2 + Vue-cli 2 的起手式,到了2019,兩者也紛紛出版本3。這次,我們將說明如何用 .NET Core 3 + Vue-cli 3 起一個新專案,附贈最新 Vuetify 2 的 Material Design 框架。

安裝 vue-cli 模板

注意: vue-cli 需要 Node.js 版本 > v8.9


  • 安裝全域 vue-cli
1
npm install -g @vue/cli
  • 起始一個 vue 專案 my-app
1
vue create my-app

按照 vue-cli 的指示選擇預設 (default) 即可。

安裝完後,可以把專案從 my-app 資料夾中移出來,如下圖。

專案目錄

  • 執行套件安裝
1
npm install
  • 安裝 Vuetify 框架

如果不想要安裝樣式框架可以直接跳過這個步驟

1
vue add vuetify
  • 測試 vue 專案是否安裝成功
1
npm run serve

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

http://localhost:8080

起始 .NET Core 3.0 MVC 專案

1
dotnet new mvc

把產生的檔案都移到最外層 (跟 Vue 同一層),如下圖。

專案目錄

  • 刪除不必要的檔案

因為我們是 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
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using dotnet_core_with_vue_cli3.Models;

namespace dotnet_core_with_vue_cli3.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

public IActionResult Index()
{
return View();
}

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
  • Index.cshtml 多餘的 HTML 刪除
1
<div id="app"></div>
  • _Layout.cshtml 修改內容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="~/favicon.ico">
<title>dotnet_core_with_vue_cli3</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but my-app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>

@RenderBody()

<script src="~/js/app.js" asp-append-version="true"></script>

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

誒~你有沒有覺得明明我們把 wwwroot 裡面的靜態資源都殺光光,卻在 _Layout.cshtml 上面放 app.js?因為這邊是留給 Vue-cli 去產生靜態資源,所以我們接下來就要說明如何設定讓 .NET CoreVue 做連動。

設定 HMRvue router 的 fallback

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

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

  • 安裝 aspnet-webpack, webpack-hot-middleware, webpack-dev-middleware
1
npm i -D aspnet-webpack webpack-hot-middleware webpack-dev-middleware
  • 新增 Microsoft.AspNetCore.SpaServices.Extensions
1
dotnet add package Microsoft.AspNetCore.SpaServices.Extensions --version 3.0.0
  • 修改 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
30
31
...
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, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true,
ConfigFile = @"./node_modules/@vue/cli-service/webpack.config.js"
});
}
else
{
...
}
...

app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapFallbackToController("Index", "Home");
});
}
......
  • 新增 vue.config.js 在最外層

這邊就是設定 Vue-cli 將產生的靜態檔案放在 wwwroot.Net Core 去吃。

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
outputDir: 'wwwroot',
publicPath: "/",
chainWebpack: config => {
// https://github.com/vuejs/vue-cli/issues/3603#issuecomment-483913563
// remove vue-cli-service's progress output
config.plugins.delete('progress')
// https://intellitect.com/quickly-configure-asp-net-core-api-to-work-with-vue-cli-3/
// aspnet uses the other hmr so remove this one
config.plugins.delete('hmr');
}
}
  • 若要使用 vscode 跑專案:修改 Properties/launchSettings.json

修改 Properties/launchSettings.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"iisSettings": {
...
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"NODE_ENV": "development"
}
},
"dotnet_core_with_vue_cli3": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"NODE_ENV": "development"
}
}
}
}
  • 若要使用 npm 跑專案:package.json 指令加上 HMR

安裝 cross-env

1
npm install -D cross-env

package.json

1
2
3
4
5
6
7
8
{
......
"scripts": {
"hmr": "cross-env ASPNETCORE_ENVIRONMENT=Development NODE_ENV=development dotnet run",
...
},
......
}

執行如下 npm 指令或使用之前寫的另一篇文章方式 vscode task 來啟動專案。

1
npm run hmr

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

http://localhost:5000

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

參考資料