ASP.NET Core 與 Vue.js 服務端渲染

来源:http://www.cnblogs.com/oopsguy/archive/2017/11/15/7837400.html
-Advertisement-
Play Games

我真的很喜歡在前端使用 Vue.js,Vue 服務端渲染直到第二個版本才被支持。 在本例中,我想展示如何將 Vue.js 2 服務端渲染功能整合 ASP.NET Core ...


http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/
原作者:Mihály Gyöngyösi
譯者:oopsguy.com

我真的很喜歡在前端使用 Vue.js,Vue 服務端渲染直到第二個版本才被支持。 在本例中,我想展示如何將 Vue.js 2 服務端渲染功能整合 ASP.NET Core。 我們在服務端使用了 Microsoft.AspNetCore.SpaServices 包,該包提供 ASP.NET Core API,以便於我們可以使用上下文信息調用 Node.js 托管的 JavaScript 代碼,並將生成的 HTML 字元串註入渲染頁面。

在此示例中,應用程式將展示一個消息列表,服務端只渲染最後兩條消息(按日期排序)。可以通過點擊“獲取消息”按鈕從服務端下載剩餘的消息。

項目結構如下所示:

.
├── VuejsSSRSample
|   ├── Properties
|   ├── References
|   ├── wwwroot
|   └── Dependencies
├── Controllers
|   └── HomeController.cs
├── Models
|   ├── ClientState.cs
|   ├── FakeMessageStore.cs
|   └── Message.cs
├── Views
|   ├── Home
|   |   └── Index.cshtml
|   └── _ViewImports.cshtml
├── VueApp
|   ├── components
|   |   ├── App.vue
|   |   └── Message.vue
|   ├── vuex
|   |   ├── actions.js
|   |   └── store.js
|   ├── app.js
|   ├── client.js
|   ├── renderOnServer.js
|   └── server.js
├── .babelrc
├── appsettings.json
├── Dockerfile
├── packages.json
├── Program.cs
├── project.json
├── Startup.cs
├── web.config
├── webpack.client.config.js
└── webpack.server.config.js

正如你看到的,Vue 應用位於 VueApp 文件夾下,它有兩個組件、一個包含了一個 mutation 和一個 action 的簡單 Vuex store 和一些我們接下來要討論的其他文件:app.js、client.js、 renderOnServer.js、server.js。

實現 Vue.js 服務端渲染

要使用服務端渲染,我們必須從 Vue 應用創建兩個不同的 bundle:一個用於服務端(由 Node.js 運行),另一個用於將在瀏覽器中運行併在客戶端上混合應用。

app.js

引導此模塊中的 Vue 實例。它由兩個 bundle 共同使用。

import Vue from 'vue';
import App from './components/App.vue';
import store from './vuex/store.js';

const app = new Vue({
    store,
    ...App
});

export { app, store };

server.js

此服務端 bundle 的入口點導出一個函數,該函數有一個 context 屬性,可用於從渲染調用中推送任何數據。

client.js

客戶端 bundle 的入口點,其用一個名為 INITIAL_STATE 的全局 Javascript 對象(該對象將由預渲染模塊創建)替換 store 的當前狀態,並將應用掛載到指定的元素(.my-app)。

import { app, store } from './app';

store.replaceState(__INITIAL_STATE__);

app.$mount('.my-app');

Webpack 配置

為了創建 bundle,我們必須添加兩個 Webpack 配置文件(一個用於服務端,一個用於客戶端構建),不要忘了安裝 Webpack,如果尚未安裝,則:npm install -g webpack

webpack.server.config.js

const path = require('path');

module.exports = {
    target: 'node',
    entry: path.join(__dirname, 'VueApp/server.js'),
    output: {
        libraryTarget: 'commonjs2',
        path: path.join(__dirname, 'wwwroot/dist'),
        filename: 'bundle.server.js',
    },
    module: {
        loaders: [
          {
              test: /\.vue$/,
              loader: 'vue',
          },
          {
              test: /\.js$/,
              loader: 'babel',
              include: __dirname,
              exclude: /node_modules/
          },
          {
              test: /\.json?$/,
              loader: 'json'
          }
        ]
    },
};

webpack.client.config.js

const path = require('path');

module.exports = {
    entry: path.join(__dirname, 'VueApp/client.js'),
    output: {
        path: path.join(__dirname, 'wwwroot/dist'),
        filename: 'bundle.client.js',
    },
    module: {
        loaders: [
          {
              test: /\.vue$/,
              loader: 'vue',
          },
          {
              test: /\.js$/,
              loader: 'babel',
              include: __dirname,
              exclude: /node_modules/
          },
        ]
    },
};

運行 webpack --config webpack.server.config.js, 如果運行成功,則可以在 /wwwroot/dist/bundle.server.js 找到服端 bundle。獲取客戶端 bundle 請運行 webpack --config webpack.client.config.js,相關輸出可以在 /wwwroot/dist/bundle.client.js 中找到。

實現 Bundle Render

該模塊將由 ASP.NET Core 執行,其負責:

  1. 渲染我們之前創建的服務端 bundle
  2. 將 **window.__ INITIAL_STATE__** 設置為從服務端發送的對象
process.env.VUE_ENV = 'server';

const fs = require('fs');
const path = require('path');

const filePath = path.join(__dirname, '../wwwroot/dist/bundle.server.js')
const code = fs.readFileSync(filePath, 'utf8');

const bundleRenderer = require('vue-server-renderer').createBundleRenderer(code)

