mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-22 17:47:53 +00:00
Implement and document asp-prerender-data
This commit is contained in:
@@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
private const string PrerenderModuleAttributeName = "asp-prerender-module";
|
||||
private const string PrerenderExportAttributeName = "asp-prerender-export";
|
||||
private const string PrerenderWebpackConfigAttributeName = "asp-prerender-webpack-config";
|
||||
private const string PrerenderDataAttributeName = "asp-prerender-data";
|
||||
private static INodeServices _fallbackNodeServices; // Used only if no INodeServices was registered with DI
|
||||
|
||||
private readonly string _applicationBasePath;
|
||||
@@ -51,6 +52,9 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
[HtmlAttributeName(PrerenderWebpackConfigAttributeName)]
|
||||
public string WebpackConfigPath { get; set; }
|
||||
|
||||
[HtmlAttributeName(PrerenderDataAttributeName)]
|
||||
public object CustomDataParameter { get; set; }
|
||||
|
||||
[HtmlAttributeNotBound]
|
||||
[ViewContext]
|
||||
public ViewContext ViewContext { get; set; }
|
||||
@@ -67,7 +71,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
WebpackConfig = WebpackConfigPath
|
||||
},
|
||||
request.GetEncodedUrl(),
|
||||
request.Path + request.QueryString.Value);
|
||||
request.Path + request.QueryString.Value,
|
||||
CustomDataParameter);
|
||||
output.Content.SetHtmlContent(result.Html);
|
||||
|
||||
// Also attach any specified globals to the 'window' object. This is useful for transferring
|
||||
|
||||
@@ -22,7 +22,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
INodeServices nodeServices,
|
||||
JavaScriptModuleExport bootModule,
|
||||
string requestAbsoluteUrl,
|
||||
string requestPathAndQuery)
|
||||
string requestPathAndQuery,
|
||||
object customDataParameter)
|
||||
{
|
||||
return nodeServices.InvokeExport<RenderToStringResult>(
|
||||
NodeScript.Value.FileName,
|
||||
@@ -30,7 +31,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
applicationBasePath,
|
||||
bootModule,
|
||||
requestAbsoluteUrl,
|
||||
requestPathAndQuery);
|
||||
requestPathAndQuery,
|
||||
customDataParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,34 @@ If you try running your app now, you should see the HTML snippet generated by yo
|
||||
|
||||
As you can see, your JavaScript code receives context information (such as the URL being requested), and returns a `Promise` so that it can asynchronously supply the markup to be injected into the page. You can put whatever logic you like here, but typically you'll want to execute a component from your Angular 2 / React / etc. application.
|
||||
|
||||
**Passing data from .NET code into JavaScript code**
|
||||
|
||||
If you want to supply additional data to the JavaScript function that performs your prerendering, you can use the `asp-prerender-data` attribute. You can give any value as long as it's JSON-serializable. Bear in mind that it will be serialized and sent as part of the remote procedure call (RPC) to Node.js, so avoid trying to pass massive amounts of data.
|
||||
|
||||
For example, in your `cshtml`,
|
||||
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/boot-server"
|
||||
asp-prerender-data="new {
|
||||
IsGoldUser = true,
|
||||
Cookies = ViewContext.HttpContext.Request.Cookies
|
||||
}""></div>
|
||||
|
||||
Now in your JavaScript prerendering function, you can access this data by reading `params.data`, e.g.:
|
||||
|
||||
```javascript
|
||||
module.exports = function(params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var result = '<h1>Hello world!</h1>'
|
||||
+ '<p>Is gold user: ' + params.data.isGoldUser + '</p>'
|
||||
+ '<p>Number of cookies: ' + params.data.cookies.length + '</p>';
|
||||
|
||||
resolve({ html: result });
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
Notice that the property names are received in JavaScript-style casing (e.g., `isGoldUser`) even though they were sent in C#-style casing (e.g., `IsGoldUser`). This is because of how the JSON serialization is configured by default.
|
||||
|
||||
**Passing data from server-side to client-side code**
|
||||
|
||||
If, as well as returning HTML, you also want to pass some contextual data from your server-side code to your client-side code, you can supply a `globals` object alongside the initial `html`, e.g.:
|
||||
@@ -245,7 +273,7 @@ At this stage, run `webpack` on the command line to build `wwwroot/dist/main.js`
|
||||
|
||||
You can now run your React code on the client by adding the following to one of your MVC views:
|
||||
|
||||
<div id="my-spa"></div>
|
||||
<div id="my-spa"></div>
|
||||
<script src="/dist/main.js"></script>
|
||||
|
||||
#### Running React code on the server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aspnet-prerendering",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "Helpers for server-side rendering of JavaScript applications in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface BootFuncParams {
|
||||
url: string; // e.g., '/some/path'
|
||||
absoluteUrl: string; // e.g., 'https://example.com:1234/some/path'
|
||||
domainTasks: Promise<any>;
|
||||
data: any; // any custom object passed through from .NET
|
||||
}
|
||||
|
||||
export interface BootModuleInfo {
|
||||
@@ -32,7 +33,7 @@ export interface BootModuleInfo {
|
||||
webpackConfig?: string;
|
||||
}
|
||||
|
||||
export function renderToString(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string) {
|
||||
export function renderToString(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any) {
|
||||
findBootFunc(applicationBasePath, bootModule, (findBootFuncError, bootFunc) => {
|
||||
if (findBootFuncError) {
|
||||
callback(findBootFuncError, null);
|
||||
@@ -51,7 +52,8 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
||||
origin: parsedAbsoluteRequestUrl.protocol + '//' + parsedAbsoluteRequestUrl.host,
|
||||
url: requestPathAndQuery,
|
||||
absoluteUrl: absoluteRequestUrl,
|
||||
domainTasks: domainTaskCompletionPromise
|
||||
domainTasks: domainTaskCompletionPromise,
|
||||
data: customDataParameter
|
||||
};
|
||||
|
||||
// Open a new domain that can track all the async tasks involved in the app's execution
|
||||
@@ -86,7 +88,7 @@ function findBootModule<T>(applicationBasePath: string, bootModule: BootModuleIn
|
||||
const bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||
if (bootModule.webpackConfig) {
|
||||
const webpackConfigFullPath = path.resolve(applicationBasePath, bootModule.webpackConfig);
|
||||
|
||||
|
||||
let aspNetWebpackModule: any;
|
||||
try {
|
||||
aspNetWebpackModule = require('aspnet-webpack');
|
||||
|
||||
Reference in New Issue
Block a user