mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-23 01:58:29 +00:00
Support new prerendering mode that doesn't require you to deploy node_modules to production. This is a breaking change in aspnet-prerendering, hence the major version bump. The NuGet package is back-compatible though.
This commit is contained in:
@@ -52,29 +52,105 @@
|
|||||||
/***/ function(module, exports, __webpack_require__) {
|
/***/ function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
// Pass through the invocation to the 'aspnet-prerendering' package, verifying that it can be loaded
|
var path = __webpack_require__(2);
|
||||||
function renderToString(callback) {
|
// Separate declaration and export just to add type checking on function signature
|
||||||
var aspNetPrerendering;
|
exports.renderToString = renderToStringImpl;
|
||||||
|
// This function is invoked by .NET code (via NodeServices). Its job is to hand off execution to the application's
|
||||||
|
// prerendering boot function. It can operate in two modes:
|
||||||
|
// [1] Legacy mode
|
||||||
|
// This is for backward compatibility with projects created with templates older than the generator version 0.6.0.
|
||||||
|
// In this mode, we don't really do anything here - we just load the 'aspnet-prerendering' NPM module (which must
|
||||||
|
// exist in node_modules, and must be v1.x (not v2+)), and pass through all the parameters to it. Code in
|
||||||
|
// 'aspnet-prerendering' v1.x will locate the boot function and invoke it.
|
||||||
|
// The drawback to this mode is that, for it to work, you have to deploy node_modules to production.
|
||||||
|
// [2] Current mode
|
||||||
|
// This is for projects created with the Yeoman generator 0.6.0+ (or projects manually updated). In this mode,
|
||||||
|
// we don't invoke 'require' at runtime at all. All our dependencies are bundled into the NuGet package, so you
|
||||||
|
// don't have to deploy node_modules to production.
|
||||||
|
// To determine whether we're in mode [1] or [2], the code locates your prerendering boot function, and checks whether
|
||||||
|
// a certain flag is attached to the function instance.
|
||||||
|
function renderToStringImpl(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds) {
|
||||||
try {
|
try {
|
||||||
aspNetPrerendering = __webpack_require__(2);
|
var renderToStringFunc = findRenderToStringFunc(applicationBasePath, bootModule);
|
||||||
|
var isNotLegacyMode = renderToStringFunc && renderToStringFunc['isServerRenderer'];
|
||||||
|
if (isNotLegacyMode) {
|
||||||
|
// Current (non-legacy) mode - we invoke the exported function directly (instead of going through aspnet-prerendering)
|
||||||
|
// It's type-safe to just apply the incoming args to this function, because we already type-checked that it's a RenderToStringFunc,
|
||||||
|
// just like renderToStringImpl itself is.
|
||||||
|
renderToStringFunc.apply(null, arguments);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Legacy mode - just hand off execution to 'aspnet-prerendering' v1.x, which must exist in node_modules at runtime
|
||||||
|
renderToStringFunc = __webpack_require__(3).renderToString;
|
||||||
|
if (renderToStringFunc) {
|
||||||
|
renderToStringFunc(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback('If you use aspnet-prerendering >= 2.0.0, you must update your server-side boot module to call createServerRenderer. '
|
||||||
|
+ 'Either update your boot module code, or revert to aspnet-prerendering version 1.x');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
// Make sure loading errors are reported back to the .NET part of the app
|
||||||
// to find node_modules. Or they accidentally fail to deploy node_modules, or even to run 'npm install'.
|
callback('Prerendering failed because of error: '
|
||||||
// Make sure such errors are reported back to the .NET part of the app.
|
|
||||||
callback('Prerendering failed because of an error while loading \'aspnet-prerendering\'. Error was: '
|
|
||||||
+ ex.stack
|
+ ex.stack
|
||||||
+ '\nCurrent directory is: '
|
+ '\nCurrent directory is: '
|
||||||
+ process.cwd());
|
+ process.cwd());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
return aspNetPrerendering.renderToString.apply(this, arguments);
|
|
||||||
}
|
}
|
||||||
exports.renderToString = renderToString;
|
;
|
||||||
|
function findBootModule(applicationBasePath, bootModule) {
|
||||||
|
var bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||||
|
if (bootModule.webpackConfig) {
|
||||||
|
// If you're using asp-prerender-webpack-config, you're definitely in legacy mode
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return require(bootModuleNameFullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function findRenderToStringFunc(applicationBasePath, bootModule) {
|
||||||
|
// First try to load the module
|
||||||
|
var foundBootModule = findBootModule(applicationBasePath, bootModule);
|
||||||
|
if (foundBootModule === null) {
|
||||||
|
return null; // Must be legacy mode
|
||||||
|
}
|
||||||
|
// Now try to pick out the function they want us to invoke
|
||||||
|
var renderToStringFunc;
|
||||||
|
if (bootModule.exportName) {
|
||||||
|
// Explicitly-named export
|
||||||
|
renderToStringFunc = foundBootModule[bootModule.exportName];
|
||||||
|
}
|
||||||
|
else if (typeof foundBootModule !== 'function') {
|
||||||
|
// TypeScript-style default export
|
||||||
|
renderToStringFunc = foundBootModule.default;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Native default export
|
||||||
|
renderToStringFunc = foundBootModule;
|
||||||
|
}
|
||||||
|
// Validate the result
|
||||||
|
if (typeof renderToStringFunc !== 'function') {
|
||||||
|
if (bootModule.exportName) {
|
||||||
|
throw new Error("The module at " + bootModule.moduleName + " has no function export named " + bootModule.exportName + ".");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("The module at " + bootModule.moduleName + " does not export a default function, and you have not specified which export to invoke.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return renderToStringFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ },
|
/***/ },
|
||||||
/* 2 */
|
/* 2 */
|
||||||
|
/***/ function(module, exports) {
|
||||||
|
|
||||||
|
module.exports = require("path");
|
||||||
|
|
||||||
|
/***/ },
|
||||||
|
/* 3 */
|
||||||
/***/ function(module, exports) {
|
/***/ function(module, exports) {
|
||||||
|
|
||||||
module.exports = require("aspnet-prerendering");
|
module.exports = require("aspnet-prerendering");
|
||||||
|
|||||||
@@ -44,13 +44,14 @@
|
|||||||
/* 0 */
|
/* 0 */
|
||||||
/***/ function(module, exports, __webpack_require__) {
|
/***/ function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
module.exports = __webpack_require__(3);
|
module.exports = __webpack_require__(4);
|
||||||
|
|
||||||
|
|
||||||
/***/ },
|
/***/ },
|
||||||
/* 1 */,
|
/* 1 */,
|
||||||
/* 2 */,
|
/* 2 */,
|
||||||
/* 3 */
|
/* 3 */,
|
||||||
|
/* 4 */
|
||||||
/***/ function(module, exports, __webpack_require__) {
|
/***/ function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -58,7 +59,7 @@
|
|||||||
function createWebpackDevServer(callback) {
|
function createWebpackDevServer(callback) {
|
||||||
var aspNetWebpack;
|
var aspNetWebpack;
|
||||||
try {
|
try {
|
||||||
aspNetWebpack = __webpack_require__(4);
|
aspNetWebpack = __webpack_require__(5);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/***/ },
|
/***/ },
|
||||||
/* 4 */
|
/* 5 */
|
||||||
/***/ function(module, exports) {
|
/***/ function(module, exports) {
|
||||||
|
|
||||||
module.exports = require("aspnet-webpack");
|
module.exports = require("aspnet-webpack");
|
||||||
|
|||||||
@@ -1,20 +1,94 @@
|
|||||||
// Pass through the invocation to the 'aspnet-prerendering' package, verifying that it can be loaded
|
/// <reference path="../npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts" />
|
||||||
export function renderToString(callback) {
|
import * as url from 'url';
|
||||||
let aspNetPrerendering;
|
import * as path from 'path';
|
||||||
|
declare var __non_webpack_require__;
|
||||||
|
|
||||||
|
// Separate declaration and export just to add type checking on function signature
|
||||||
|
export const renderToString: RenderToStringFunc = renderToStringImpl;
|
||||||
|
|
||||||
|
// This function is invoked by .NET code (via NodeServices). Its job is to hand off execution to the application's
|
||||||
|
// prerendering boot function. It can operate in two modes:
|
||||||
|
// [1] Legacy mode
|
||||||
|
// This is for backward compatibility with projects created with templates older than the generator version 0.6.0.
|
||||||
|
// In this mode, we don't really do anything here - we just load the 'aspnet-prerendering' NPM module (which must
|
||||||
|
// exist in node_modules, and must be v1.x (not v2+)), and pass through all the parameters to it. Code in
|
||||||
|
// 'aspnet-prerendering' v1.x will locate the boot function and invoke it.
|
||||||
|
// The drawback to this mode is that, for it to work, you have to deploy node_modules to production.
|
||||||
|
// [2] Current mode
|
||||||
|
// This is for projects created with the Yeoman generator 0.6.0+ (or projects manually updated). In this mode,
|
||||||
|
// we don't invoke 'require' at runtime at all. All our dependencies are bundled into the NuGet package, so you
|
||||||
|
// don't have to deploy node_modules to production.
|
||||||
|
// To determine whether we're in mode [1] or [2], the code locates your prerendering boot function, and checks whether
|
||||||
|
// a certain flag is attached to the function instance.
|
||||||
|
function renderToStringImpl(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) {
|
||||||
try {
|
try {
|
||||||
aspNetPrerendering = require('aspnet-prerendering');
|
let renderToStringFunc = findRenderToStringFunc(applicationBasePath, bootModule);
|
||||||
|
const isNotLegacyMode = renderToStringFunc && renderToStringFunc['isServerRenderer'];
|
||||||
|
|
||||||
|
if (isNotLegacyMode) {
|
||||||
|
// Current (non-legacy) mode - we invoke the exported function directly (instead of going through aspnet-prerendering)
|
||||||
|
// It's type-safe to just apply the incoming args to this function, because we already type-checked that it's a RenderToStringFunc,
|
||||||
|
// just like renderToStringImpl itself is.
|
||||||
|
renderToStringFunc.apply(null, arguments);
|
||||||
|
} else {
|
||||||
|
// Legacy mode - just hand off execution to 'aspnet-prerendering' v1.x, which must exist in node_modules at runtime
|
||||||
|
renderToStringFunc = require('aspnet-prerendering').renderToString;
|
||||||
|
if (renderToStringFunc) {
|
||||||
|
renderToStringFunc(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds);
|
||||||
|
} else {
|
||||||
|
callback('If you use aspnet-prerendering >= 2.0.0, you must update your server-side boot module to call createServerRenderer. '
|
||||||
|
+ 'Either update your boot module code, or revert to aspnet-prerendering version 1.x');
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
// Make sure loading errors are reported back to the .NET part of the app
|
||||||
// to find node_modules. Or they accidentally fail to deploy node_modules, or even to run 'npm install'.
|
|
||||||
// Make sure such errors are reported back to the .NET part of the app.
|
|
||||||
callback(
|
callback(
|
||||||
'Prerendering failed because of an error while loading \'aspnet-prerendering\'. Error was: '
|
'Prerendering failed because of error: '
|
||||||
+ ex.stack
|
+ ex.stack
|
||||||
+ '\nCurrent directory is: '
|
+ '\nCurrent directory is: '
|
||||||
+ process.cwd()
|
+ process.cwd()
|
||||||
);
|
);
|
||||||
return;
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function findBootModule(applicationBasePath: string, bootModule: BootModuleInfo): any {
|
||||||
|
const bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||||
|
if (bootModule.webpackConfig) {
|
||||||
|
// If you're using asp-prerender-webpack-config, you're definitely in legacy mode
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return __non_webpack_require__(bootModuleNameFullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findRenderToStringFunc(applicationBasePath: string, bootModule: BootModuleInfo): RenderToStringFunc {
|
||||||
|
// First try to load the module
|
||||||
|
const foundBootModule = findBootModule(applicationBasePath, bootModule);
|
||||||
|
if (foundBootModule === null) {
|
||||||
|
return null; // Must be legacy mode
|
||||||
}
|
}
|
||||||
|
|
||||||
return aspNetPrerendering.renderToString.apply(this, arguments);
|
// Now try to pick out the function they want us to invoke
|
||||||
|
let renderToStringFunc: RenderToStringFunc;
|
||||||
|
if (bootModule.exportName) {
|
||||||
|
// Explicitly-named export
|
||||||
|
renderToStringFunc = foundBootModule[bootModule.exportName];
|
||||||
|
} else if (typeof foundBootModule !== 'function') {
|
||||||
|
// TypeScript-style default export
|
||||||
|
renderToStringFunc = foundBootModule.default;
|
||||||
|
} else {
|
||||||
|
// Native default export
|
||||||
|
renderToStringFunc = foundBootModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the result
|
||||||
|
if (typeof renderToStringFunc !== 'function') {
|
||||||
|
if (bootModule.exportName) {
|
||||||
|
throw new Error(`The module at ${ bootModule.moduleName } has no function export named ${ bootModule.exportName }.`);
|
||||||
|
} else {
|
||||||
|
throw new Error(`The module at ${ bootModule.moduleName } does not export a default function, and you have not specified which export to invoke.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderToStringFunc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
"target": "es3",
|
"target": "es3",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"types": ["node"]
|
"types": ["node"],
|
||||||
|
"lib": ["es2015"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
/typings/
|
/typings/
|
||||||
/node_modules/
|
/node_modules/
|
||||||
/*.js
|
/**/*.js
|
||||||
/*.d.ts
|
|
||||||
|
/**/.d.ts
|
||||||
|
!/src/**/*.d.ts
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aspnet-prerendering",
|
"name": "aspnet-prerendering",
|
||||||
"version": "1.0.7",
|
"version": "2.0.0",
|
||||||
"description": "Helpers for server-side rendering of JavaScript applications in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
|
"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",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -17,8 +17,7 @@
|
|||||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domain-task": "^2.0.1",
|
"domain-task": "^2.0.1"
|
||||||
"es6-promise": "^3.1.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^6.0.42",
|
"@types/node": "^6.0.42",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'es6-promise';
|
/// <reference path="./PrerenderingInterfaces.d.ts" />
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as domain from 'domain';
|
import * as domain from 'domain';
|
||||||
@@ -7,41 +7,8 @@ import { baseUrl } from 'domain-task/fetch';
|
|||||||
|
|
||||||
const defaultTimeoutMilliseconds = 30 * 1000;
|
const defaultTimeoutMilliseconds = 30 * 1000;
|
||||||
|
|
||||||
export interface RenderToStringCallback {
|
export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
|
||||||
(error: any, result: RenderToStringResult): void;
|
const resultFunc = (callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) => {
|
||||||
}
|
|
||||||
|
|
||||||
export interface RenderToStringResult {
|
|
||||||
html: string;
|
|
||||||
globals: { [key: string]: any };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BootFunc {
|
|
||||||
(params: BootFuncParams): Promise<RenderToStringResult>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BootFuncParams {
|
|
||||||
location: url.Url; // e.g., Location object containing information '/some/path'
|
|
||||||
origin: string; // e.g., 'https://example.com:1234'
|
|
||||||
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 {
|
|
||||||
moduleName: string;
|
|
||||||
exportName?: string;
|
|
||||||
webpackConfig?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderToString(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) {
|
|
||||||
findBootFunc(applicationBasePath, bootModule, (findBootFuncError, bootFunc) => {
|
|
||||||
if (findBootFuncError) {
|
|
||||||
callback(findBootFuncError, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare a promise that will represent the completion of all domain tasks in this execution context.
|
// Prepare a promise that will represent the completion of all domain tasks in this execution context.
|
||||||
// The boot code will wait for this before performing its final render.
|
// The boot code will wait for this before performing its final render.
|
||||||
let domainTaskCompletionPromiseResolve;
|
let domainTaskCompletionPromiseResolve;
|
||||||
@@ -76,7 +43,7 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
|||||||
}
|
}
|
||||||
const timeoutMilliseconds = overrideTimeoutMilliseconds || defaultTimeoutMilliseconds; // e.g., pass -1 to override as 'never time out'
|
const timeoutMilliseconds = overrideTimeoutMilliseconds || defaultTimeoutMilliseconds; // e.g., pass -1 to override as 'never time out'
|
||||||
const bootFuncPromiseWithTimeout = timeoutMilliseconds > 0
|
const bootFuncPromiseWithTimeout = timeoutMilliseconds > 0
|
||||||
? wrapWithTimeout(bootFuncPromise, timeoutMilliseconds,
|
? wrapWithTimeout(bootFuncPromise, timeoutMilliseconds,
|
||||||
`Prerendering timed out after ${timeoutMilliseconds}ms because the boot function in '${bootModule.moduleName}' `
|
`Prerendering timed out after ${timeoutMilliseconds}ms because the boot function in '${bootModule.moduleName}' `
|
||||||
+ 'returned a promise that did not resolve or reject. Make sure that your boot function always resolves or '
|
+ 'returned a promise that did not resolve or reject. Make sure that your boot function always resolves or '
|
||||||
+ 'rejects its promise. You can change the timeout value using the \'asp-prerender-timeout\' tag helper.')
|
+ 'rejects its promise. You can change the timeout value using the \'asp-prerender-timeout\' tag helper.')
|
||||||
@@ -97,7 +64,14 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
|||||||
domainTaskCompletionPromiseResolve();
|
domainTaskCompletionPromiseResolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Indicate to the prerendering code bundled into Microsoft.AspNetCore.SpaServices that this is a serverside rendering
|
||||||
|
// function, so it can be invoked directly. This flag exists only so that, in its absence, we can run some different
|
||||||
|
// backward-compatibility logic.
|
||||||
|
resultFunc['isServerRenderer'] = true;
|
||||||
|
|
||||||
|
return resultFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number, timeoutRejectionValue: any): Promise<T> {
|
function wrapWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number, timeoutRejectionValue: any): Promise<T> {
|
||||||
@@ -119,59 +93,6 @@ function wrapWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number, ti
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findBootModule<T>(applicationBasePath: string, bootModule: BootModuleInfo, callback: (error: any, foundModule: T) => void) {
|
|
||||||
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');
|
|
||||||
} catch (ex) {
|
|
||||||
callback('To load your boot module via webpack (i.e., if you specify a \'webpackConfig\' option), you must install the \'aspnet-webpack\' NPM package. Error encountered while loading \'aspnet-webpack\': ' + ex.stack, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aspNetWebpackModule.loadViaWebpack(webpackConfigFullPath, bootModuleNameFullPath, callback);
|
|
||||||
} else {
|
|
||||||
callback(null, require(bootModuleNameFullPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findBootFunc(applicationBasePath: string, bootModule: BootModuleInfo, callback: (error: any, bootFunc: BootFunc) => void) {
|
|
||||||
// First try to load the module (possibly via Webpack)
|
|
||||||
findBootModule<any>(applicationBasePath, bootModule, (findBootModuleError, foundBootModule) => {
|
|
||||||
if (findBootModuleError) {
|
|
||||||
callback(findBootModuleError, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now try to pick out the function they want us to invoke
|
|
||||||
let bootFunc: BootFunc;
|
|
||||||
if (bootModule.exportName) {
|
|
||||||
// Explicitly-named export
|
|
||||||
bootFunc = foundBootModule[bootModule.exportName];
|
|
||||||
} else if (typeof foundBootModule !== 'function') {
|
|
||||||
// TypeScript-style default export
|
|
||||||
bootFunc = foundBootModule.default;
|
|
||||||
} else {
|
|
||||||
// Native default export
|
|
||||||
bootFunc = foundBootModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the result
|
|
||||||
if (typeof bootFunc !== 'function') {
|
|
||||||
if (bootModule.exportName) {
|
|
||||||
callback(`The module at ${ bootModule.moduleName } has no function export named ${ bootModule.exportName }.`, null);
|
|
||||||
} else {
|
|
||||||
callback(`The module at ${ bootModule.moduleName } does not export a default function, and you have not specified which export to invoke.`, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(null, bootFunc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindPromiseContinuationsToDomain(promise: Promise<any>, domainInstance: domain.Domain) {
|
function bindPromiseContinuationsToDomain(promise: Promise<any>, domainInstance: domain.Domain) {
|
||||||
const originalThen = promise.then;
|
const originalThen = promise.then;
|
||||||
promise.then = (function then(resolve, reject) {
|
promise.then = (function then(resolve, reject) {
|
||||||
|
|||||||
35
src/Microsoft.AspNetCore.SpaServices/npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts
vendored
Normal file
35
src/Microsoft.AspNetCore.SpaServices/npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
interface RenderToStringFunc {
|
||||||
|
(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RenderToStringCallback {
|
||||||
|
(error: any, result?: RenderToStringResult): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RenderToStringResult {
|
||||||
|
html: string;
|
||||||
|
globals?: { [key: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RedirectResult {
|
||||||
|
redirectUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BootFunc {
|
||||||
|
(params: BootFuncParams): Promise<RenderToStringResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BootFuncParams {
|
||||||
|
location: any; // e.g., Location object containing information '/some/path'
|
||||||
|
origin: string; // e.g., 'https://example.com:1234'
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BootModuleInfo {
|
||||||
|
moduleName: string;
|
||||||
|
exportName?: string;
|
||||||
|
webpackConfig?: string;
|
||||||
|
}
|
||||||
@@ -1 +1,5 @@
|
|||||||
|
/// <reference path="./PrerenderingInterfaces.d.ts" />
|
||||||
|
|
||||||
export * from './Prerendering';
|
export * from './Prerendering';
|
||||||
|
|
||||||
|
export type RenderResult = RenderToStringResult | RedirectResult;
|
||||||
|
|||||||
Reference in New Issue
Block a user