module.exports = function (params) {
    return new Promise(function (resolve, reject) {
        bundleRenderer.renderToString(params.data, (err, resultHtml) => { // params.data is the store's initial state. Sent by the asp-prerender-data attribute
            if (err) {
                reject(err.message);
            }
            resolve({
                html: resultHtml,
                globals: {
                    __INITIAL_STATE__: params.data // window.__INITIAL_STATE__ will be the initial state of the Vuex store
                }
            });
        });
    });
};

實現 ASP.NET Core 部分

如之前所述,我們使用了 Microsoft.AspNetCore.SpaServices 包,它提供了一些 TagHelper,可輕鬆調用 Node.js 托管的 Javascript(在後臺,SpaServices 使用 Microsoft.AspNetCore.NodeServices 包來執行 Javascript)。

Views/_ViewImports.cshtml
為了使用 SpaServices 的 TagHelper,我們需要將它們添加到 _ViewImports 中。

@addTagHelper "*, Microsoft.AspNetCore.SpaServices"

Home/Index

public IActionResult Index()
{
   var initialMessages = FakeMessageStore.FakeMessages.OrderByDescending(m => m.Date).Take(2);

   var initialValues = new ClientState() {
       Messages = initialMessages,
       LastFetchedMessageDate = initialMessages.Last().Date
   };

   return View(initialValues);
}

它從 MessageStore(僅用於演示目的的一些靜態數據)中獲取兩條最新的消息(按日期倒序排序),並創建一個 ClientState 對象,該對象將被用作 Vuex store 的初始狀態。

Vuex store 預設狀態:

const store = new Vuex.Store({
    state: { messages: [], lastFetchedMessageDate: -1 },
    // ...
});

ClientState 類:

public class ClientState
{
    [JsonProperty(PropertyName = "messages")]
    public IEnumerable<Message> Messages { get; set; }

    [JsonProperty(PropertyName = "lastFetchedMessageDate")]
    public DateTime LastFetchedMessageDate { get; set; }
}

Index View

最後,我們有了初始狀態(來自服務端)和 Vue 應用,所以只需一個步驟:使用 asp-prerender-moduleasp-prerender-data TagHelper 在視圖中渲染 Vue 應用的初始值。

@model VuejsSSRSample.Models.ClientState
<!-- ... -->
<body>
    <div class="my-app" asp-prerender-module="VueApp/renderOnServer" asp-prerender-data="Model"></div>
    <script src="~/dist/bundle.client.js" asp-append-version="true"></script>
</body>
<!-- ... -->

asp-prerender-module 屬性用於指定要渲染的模塊(在我們的例子中為 VueApp/renderOnServer)。我們可以使用 asp-prerender-data 屬性指定一個將被序列化併發送到模塊的預設函數作為參數的對象。

您可以從以下地址下載原文的示例代碼:

http://github.com/mgyongyosi/VuejsSSRSample


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第一步:下載Linux環境下的jdk1.8,請去(官網)中下載jdk的安裝文件; 查看Linux操作系統位數: [root@localhost ~]# getconf LONG_BIT 由於我的Linux是64位的,因此我下載的是jdk-8u151-linux-x64.tar.gz 如下圖所示: 第 ...
  • Linux如何查找處理文件名後包含空格的文件 當Linux下文件名中出現空格這類特殊情況話,如何查找或確認那些文件名後有空格呢? 又怎麼批量替換處理掉這些空格呢? 方法1: 輸入文件名後使用Tab鍵,如果使用Tab鍵後面出現\ \ \這樣的可見字元,那麼該文件名包含空格。當然,這個方法弊端很大,例如... ...
  • 配置環境: linux版本:Centos6.4 httpd版本: [root@centos64Study init.d]# pwd/etc/init.d[root@centos64Study init.d]# httpd -vServer version: Apache/2.2.15 (Unix)S ...
  • 最近又碰到一起Linux下SendMail發送郵件失敗的案例,郵件發送後,郵箱收不到具體郵件, 查看日誌/var/log/maillog 發現有"DSN: User unknown"以及“dsn=5.1.1, stat=User unknown”等錯誤信息,脫敏後的具體日誌如下所示: Nov 1 0... ...
  • 1. 首先查看自己的ubuntu系統的codename,這一步很重要,直接導致你更新的源是否對你的系統起效果,查看方法: lsb_release -a 如,我的系統顯示: Description: Ubuntu 17.04 Release: 17.04 Codename: zesty 2. 確認阿裡 ...
  • 這個是Linux下連接VFS文件系統框架和不同文件/文件系統底層實現之間的一個核心數據結構,雖然它只是一個指針,但是一個指針可以解決所有問題,有了它,媽媽再也不用擔心我的學習。我們回想一下用戶態線程的創建結構,函數的入口同樣是一個void*指針,而千言萬語彙成一根指針,詩可以興、可以觀、可以群、可以 ...
  • 遞歸時候每次調用自身在堆棧上要記錄返回地址,而堆棧的空間很少,調用次數多了後會產生堆棧溢出,以下代碼是實際項目中,通過Queue<T>來避免遞歸演算法的代碼: /// <summary> /// 獲取某個節點下特定屬性的所有子孫節點 /// </summary> /// <param name="gr ...
  • UNIT_PRICE :資料庫原先類型為: NUMBER(18,4) AMOUNT : 資料庫原先類型為: NUMBER(18,4) 如果直接進行修改會報錯,因為原先欄位中已經有數據了。 ALTER TABLE CLOUD_RELEASE.CONTRACT_PRODUCT_ITEM MODIFY(U ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...