【Vue】Vue与ASP.NET Core WebAPI的集成
SPA單頁(yè)面應(yīng)用已經(jīng)遍地開(kāi)花,熟知的三大框架,Angular、Vue和React,其中Angular與React均可集成至ASP.NET Core,且提供了相關(guān)了中間件。但是Vue沒(méi)有:
“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集成后。根據(jù)需求不同,是可以達(dá)到兩種不同效果。
1.1 一鍵開(kāi)啟
通過(guò)Vistual Studio-->F5,便可以直接啟動(dòng)前端應(yīng)用開(kāi)發(fā)模式和后臺(tái)api服務(wù),且再用一個(gè)端口下。這種方便單人開(kāi)發(fā)運(yùn)行,調(diào)試。
app.UseSpa(spa?=>{spa.Options.SourcePath?=?"ClientApp";if?(env.IsDevelopment()){//spa.UseReactDevelopmentServer(npmScript:?"start");spa.UseVueCliServer(npmScript:?"start");//spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");}});1.2 獨(dú)立運(yùn)行,減輕依賴
另外就是在典型前后端分離的協(xié)同開(kāi)發(fā),常用調(diào)試方式啟動(dòng)后端api服務(wù),確定api端口號(hào)(假設(shè)后端端口為3000),然后去前端配置文件,如vue.config.js修改代理,如下配置:
module.exports?=?{//omit?some?config..devServer:?{proxy:?'localhost:3000'} }然后:
后端啟動(dòng)
前端啟動(dòng)
然后再去訪問(wèn)前端
但是集成后,就不必這樣操作,只需要在后端Startup.cs中指定固定的SPA調(diào)試服務(wù)器地址。
app.UseSpa(spa?=>{spa.Options.SourcePath?=?"ClientApp";if?(env.IsDevelopment()){//spa.UseReactDevelopmentServer(npmScript:?"start");//spa.UseVueCliServer(npmScript:?"start");spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");}});這樣后端開(kāi)發(fā)人員需要再看下前端效果,就不必再去單獨(dú)看前端,前端一旦啟動(dòng),端口一般不會(huì)變化,做如上配置,便可直接通過(guò)Vistual Studio-->F5直接運(yùn)行。
前端啟動(dòng)
后端啟動(dòng),直接就反向代理到前端開(kāi)發(fā)服務(wù)器,無(wú)需再去訪問(wèn)前端。
2.集成的原理
2.1 啟動(dòng)前端
通過(guò)中間件調(diào)用node進(jìn)程,執(zhí)行如下命令:
npm?start?--?--port?{dynamic_port}dynamic_port是在運(yùn)行過(guò)程中隨機(jī)一個(gè)端口。npm 命令已經(jīng)存在在 package.json 中配置,它將通過(guò) vue-cli-service serve --port 啟動(dòng)開(kāi)發(fā)服務(wù)器。
2.2 代理前端調(diào)試服務(wù)器
前端調(diào)試服務(wù)器啟動(dòng)成功后,中間件將會(huì)創(chuàng)建一個(gè)HttpClient代理:將請(qǐng)求一起轉(zhuǎn)發(fā)到前端調(diào)試服務(wù)器 ,然后將響應(yīng)復(fù)制為自己的響應(yīng),上面UseProxyToSpaDevelopmentServer沒(méi)有啟動(dòng)前端的過(guò)程(因?yàn)榍岸艘褑?dòng)完成),只是把前端請(qǐng)求靜態(tài)資源的請(qǐng)求代理到前端調(diào)試服務(wù)器。
3.集成步驟
3.1 安裝nuget包
Install-Package?Garfield.SpaServices.Extensions.Vue?-Version?1.0.0這是博主根據(jù)官方庫(kù)改寫(xiě),正如nuget包的文檔寫(xiě)的那樣:由于官方?jīng)]有支持Vue,看后續(xù)是否支持,如支持,此包將歸檔廢棄。
3.2 創(chuàng)建Vue項(xiàng)目
在API項(xiàng)目創(chuàng)建ClientApp文件,在此文件夾下創(chuàng)建或復(fù)制Vue項(xiàng)目。
保證以下目錄結(jié)構(gòu)即可:
ClientApp/package.json3.3 修改package.json
適配后端這邊,package.json要做一些調(diào)整,主要是端口由后端啟動(dòng)時(shí)隨機(jī)指定可用的。
"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
public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env) {//omit?some?code..app.UseStaticFiles();//PRODUCTION?uses?webpack?static?filesif?(!env.IsDevelopment()){app.UseSpaStaticFiles();}app.UseSpa(spa?=>{spa.Options.SourcePath?=?"ClientApp";if?(env.IsDevelopment()){spa.UseVueCliServer(npmScript:?"start");//spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");}}); }4.還原構(gòu)建-Build
在我們調(diào)試之前,一定是構(gòu)建項(xiàng)目,但是我們的項(xiàng)目現(xiàn)在是一個(gè)包含前端Vue和后端Webapi的前后端分離項(xiàng)目。后端需要還原各種nuget包,在那之前,前端也需要還原npm包,以前博主是執(zhí)行npm install
這里介紹下使用MSBuild自動(dòng)執(zhí)行,修改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>此時(shí)就會(huì)在Build ASP.NET WebAPI項(xiàng)目前,自動(dòng)還原前端項(xiàng)目,執(zhí)行npm install。
5.調(diào)試-Debug
從效果上來(lái)看,兩種集成方式貌似沒(méi)啥大的差別,但是從開(kāi)發(fā)的調(diào)試的角度,有各自運(yùn)用的場(chǎng)景。
5.1 集成調(diào)試
保持上面的配置與代碼不變,直接運(yùn)行ASP.NET Web API
Vue將會(huì)自動(dòng)構(gòu)建,并與ASP.NET Core WebAPI項(xiàng)目將會(huì)集成運(yùn)行,通過(guò)訪問(wèn)localhost:port便可以調(diào)試訪問(wèn)應(yīng)用。
5.2 獨(dú)立調(diào)試
如果后端接口穩(wěn)定,僅僅是前端問(wèn)題,那么上面的集成調(diào)試是比較方便的。想象一下,每次都要重新啟動(dòng),執(zhí)行npm start,還是有點(diǎn)費(fèi)時(shí)間。特別是前端已經(jīng)足夠穩(wěn)定,后端接口修改頻繁,那么這樣的方式無(wú)疑是太慢了,因?yàn)槊看味夹枰匦聠?dòng)vue項(xiàng)目,失去了集成的優(yōu)勢(shì)。所以獨(dú)立調(diào)試后端更符合此類場(chǎng)景。
5.2.1 啟動(dòng)前端
cd?ClientApp npm?start?80805.2.2 修改后端
//?spa.UseVueCliServer(npmScript:?"start");?//替換如下代碼 spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");當(dāng)啟動(dòng) ASP.NET Core 應(yīng)用時(shí),它不會(huì)啟動(dòng) Vue dev 服務(wù)器, 而是使用手動(dòng)啟動(dòng)的實(shí)例。這使它能夠更快地啟動(dòng)和重新啟動(dòng)。不再需要每次都等待 Vue CLI重新生成客戶端應(yīng)用。
6.發(fā)布-Publish
小項(xiàng)目,我們就不需要nginx去放靜態(tài)文件,修改配置等等。
以往博主部署這種前后端分離項(xiàng)目,是通過(guò)nginx部署靜態(tài)前端文件,反向代理后端接口。這種方式?jīng)]問(wèn)題。但是這里介紹一點(diǎn)新鮮的(至少對(duì)博主而言),前端Vue項(xiàng)目通過(guò)npm run build構(gòu)建成一系列的靜態(tài)文件。這些靜態(tài)文件就是我們的SPA。說(shuō)白了,就是一個(gè)靜態(tài)網(wǎng)頁(yè)。
所以需要靜態(tài)文件中間件:
public?void?Configure(IApplicationBuilder?app,?IWebHostEnvironment?env) {//omit?some?code..app.UseStaticFiles();if?(!env.IsDevelopment()){app.UseSpaStaticFiles();} }然后指定我們靜態(tài)文件的路徑:
//Startup.cs public?void?ConfigureServices(IServiceCollection?services) {//omit?some?code..services.AddSpaStaticFiles(c=>{c.RootPath?=?"ClientApp/dist";}); }這里我們把Vue項(xiàng)目包含在webapi項(xiàng)目中,文件夾ClientApp,他構(gòu)建的文件夾為dist,當(dāng)然這個(gè)也是可以修改的。
最重要一步來(lái)了,發(fā)布時(shí)讓構(gòu)建好的靜態(tài)文件隨著WebAPI一起發(fā)布,而不需要,單獨(dú)執(zhí)行npm run build然后手動(dòng)拷貝,這里還是用到了MSbuild,所以同樣需要修改csproj文件,增加publish的Target:
<PropertyGroup><!--omit?some?xml..--><SpaRoot>ClientApp\</SpaRoot> </PropertyGroup>?? <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>大概指令:發(fā)布時(shí)運(yùn)行webpack
如果需要的話執(zhí)行npm install還原(我注釋了)
執(zhí)行npm run build進(jìn)行構(gòu)建
拷貝構(gòu)建好的dist文件夾內(nèi)容到發(fā)布文件夾中
這時(shí)再通過(guò)Visual Studio后者命令發(fā)布時(shí),就會(huì)同步構(gòu)建前端項(xiàng)目,發(fā)布后端API且包含前端構(gòu)建后的dist文件。便可以不用分開(kāi)部署,從而融合為同一個(gè)程序。
參考鏈接
https://docs.microsoft.com/zh-cn/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2019
https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/visual-studio-publish-profiles?view=aspnetcore-3.1
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
總結(jié)
以上是生活随笔為你收集整理的【Vue】Vue与ASP.NET Core WebAPI的集成的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: IdentityServer4系列 |
- 下一篇: 如何在 ASP.NET Core 中 自