Http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/
Hara Mihály Gy?ngy?si
Translator: oopsguy.com
I really like to use Vue.js,vue server rendering on the front end until the second version is supported. In this example, I want to show how to integrate the Vue.js service-side rendering functionality into ASP. We used the Microsoft.AspNetCore.SpaServices package on the server, which provides the ASP. NET Core API so that we can invoke node. JS managed JavaScript code using contextual information and generate the HTML The string is injected into the render page.
In this example, the application will present a list of messages that the service side renders only the last two messages (sorted by date). You can download the remaining messages from the server by clicking the "Get Message" button.
The project structure is as follows:
?
12345678910111213141516171819202122232425262728293031323334353637 |
.
├── 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 app is located under the Vueapp folder, it has two components, a simple Vuex store with a mutation and an action, and some other files we'll discuss next: App.js, Client.js, Renderon Server.js, Server.js.
Implement Vue.js service-side rendering
To use server-side rendering, we had to create two different bundles from the Vue app: one for the server (run by node. js) and the other to run in the browser and mix the apps on the client.
App.js
Boot the Vue instance in this module. It is used by two bundles together.
?
12345678 |
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 for this service-side bundle exports a function that has a context property that can be used to push any data from the render call.
Client.js
The entry point for the client bundle, which replaces the current state of the store with a global Javascript object named Initial_state, which is created by the pre-render module, and mounts the app to the specified element (. my-app).
?
123 |
import { app, store } from ‘./app‘ ; store.replaceState(__INITIAL_STATE__); app.$mount( ‘.my-app‘ ); |
Webpack Configuration
In order to create bundles, we must add two Webpack configuration files (one for the server and one for client building), and do not forget to install Webpack, if not already installed: NPM install-g Webpack.
?
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
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 successful, you can find the service bundle in/wwwroot/dist/bundle.server.js. To get the client bundle, run Webpack--config webpack.client.config.js, and the related output can be found in/wwwroot/dist/bundle.client.js.
Implement Bundle Render
The module will be executed by the ASP. NET Core, which is responsible for:
Render the service-side bundle we created earlier
Set **window.__ initial_state__** to an object sent from the server
?
123456789101112131415161718192021 |
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
}
});
});
});
};
|
Implementing the ASP. NET Core section
As mentioned earlier, we used the Microsoft.AspNetCore.SpaServices package, which provides some taghelper that make it easy to invoke node. JS managed Javascript (in the background, Spaservices uses Microsoft.AspNetCore.NodeServices package to execute Javascript).
Views/_viewimports.cshtml
In order to use Spaservices's taghelper, we need to add them to _viewimports.
?
1234567891011 |
@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 obtains two most recent messages (sorted in reverse chronological order) from Messagestore (some static data for demonstration purposes) and creates an ClientState object that will be used as the initial state of the Vuex store.
Vuex Store default state:
?
123456789101112131415 |
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 have the initial state (from the server side) and the Vue app, so we only need one step: use Asp-prerender-module and Asp-prerender-data Taghelper to render the initial value of the Vue app in the view.
?
1234567 |
@model VuejsSSRSample.Models.ClientState <!--...--; <body> &NBSP; <div class= "My-app" asp-prerender-module= "vueapp/ Renderonserver " asp-prerender-data= Code class= "JS plain" >></DIV> &NBSP; < Script src= "~/dist/bundle.client.js" asp-append-version= ></script> </BODY> <!--...--; |
The Asp-prerender-module property is used to specify the module to render (in our case, vueapp/renderonserver). We can use the asp-prerender-data property to specify an object that will be serialized and sent to the module's default function as a parameter.
You can download the sample code for the original source from the following address:
Http://github.com/mgyongyosi/VuejsSSRSample
Summarize
The above is a small series to introduce you to the vue.js and ASP. NET Core server rendering function integration, I hope we have some help, if you have any questions please give me a message, small series will promptly reply to you. Thank you very much for the support of the Scripting House website!
Original link: https://www.cnblogs.com/oopsguy/p/7837400.html
Vue.js integration with ASP. NET Core service-side rendering capabilities