Home  >  Article  >  Web Front-end  >  Vue.js and ASP.NET Core server-side rendering function

Vue.js and ASP.NET Core server-side rendering function

小云云
小云云Original
2018-01-18 13:54:092639browse

Use Vue.js on the front end, Vue server-side rendering was not supported until the second version. In this example, I want to show how to integrate Vue.js server-side rendering functionality with ASP.NET Core. On the server side, we used the Microsoft.AspNetCore.SpaServices package, which provides the ASP.NET Core API so that we can use contextual information to call Node.js-hosted JavaScript code and inject the resulting HTML string into the rendered page.

In this example, the application will display a list of messages, and the server will only render the last two messages (sorted by date). The remaining messages can be downloaded from the server by clicking the "Get Message" button.

The project structure is as follows:


.
├── 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

As you can see, the Vue application is located under the VueApp folder. It has two components, one containing A simple Vuex store with a mutation and an action and some other files we will discuss next: app.js, client.js, renderOnServer.js, server.js.

Implement Vue.js server-side rendering

To use the server-side To render, we have to create two different bundles from the Vue application: one for the server side (run by Node.js) and another for the hybrid application that will run in the browser and on the client.

app.js

Bootstrap the Vue instance in this module. It is used by both bundles.


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

The entry point of this server bundle exports a function, which has a context attribute that is available for pushing any data from the render call.

client.js

The entry point of the client bundle, which replaces the store with a global Javascript object named INITIAL_STATE (which will be created by the pre-rendering module) current state and mounts the app to the specified element (.my-app).


import { app, store } from './app';
store.replaceState(__INITIAL_STATE__);
app.$mount('.my-app');

Webpack Configuration

In order to create the bundle, we have to add two Webpack configuration files (one one for the server side and one for the client build), don't forget to install Webpack if you haven't already: 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/
  },
 ]
 },
};

Run webpack --config webpack.server.config.js. If the operation is successful, you can find the server bundle at /wwwroot/dist/bundle.server.js . To obtain the client bundle, please run webpack --config webpack.client.config.js. The relevant output can be found in /wwwroot/dist/bundle.client.js.

Implementing Bundle Render

This module will be executed by ASP.NET Core and is responsible for:

Rendering what we created before Server bundle

Set **window.__ INITIAL_STATE__** to the object sent from the server


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
  }
  });
 });
 });
};

Implement ASP .NET Core part

As mentioned before, we used the Microsoft.AspNetCore.SpaServices package, which provides some TagHelpers to easily call Node.js hosted Javascript (under the hood, SpaServices uses the Microsoft.AspNetCore.NodeServices package to execute Javascript).

Views/_ViewImports.cshtml

In order to use the TagHelper of SpaServices, we need to add them to _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);
}

It gets the two latest messages (sorted by date in reverse order) from the MessageStore (some static data just for demonstration purposes) and creates a ClientState object, This object will be used as the initial state of the Vuex store.

Vuex store Default state:


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

Finally, we With the initial state (from the server) and the Vue application, there is only one step: use asp-prerender-module and asp-prerender-data TagHelper to render the Vue application's initial values ​​in the view.


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

asp-prerender-module property is used to specify the module to render (in our case VueApp/renderOnServer). We can use the asp-prerender-data attribute to specify an object that will be serialized and sent to the module's default function as a parameter.

You can download the original sample code from the following address:

http://github.com/mgyongyosi/VuejsSSRSample

Related recommendations:

Detailed explanation of React server-side rendering examples

Diy page server-side rendering solution_html/css_WEB-ITnose

Nuxt Vue.js server-side rendering practice

The above is the detailed content of Vue.js and ASP.NET Core server-side rendering function. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn