Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Commit 749c7cb

Browse files
Add example of full-page prerendering via a custom action result
1 parent edf1f88 commit 749c7cb

File tree

8 files changed

+115
-4
lines changed

8 files changed

+115
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.AspNetCore.Http;
4+
using Microsoft.AspNetCore.Http.Extensions;
5+
using Microsoft.AspNetCore.Mvc;
6+
using Microsoft.AspNetCore.NodeServices;
7+
using Microsoft.AspNetCore.SpaServices.Prerendering;
8+
using Microsoft.Extensions.DependencyInjection;
9+
10+
namespace Webpack.ActionResults
11+
{
12+
// This is an example of how you could invoke the prerendering API from an ActionResult, so as to
13+
// prerender a SPA component as the entire response page (instead of injecting the SPA component
14+
// into a Razor view's output)
15+
public class PrerenderResult : ActionResult
16+
{
17+
private JavaScriptModuleExport _moduleExport;
18+
private object _dataToSupply;
19+
20+
public PrerenderResult(JavaScriptModuleExport moduleExport, object dataToSupply = null)
21+
{
22+
_moduleExport = moduleExport;
23+
_dataToSupply = dataToSupply;
24+
}
25+
26+
public override async Task ExecuteResultAsync(ActionContext context)
27+
{
28+
var nodeServices = context.HttpContext.RequestServices.GetRequiredService<INodeServices>();
29+
var hostEnv = context.HttpContext.RequestServices.GetRequiredService<IHostingEnvironment>();
30+
var applicationBasePath = hostEnv.ContentRootPath;
31+
var request = context.HttpContext.Request;
32+
var response = context.HttpContext.Response;
33+
34+
var prerenderedHtml = await Prerenderer.RenderToString(
35+
applicationBasePath,
36+
nodeServices,
37+
_moduleExport,
38+
request.GetEncodedUrl(),
39+
request.Path + request.QueryString.Value,
40+
_dataToSupply
41+
);
42+
43+
response.ContentType = "text/html";
44+
await response.WriteAsync(prerenderedHtml.Html);
45+
}
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.SpaServices.Prerendering;
3+
4+
namespace Webpack.ActionResults
5+
{
6+
public static class PrerenderResultExtensions
7+
{
8+
public static PrerenderResult Prerender(this ControllerBase controller, JavaScriptModuleExport exportToPrerender, object dataToSupply = null)
9+
{
10+
return new PrerenderResult(exportToPrerender, dataToSupply);
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export default function (params: any): Promise<{ html: string, globals?: any }> {
2+
return new Promise((resolve, reject) => {
3+
4+
// Here, you could put any logic that synchronously or asynchronously prerenders
5+
// your SPA components. For example, see the boot-server.ts files in the Angular2Spa
6+
// and ReactReduxSpa templates for ways to prerender Angular 2 and React components.
7+
//
8+
// If you wanted, you could use a property on the 'params.data' object to specify
9+
// which SPA component or template to render.
10+
11+
const html = `
12+
<h1>Hello</h1>
13+
It works! You passed <b>${ JSON.stringify(params.data) }</b>
14+
and are currently requesting <b>${ params.location.path }</b>`;
15+
resolve({ html });
16+
});
17+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.AspNetCore.SpaServices.Prerendering;
4+
using Webpack.ActionResults;
5+
6+
namespace Webpack.Controllers
7+
{
8+
// This sample shows how you could invoke the prerendering APIs directly from an MVC
9+
// action result.
10+
public class FullPagePrerenderingController : Controller
11+
{
12+
private static JavaScriptModuleExport BootModule = new JavaScriptModuleExport("Clientside/PrerenderingSample")
13+
{
14+
// Because the boot module is written in TypeScript, we need to specify a webpack
15+
// config so it can be built. If it was written in JavaScript, this would not be needed.
16+
WebpackConfig = "webpack.config.js"
17+
};
18+
19+
public IActionResult Index()
20+
{
21+
var dataToSupply = new { nowTime = DateTime.Now.Ticks };
22+
return this.Prerender(BootModule, dataToSupply);
23+
}
24+
}
25+
}

samples/misc/Webpack/Startup.cs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Extensions.DependencyInjection;
66
using Microsoft.Extensions.Logging;
77
using System.IO;
8+
using Microsoft.AspNetCore.NodeServices;
89

910
namespace Webpack
1011
{
@@ -14,6 +15,7 @@ public class Startup
1415
public void ConfigureServices(IServiceCollection services)
1516
{
1617
services.AddMvc();
18+
services.AddNodeServices();
1719
}
1820

1921
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

samples/misc/Webpack/Views/Home/Index.cshtml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
<h1>Hello</h1>
66
Hi there. Enter some text: <input />
77

8+
<hr />
9+
See also: <a asp-controller='FullPagePrerendering'>Full-page prerendering example</a>
10+
811
@section scripts {
912
<script src="dist/main.js"></script>
1013
}

samples/misc/Webpack/package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
"name": "Webpack",
33
"version": "0.0.0",
44
"devDependencies": {
5-
"aspnet-webpack": "^1.0.3",
65
"css-loader": "^0.23.1",
76
"extendify": "^1.0.0",
87
"extract-text-webpack-plugin": "^1.0.1",
98
"less": "^2.6.0",
109
"less-loader": "^2.2.2",
1110
"style-loader": "^0.13.0",
12-
"ts-loader": "^0.8.1",
13-
"typescript": "^1.7.5",
1411
"webpack-hot-middleware": "^2.7.1"
12+
},
13+
"dependencies": {
14+
"aspnet-webpack": "^1.0.3",
15+
"aspnet-prerendering": "^1.0.4",
16+
"ts-loader": "^0.8.1",
17+
"typescript": "^1.7.5"
1518
}
1619
}

samples/misc/Webpack/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"compilerOptions": {
33
"moduleResolution": "node",
4-
"target": "es5",
4+
"module": "commonjs",
5+
"target": "es6",
56
"jsx": "preserve",
67
"sourceMap": true
78
},

0 commit comments

Comments
 (0)