【Vue】Vue與ASP.NET Core WebAPI的集成


SPA單頁面應用已經遍地開花,熟知的三大框架,AngularVueReact,其中AngularReact均可集成至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.集成的效果

SPAASP.NET Core集成后。根據需求不同,是可以達到兩種不同效果。

1.1 一鍵開啟

通過Vistual Studio-->F5,便可以直接啟動前端應用開發模式后台api服務,且在用一個端口下。這種方便單人開發運行,調試。

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 獨立運行,減輕依賴

另外就是在典型前后端分離的協同開發,常用調試方式啟動后端api服務,確定api端口號(假設后端端口為3000),然后去前端配置文件,如vue.config.js修改代理,如下配置:

module.exports = {
    //omit some config..
    devServer: {
        proxy: 'localhost:3000'
    }
}

然后:

  • 后端啟動
  • 前端啟動
  • 然后再去訪問前端

但是集成后,就不必這樣操作,只需要在后端Startup.cs中指定固定的SPA調試服務器地址。

app.UseSpa(spa =>
           {
               spa.Options.SourcePath = "ClientApp";

               if (env.IsDevelopment())
               {
                   //spa.UseReactDevelopmentServer(npmScript: "start");
                   //spa.UseVueCliServer(npmScript: "start");
                   spa.UseProxyToSpaDevelopmentServer("http://localhost:8080");
               }
           });

這樣后端開發人員需要再看下前端效果,就不必再去單獨看前端,前端一旦啟動,端口一般不會變化,做如上配置,便可直接通過Vistual Studio-->F5直接運行。

  • 前端啟動
  • 后端啟動,直接就反向代理到前端開發服務器,無需再去訪問前端。

2.集成的原理

2.1 啟動前端

通過中間件調用node進程,執行如下命令:

npm start -- --port {dynamic_port}
  • dynamic_port是在運行過程中隨機一個端口。npm 命令已經存在在 package.json 中配置,它將通過 vue-cli-service serve --port 啟動開發服務器。

2.2 代理前端調試服務器

前端調試服務器啟動成功后,中間件將會創建一個HttpClient代理:將請求一起轉發到前端調試服務器 ,然后將響應復制為自己的響應,上面UseProxyToSpaDevelopmentServer沒有啟動前端的過程(因為前端已啟動完成),只是把前端請求靜態資源的請求代理到前端調試服務器。

3.集成步驟

3.1 安裝nuget包

Install-Package Garfield.SpaServices.Extensions.Vue -Version 2.0.0
#請安裝最新版本 適用於.net core 3.1

這是博主根據官方庫改寫,正如nuget包的文檔寫點那樣:由於官方沒有支持Vue,看后續是否支持,如支持,此包將歸檔廢棄。

3.2 創建Vue項目

在API項目創建ClientApp文件,在此文件夾下創建或復制Vue項目。

保證以下目錄結構即可:

ClientApp/package.json

3.3 修改package.json

適配后端這邊,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

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項目前,自動還原前端項目,執行npm install

5.調試-Debug

從效果上來看,兩種集成方式貌似沒啥大的差別,但是從開發的調試的角度,有各自運用的場景。

5.1 集成調試

保持上面的配置與代碼不變,直接運行ASP.NET Web API

Vue將會自動構建,並與ASP.NET Core WebAPI項目將會集成運行,通過訪問localhost:port便可以調試訪問應用。

5.2 獨立調試

如果后端接口穩定,僅僅是前端問題,那么上面的集成調試時比較方便的。想象一下,每次都要重新啟動,執行npm start,還是有點費時間。特別是前端已經足夠穩定,后端接口修改頻繁,那么這樣的方式無疑是太慢了,因為每次都需要重新啟動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去放靜態文件,修改配置等等。

以往博主部署這種前后端分離項目,是通過nginx部署靜態前端文件,反向代理后端接口。這種方式沒問題。但是這里介紹一點新鮮的(至少對博主而言),前端Vue項目通過npm run build構建成一系列的靜態文件。這些靜態文件就是我們的SPA。說白了,就是一個靜態網頁。

所以需要靜態文件中間件:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //omit some code..
    app.UseStaticFiles();
    if (!env.IsDevelopment())
    {
        app.UseSpaStaticFiles();
    }
}

然后指定我們靜態文件的路徑

//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    //omit some code..
    services.AddSpaStaticFiles(c=>
                               {
                                   c.RootPath = "ClientApp/dist";
                               });
}

這里我們把Vue項目包含在webapi項目中,文件夾ClientApp,他構建的文件夾為dist,當然這個也是可以修改的。

最重要一步來了,發布時讓構建好的靜態文件隨着WebAPI一起發布,而不需要,單獨執行npm run build然后手動拷貝,這里還是用到了MSbuild,所以同樣需要修改csproj文件,增加publishTarget

<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>

大概指令:發布時運行webpack

  • 如果需要的話執行npm install還原(我注釋了)
  • 執行npm run build進行構建
  • 拷貝構建好的dist文件夾內容到發布文件夾中

這時再通過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/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


作者:Garfield

同步更新至個人博客:http://www.randyfield.cn/

本文版權歸作者所有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系287572291@qq.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM