SPA
單頁面應用已經遍地開花,熟知的三大框架,Angular
、Vue
和React
,其中Angular
與React
均可集成至ASP.NET Core
,且提供了相關了中間件。但是Vue沒有:
As far as I’m aware, we don’t have plans to introduce Vue-specific features. This isn’t because we have anything against Vue, but rather just to limit the growth in the number of frameworks that we’re maintaining support for. The dev team only has a finite capacity for handling third-party concepts, and last year we made the strategic choice to focus on only Angular and React.
本篇將介紹如何集成Vue
。
1.集成的效果
SPA
與ASP.NET Core
集成後。可以達到兩種效果
1.1 一鍵開啓
通過Vistual Studio
-->F5
,便可以直接啓動前端應用和後臺服務,可在用一個端口下調試運行。
1.2 分開運行,無需修改代理
常用調試方式啓動後端api服務,記住端口號(假設後端端口-3000),然後去前端配置文件,如vue.config.js
修改代理
module.exports = {
//omit some config..
devServer: {
proxy: 'localhost:3000'
}
}
但是集成後,就不必這樣操作,只需要在後端UseProxyToSpaDevelopmentServer
中指定固定的SPA調試服務器地址。
2.集成的原理
2.1 啓動前端
通過中間件調用node服務,執行如下命令
npm start -- --port {dynamic_port}
dynamic_port
是在運行過程中隨機一個端口。npm
命令已經存在在package.json
中配置,它將通過vue-cli-service serve --port
啓動開發服務器。
2.2 代理前端調試服務器
前端調試服務器啓動成功後,中間件將會創建一個HttpClient
代理:將請求一起轉發到前端調試服務器 ,然後將響應複製爲自己的響應。
3.集成步驟
3.1 安裝nuget包
Install-Package Garfield.SpaServices.Extensions.Vue -Version 1.0.0
這是博主根據官方庫改寫,正如nuget包的文檔寫點那樣:由於官方沒有支持Vue,看後續是否支持,如支持,此包將歸檔廢棄。
3.2 創建Vue項目
在API項目創建ClientApp
文件,在此文件夾下創建或複製Vue
項目。
保證以下目錄結構即可:
ClientApp/package.json
3.3 修改package.json
"scripts": {
"start": "vue-cli-service serve --port", //edit here
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e"
},
3.4 修改Startup.cs
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//omit some code..
services.AddSpaStaticFiles(c=>
{
c.RootPath = "ClientApp/dist";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//omit some code..
app.UseStaticFiles();
//PRODUCTION uses webpack static files
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseVueCliServer(npmScript: "start");
//spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");
}
});
}
4.還原構建-Build
在我們調試之前,一定是構建項目,但是我們的項目現在是一個包含前端Vue
和後端Webapi
的前後端分離項目。後端需要還原各種nuget
包,在那之前,前端也需要還原npm包
,以前博主是執行npm install
這裏介紹下使用MSBuild
自動執行,修改csproj
,增加Target
:
<PropertyGroup>
<!--omit some-->
<SpaRoot>ClientApp\</SpaRoot>
</PropertyGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
</Target>
此時就會優先在Build ASP.NET WebAPI
項目前,還原前端項目。
5.調試-Debug
5.1 集成調試
保持上面的配置與代碼不變,直接運行ASP.NET Web API
Vue
將會自動構建,並與ASP.NET Core WebAPI
項目將會集成運行,通過訪問localhost:port
便可以訪問應用。
5.2 獨立調試
如果後端接口穩定,僅僅是前端問題,那麼上面的集成調試時比較方便的。但是如果是前端穩定,後端接口修改頻繁,那麼這樣的方式無疑是太慢了,因爲每次都需要重新構建vue
項目。所以獨立調試更符合此場景.
5.2.1 啓動前端
cd ClientApp
npm start 8080
5.2.2 修改後端
// spa.UseVueCliServer(npmScript: "start"); //替換如下代碼
spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");
當啓動 ASP.NET Core
應用時,它不會啓動 Vue dev 服務器
, 而是使用手動啓動的實例。 這使它能夠更快地啓動和重新啓動。 不再需要每次都等待 Vue CLI
重新生成客戶端應用。
6.發佈-Publish
以往博主部署這種前後端分離項目,是通過nginx
部署靜態前端文件,反向代理後端接口。這種方式沒問題。但是這裏介紹一點新鮮的(至少對博主而言),前端Vue
項目通過npm run build
構建成一系列的靜態文件。這些靜態文件就是我們的SPA
。說白了,就是一個靜態網頁。
所以需要靜態文件中間件:
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
最重要的是發佈時隨着WebAPI
一起發佈,而不需要,單獨執行npm run build
然後手動拷貝,這裏還是用到了MSbuild
,所以同樣需要修改csproj
文件,增加publish
的Target
:
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
<!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
<!--<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />-->
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
這時再通過Visual Studio
後者命令發佈時,就會同步構建前端項目,發佈後端API且包含前端構建後的dist
文件.現在就可以不用分開部署。
參考鏈接
https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2019
https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild?view=vs-2019
https://blog.csdn.net/sinat_36112136/article/details/103039817
https://github.com/dotnet/sdk/issues/795#issuecomment-289782712