mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-24 02:30:13 +00:00
Compare commits
22 Commits
v1.0.x
...
example-us
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acdf18f19e | ||
|
|
633969c7b4 | ||
|
|
9c1c1b4023 | ||
|
|
0a116ba2a1 | ||
|
|
2b2465ad2e | ||
|
|
dc130adc91 | ||
|
|
b8913d29dd | ||
|
|
5e669d6e7a | ||
|
|
5d02728159 | ||
|
|
78632617f8 | ||
|
|
e2f8031bb8 | ||
|
|
2cffab14f6 | ||
|
|
9001c191c1 | ||
|
|
832da2a451 | ||
|
|
ebf5a18344 | ||
|
|
d865e1f28b | ||
|
|
62c0680193 | ||
|
|
a8d3eed32c | ||
|
|
5d14f11b1b | ||
|
|
196c0dd32e | ||
|
|
31d8eb69a7 | ||
|
|
4cbbf58600 |
@@ -2,6 +2,7 @@ versionSuffix=$1
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
projects=(
|
||||
./src/Microsoft.AspNetCore.NodeServices
|
||||
./src/Microsoft.AspNetCore.NodeServices.Sockets
|
||||
./src/Microsoft.AspNetCore.SpaServices
|
||||
./src/Microsoft.AspNetCore.AngularServices
|
||||
./src/Microsoft.AspNetCore.ReactServices
|
||||
|
||||
@@ -15,28 +15,28 @@
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.AngularServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.AngularServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
|
||||
"AutoMapper": "5.0.2"
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ConsoleApplication
|
||||
@@ -16,7 +17,10 @@ namespace ConsoleApplication
|
||||
// Set up the DI system
|
||||
var services = new ServiceCollection();
|
||||
services.AddNodeServices(options => {
|
||||
options.HostingModel = NodeServicesOptions.DefaultNodeHostingModel;
|
||||
// To compare with Socket hosting, uncomment the following line
|
||||
// Since .NET Core 1.1, the HTTP hosting model has become basically as fast as the Socket hosting model
|
||||
//options.UseSocketHosting();
|
||||
|
||||
options.ProjectPath = Directory.GetCurrentDirectory();
|
||||
options.WatchFileExtensions = new string[] {}; // Don't watch anything
|
||||
});
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.NodeServices": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0"
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.NodeServices.Sockets": "1.1.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.1.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
|
||||
@@ -12,29 +12,22 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.AspNetCore.NodeServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"netcoreapp1.0": {}
|
||||
},
|
||||
"publishExclude": [
|
||||
"node_modules",
|
||||
|
||||
3
samples/misc/Webpack/.gitignore
vendored
3
samples/misc/Webpack/.gitignore
vendored
@@ -1,6 +1,9 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
yarn.lock
|
||||
wwwroot/dist
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
"webpack-hot-middleware": "^2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"aspnet-webpack": "^1.0.3",
|
||||
"aspnet-prerendering": "^1.0.4",
|
||||
"aspnet-webpack": "^1.0.3",
|
||||
"ts-loader": "^0.8.1",
|
||||
"typescript": "^1.7.5"
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,29 +12,22 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"netcoreapp1.0": {}
|
||||
},
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"target": "es5",
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"lib": ["es6", "dom"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
@@ -10,6 +10,6 @@ module.exports = {
|
||||
},
|
||||
plugins: [
|
||||
extractLESS,
|
||||
new webpack.optimize.UglifyJsPlugin({ minimize: true })
|
||||
new webpack.optimize.UglifyJsPlugin({ minimize: true, compressor: { warnings: false } })
|
||||
]
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"@types/react-router": "^2.0.30",
|
||||
"@types/react-router-bootstrap": "^0.0.27",
|
||||
"@types/react-router-redux": "^4.0.30",
|
||||
"@types/redux": "3.5.27",
|
||||
"@types/redux-thunk": "^2.1.28",
|
||||
"@types/source-map": "^0.1.28",
|
||||
"@types/uglify-js": "^2.0.27",
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.ReactServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
|
||||
"AutoMapper": "5.0.2"
|
||||
},
|
||||
|
||||
@@ -34,10 +34,7 @@
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
"imports": []
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'babel-loader' },
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader' },
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader?silent' },
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
|
||||
]
|
||||
|
||||
@@ -9,29 +9,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.ReactServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"netcoreapp1.0": {}
|
||||
},
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"description": "Helpers for building Angular 2 applications on ASP.NET Core.",
|
||||
"version": "1.0.0-*",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -18,8 +18,8 @@
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
||||
3
src/Microsoft.AspNetCore.NodeServices.Sockets/.gitignore
vendored
Normal file
3
src/Microsoft.AspNetCore.NodeServices.Sockets/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
@@ -44,11 +44,81 @@
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(7);
|
||||
module.exports = __webpack_require__(1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
__webpack_require__(2);
|
||||
var net = __webpack_require__(3);
|
||||
var path = __webpack_require__(4);
|
||||
var readline = __webpack_require__(5);
|
||||
var ArgsUtil_1 = __webpack_require__(6);
|
||||
var ExitWhenParentExits_1 = __webpack_require__(7);
|
||||
var virtualConnectionServer = __webpack_require__(8);
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
// reference to Node's runtime 'require' function.
|
||||
var dynamicRequire = eval('require');
|
||||
// Signal to the .NET side when we're ready to accept invocations
|
||||
var server = net.createServer().on('listening', function () {
|
||||
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
|
||||
});
|
||||
// Each virtual connection represents a separate invocation
|
||||
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
|
||||
readline.createInterface(connection, null).on('line', function (line) {
|
||||
try {
|
||||
// Get a reference to the function to invoke
|
||||
var invocation = JSON.parse(line);
|
||||
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||
// Prepare a callback for accepting non-streamed JSON responses
|
||||
var hasInvokedCallback_1 = false;
|
||||
var invocationCallback = function (errorValue, successValue) {
|
||||
if (hasInvokedCallback_1) {
|
||||
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||
+ ' or the result stream has already been accessed');
|
||||
}
|
||||
hasInvokedCallback_1 = true;
|
||||
connection.end(JSON.stringify({
|
||||
result: successValue,
|
||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||
errorDetails: errorValue && (errorValue.stack || null)
|
||||
}));
|
||||
};
|
||||
// Also support streamed binary responses
|
||||
Object.defineProperty(invocationCallback, 'stream', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
hasInvokedCallback_1 = true;
|
||||
return connection;
|
||||
}
|
||||
});
|
||||
// Actually invoke it, passing through any supplied args
|
||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||
}
|
||||
catch (ex) {
|
||||
connection.end(JSON.stringify({
|
||||
errorMessage: ex.message,
|
||||
errorDetails: ex.stack
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
// Begin listening now. The underlying transport varies according to the runtime platform.
|
||||
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
|
||||
var useWindowsNamedPipes = /^win/.test(process.platform);
|
||||
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
|
||||
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
|
||||
server.listen(listenAddress);
|
||||
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */,
|
||||
/* 2 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
@@ -90,7 +160,12 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 3 */,
|
||||
/* 3 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("net");
|
||||
|
||||
/***/ },
|
||||
/* 4 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
@@ -98,6 +173,12 @@
|
||||
|
||||
/***/ },
|
||||
/* 5 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("readline");
|
||||
|
||||
/***/ },
|
||||
/* 6 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
"use strict";
|
||||
@@ -123,7 +204,7 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 6 */
|
||||
/* 7 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
/*
|
||||
@@ -189,96 +270,13 @@
|
||||
}
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 7 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
__webpack_require__(2);
|
||||
var net = __webpack_require__(8);
|
||||
var path = __webpack_require__(4);
|
||||
var readline = __webpack_require__(9);
|
||||
var ArgsUtil_1 = __webpack_require__(5);
|
||||
var ExitWhenParentExits_1 = __webpack_require__(6);
|
||||
var virtualConnectionServer = __webpack_require__(10);
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
// reference to Node's runtime 'require' function.
|
||||
var dynamicRequire = eval('require');
|
||||
// Signal to the .NET side when we're ready to accept invocations
|
||||
var server = net.createServer().on('listening', function () {
|
||||
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
|
||||
});
|
||||
// Each virtual connection represents a separate invocation
|
||||
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
|
||||
readline.createInterface(connection, null).on('line', function (line) {
|
||||
try {
|
||||
// Get a reference to the function to invoke
|
||||
var invocation = JSON.parse(line);
|
||||
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||
// Prepare a callback for accepting non-streamed JSON responses
|
||||
var hasInvokedCallback_1 = false;
|
||||
var invocationCallback = function (errorValue, successValue) {
|
||||
if (hasInvokedCallback_1) {
|
||||
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||
+ ' or the result stream has already been accessed');
|
||||
}
|
||||
hasInvokedCallback_1 = true;
|
||||
connection.end(JSON.stringify({
|
||||
result: successValue,
|
||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||
errorDetails: errorValue && (errorValue.stack || null)
|
||||
}));
|
||||
};
|
||||
// Also support streamed binary responses
|
||||
Object.defineProperty(invocationCallback, 'stream', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
hasInvokedCallback_1 = true;
|
||||
return connection;
|
||||
}
|
||||
});
|
||||
// Actually invoke it, passing through any supplied args
|
||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||
}
|
||||
catch (ex) {
|
||||
connection.end(JSON.stringify({
|
||||
errorMessage: ex.message,
|
||||
errorDetails: ex.stack
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
// Begin listening now. The underlying transport varies according to the runtime platform.
|
||||
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
|
||||
var useWindowsNamedPipes = /^win/.test(process.platform);
|
||||
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
|
||||
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
|
||||
server.listen(listenAddress);
|
||||
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 8 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("net");
|
||||
|
||||
/***/ },
|
||||
/* 9 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("readline");
|
||||
|
||||
/***/ },
|
||||
/* 10 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
var events_1 = __webpack_require__(11);
|
||||
var VirtualConnection_1 = __webpack_require__(12);
|
||||
var events_1 = __webpack_require__(9);
|
||||
var VirtualConnection_1 = __webpack_require__(10);
|
||||
// Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
|
||||
// and both will reject longer frames.
|
||||
var MaxFrameBodyLength = 16 * 1024;
|
||||
@@ -460,13 +458,13 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 11 */
|
||||
/* 9 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("events");
|
||||
|
||||
/***/ },
|
||||
/* 12 */
|
||||
/* 10 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
@@ -475,17 +473,18 @@
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var stream_1 = __webpack_require__(13);
|
||||
var stream_1 = __webpack_require__(11);
|
||||
/**
|
||||
* Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
|
||||
*/
|
||||
var VirtualConnection = (function (_super) {
|
||||
__extends(VirtualConnection, _super);
|
||||
function VirtualConnection(_beginWriteCallback) {
|
||||
_super.call(this);
|
||||
this._beginWriteCallback = _beginWriteCallback;
|
||||
this._flowing = false;
|
||||
this._receivedDataQueue = [];
|
||||
var _this = _super.call(this) || this;
|
||||
_this._beginWriteCallback = _beginWriteCallback;
|
||||
_this._flowing = false;
|
||||
_this._receivedDataQueue = [];
|
||||
return _this;
|
||||
}
|
||||
VirtualConnection.prototype._read = function () {
|
||||
this._flowing = true;
|
||||
@@ -516,7 +515,7 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 13 */
|
||||
/* 11 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("stream");
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
{
|
||||
internal class NamedPipeConnection : StreamConnection
|
||||
{
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
{
|
||||
internal abstract class StreamConnection : IDisposable
|
||||
{
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
{
|
||||
internal class UnixDomainSocketConnection : StreamConnection
|
||||
{
|
||||
@@ -3,7 +3,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
{
|
||||
// From System.IO.Pipes/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs (an internal class in System.IO.Pipes)
|
||||
internal sealed class UnixDomainSocketEndPoint : EndPoint
|
||||
@@ -1,16 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
{
|
||||
/// <summary>
|
||||
/// A specialisation of the OutOfProcessNodeInstance base class that uses a lightweight binary streaming protocol
|
||||
@@ -42,21 +41,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
private string _socketAddress;
|
||||
private VirtualConnectionClient _virtualConnectionClient;
|
||||
|
||||
public SocketNodeInstance(string projectPath, string[] watchFileExtensions, string socketAddress,
|
||||
ILogger nodeInstanceOutputLogger, IDictionary<string, string> environmentVars,
|
||||
int invocationTimeoutMilliseconds, bool launchWithDebugging, int debuggingPort)
|
||||
public SocketNodeInstance(NodeServicesOptions options, string socketAddress)
|
||||
: base(
|
||||
EmbeddedResourceReader.Read(
|
||||
typeof(SocketNodeInstance),
|
||||
"/Content/Node/entrypoint-socket.js"),
|
||||
projectPath,
|
||||
watchFileExtensions,
|
||||
options.ProjectPath,
|
||||
options.WatchFileExtensions,
|
||||
MakeNewCommandLineOptions(socketAddress),
|
||||
nodeInstanceOutputLogger,
|
||||
environmentVars,
|
||||
invocationTimeoutMilliseconds,
|
||||
launchWithDebugging,
|
||||
debuggingPort)
|
||||
options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables,
|
||||
options.InvocationTimeoutMilliseconds,
|
||||
options.LaunchWithDebugging,
|
||||
options.DebuggingPort)
|
||||
{
|
||||
_socketAddress = socketAddress;
|
||||
}
|
||||
@@ -79,7 +76,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
// wait for the same connection task. There's no reason why the first caller should have the
|
||||
// special ability to cancel the connection process in a way that would affect subsequent
|
||||
// callers. So, each caller just independently stops awaiting connection if that call is cancelled.
|
||||
await EnsureVirtualConnectionClientCreated().OrThrowOnCancellation(cancellationToken);
|
||||
await ThrowOnCancellation(EnsureVirtualConnectionClientCreated(), cancellationToken);
|
||||
}
|
||||
|
||||
// For each invocation, we open a new virtual connection. This gives an API equivalent to opening a new
|
||||
@@ -215,6 +212,17 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
return $"--listenAddress {listenAddress}";
|
||||
}
|
||||
|
||||
private static Task ThrowOnCancellation(Task task, CancellationToken cancellationToken)
|
||||
{
|
||||
return task.IsCompleted
|
||||
? task // If the task is already completed, no need to wrap it in a further layer of task
|
||||
: task.ContinueWith(
|
||||
_ => {}, // If the task completes, allow execution to continue
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.ExecuteSynchronously,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
#pragma warning disable 649 // These properties are populated via JSON deserialization
|
||||
private class RpcJsonResponse<TResult>
|
||||
{
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
|
||||
/// </summary>
|
||||
public static class NodeServicesOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
|
||||
/// Node.js instances and perform RPC calls over binary sockets (on Windows, this is
|
||||
/// implemented as named pipes; on other platforms it uses domain sockets).
|
||||
/// </summary>
|
||||
public static void UseSocketHosting(this NodeServicesOptions options)
|
||||
{
|
||||
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
|
||||
options.NodeInstanceFactory = () => new SocketNodeInstance(options, pipeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
import './Util/OverrideStdOutputs';
|
||||
import '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/OverrideStdOutputs';
|
||||
import * as net from 'net';
|
||||
import * as path from 'path';
|
||||
import * as readline from 'readline';
|
||||
import { Duplex } from 'stream';
|
||||
import { parseArgs } from './Util/ArgsUtil';
|
||||
import { exitWhenParentExits } from './Util/ExitWhenParentExits';
|
||||
import { parseArgs } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ArgsUtil';
|
||||
import { exitWhenParentExits } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ExitWhenParentExits';
|
||||
import * as virtualConnectionServer from './VirtualConnections/VirtualConnectionServer';
|
||||
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es3",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// A virtual read/write connection, typically to a remote process. Multiple virtual connections can be
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// A callback that will be invoked if the <see cref="VirtualConnectionClient"/> encounters a read error.
|
||||
18
src/Microsoft.AspNetCore.NodeServices.Sockets/package.json
Normal file
18
src/Microsoft.AspNetCore.NodeServices.Sockets/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "nodeservices.sockets",
|
||||
"version": "1.0.0",
|
||||
"description": "This is not really an NPM package and will not be published. This file exists only to reference compilation tools.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "./node_modules/.bin/webpack"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.42",
|
||||
"ts-loader": "^0.8.2",
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.1"
|
||||
}
|
||||
}
|
||||
39
src/Microsoft.AspNetCore.NodeServices.Sockets/project.json
Normal file
39
src/Microsoft.AspNetCore.NodeServices.Sockets/project.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"description": "Socket-based RPC for Microsoft.AspNetCore.NodeServices",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
},
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"embed": [
|
||||
"Content/**/*"
|
||||
],
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
"dependencies": {
|
||||
"Microsoft.Tpl.Dataflow": "4.5.24"
|
||||
}
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"dependencies": {
|
||||
"System.IO.Pipes": "4.3.0",
|
||||
"System.Threading.Tasks.Dataflow": "4.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
target: 'node',
|
||||
externals: ['fs', 'net', 'events', 'readline', 'stream'],
|
||||
resolve: {
|
||||
extensions: [ '.ts' ]
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.ts$/, loader: 'ts-loader' },
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
'entrypoint-socket': ['./TypeScript/SocketNodeInstanceEntryPoint'],
|
||||
},
|
||||
output: {
|
||||
libraryTarget: 'commonjs',
|
||||
path: './Content/Node',
|
||||
filename: '[name].js'
|
||||
}
|
||||
};
|
||||
@@ -1,2 +1,3 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a way of creating and invoking code in a Node.js environment.
|
||||
/// </summary>
|
||||
public enum NodeHostingModel
|
||||
{
|
||||
/// <summary>
|
||||
/// An out-of-process Node.js instance where RPC calls are made via HTTP.
|
||||
/// </summary>
|
||||
Http,
|
||||
|
||||
/// <summary>
|
||||
/// An out-of-process Node.js instance where RPC calls are made over binary sockets.
|
||||
/// </summary>
|
||||
Socket,
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
@@ -19,33 +18,8 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
throw new ArgumentNullException(nameof (options));
|
||||
}
|
||||
|
||||
return new NodeServicesImpl(() => CreateNodeInstance(options));
|
||||
}
|
||||
|
||||
private static INodeInstance CreateNodeInstance(NodeServicesOptions options)
|
||||
{
|
||||
if (options.NodeInstanceFactory != null)
|
||||
{
|
||||
// If you've explicitly supplied an INodeInstance factory, we'll use that. This is useful for
|
||||
// custom INodeInstance implementations.
|
||||
return options.NodeInstanceFactory();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (options.HostingModel)
|
||||
{
|
||||
case NodeHostingModel.Http:
|
||||
return new HttpNodeInstance(options.ProjectPath, options.WatchFileExtensions, options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0);
|
||||
case NodeHostingModel.Socket:
|
||||
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
|
||||
return new SocketNodeInstance(options.ProjectPath, options.WatchFileExtensions, pipeName, options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort);
|
||||
default:
|
||||
throw new ArgumentException("Unknown hosting model: " + options.HostingModel);
|
||||
}
|
||||
}
|
||||
return new NodeServicesImpl(options.NodeInstanceFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,6 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
/// </summary>
|
||||
public class NodeServicesOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the default <see cref="NodeHostingModel"/>.
|
||||
/// </summary>
|
||||
public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http;
|
||||
|
||||
internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds);
|
||||
private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000;
|
||||
private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices";
|
||||
@@ -36,7 +31,6 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
|
||||
EnvironmentVariables = new Dictionary<string, string>();
|
||||
InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds;
|
||||
HostingModel = DefaultNodeHostingModel;
|
||||
WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone();
|
||||
|
||||
// In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few
|
||||
@@ -53,15 +47,15 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
NodeInstanceOutputLogger = loggerFactory != null
|
||||
? loggerFactory.CreateLogger(LogCategoryName)
|
||||
: new ConsoleLogger(LogCategoryName, null, false);
|
||||
|
||||
// By default, we use this package's built-in out-of-process-via-HTTP hosting/transport
|
||||
this.UseHttpHosting();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which <see cref="NodeHostingModel"/> should be used.
|
||||
/// </summary>
|
||||
public NodeHostingModel HostingModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, this callback function will be invoked to supply the <see cref="INodeServices"/> instance.
|
||||
/// Specifies how to construct Node.js instances. An <see cref="INodeInstance"/> encapsulates all details about
|
||||
/// how Node.js instances are launched and communicated with. A new <see cref="INodeInstance"/> will be created
|
||||
/// automatically if the previous instance has terminated (e.g., because a source file changed).
|
||||
/// </summary>
|
||||
public Func<INodeInstance> NodeInstanceFactory { get; set; }
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
@@ -36,21 +34,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
private bool _disposed;
|
||||
private int _portNumber;
|
||||
|
||||
public HttpNodeInstance(string projectPath, string[] watchFileExtensions, ILogger nodeInstanceOutputLogger,
|
||||
IDictionary<string, string> environmentVars, int invocationTimeoutMilliseconds, bool launchWithDebugging,
|
||||
int debuggingPort, int port = 0)
|
||||
public HttpNodeInstance(NodeServicesOptions options, int port = 0)
|
||||
: base(
|
||||
EmbeddedResourceReader.Read(
|
||||
typeof(HttpNodeInstance),
|
||||
"/Content/Node/entrypoint-http.js"),
|
||||
projectPath,
|
||||
watchFileExtensions,
|
||||
options.ProjectPath,
|
||||
options.WatchFileExtensions,
|
||||
MakeCommandLineOptions(port),
|
||||
nodeInstanceOutputLogger,
|
||||
environmentVars,
|
||||
invocationTimeoutMilliseconds,
|
||||
launchWithDebugging,
|
||||
debuggingPort)
|
||||
options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables,
|
||||
options.InvocationTimeoutMilliseconds,
|
||||
options.LaunchWithDebugging,
|
||||
options.DebuggingPort)
|
||||
{
|
||||
_client = new HttpClient();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
|
||||
/// </summary>
|
||||
public static class NodeServicesOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
|
||||
/// Node.js instances and perform RPC calls over HTTP.
|
||||
/// </summary>
|
||||
public static void UseHttpHosting(this NodeServicesOptions options)
|
||||
{
|
||||
options.NodeInstanceFactory = () => new HttpNodeInstance(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
return InvokeExportWithPossibleRetryAsync<T>(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
||||
private async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
||||
{
|
||||
ThrowAnyOutstandingDelayedDisposalException();
|
||||
var nodeInstance = GetOrCreateCurrentNodeInstance();
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
public sealed class StringAsTempFile : IDisposable
|
||||
{
|
||||
private bool _disposedValue;
|
||||
private bool _hasDeletedTempFile;
|
||||
private object _fileDeletionLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of <see cref="StringAsTempFile"/>.
|
||||
@@ -18,6 +20,18 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
FileName = Path.GetTempFileName();
|
||||
File.WriteAllText(FileName, content);
|
||||
|
||||
// Because .NET finalizers don't reliably run when the process is terminating, also
|
||||
// add event handlers for other shutdown scenarios.
|
||||
#if NET451
|
||||
AppDomain.CurrentDomain.ProcessExit += HandleProcessExit;
|
||||
AppDomain.CurrentDomain.DomainUnload += HandleProcessExit;
|
||||
#else
|
||||
// Note that this still doesn't capture SIGKILL (at least on macOS) - there doesn't
|
||||
// appear to be a way of doing that. So in that case, the temporary file will be
|
||||
// left behind.
|
||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += HandleAssemblyUnloading;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -40,15 +54,45 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Would dispose managed state here, if there was any
|
||||
// Dispose managed state
|
||||
#if NET451
|
||||
AppDomain.CurrentDomain.ProcessExit -= HandleProcessExit;
|
||||
AppDomain.CurrentDomain.DomainUnload -= HandleProcessExit;
|
||||
#else
|
||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading -= HandleAssemblyUnloading;
|
||||
#endif
|
||||
}
|
||||
|
||||
File.Delete(FileName);
|
||||
EnsureTempFileDeleted();
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureTempFileDeleted()
|
||||
{
|
||||
lock (_fileDeletionLock)
|
||||
{
|
||||
if (!_hasDeletedTempFile)
|
||||
{
|
||||
File.Delete(FileName);
|
||||
_hasDeletedTempFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NET451
|
||||
private void HandleProcessExit(object sender, EventArgs args)
|
||||
{
|
||||
EnsureTempFileDeleted();
|
||||
}
|
||||
#else
|
||||
private void HandleAssemblyUnloading(System.Runtime.Loader.AssemblyLoadContext context)
|
||||
{
|
||||
EnsureTempFileDeleted();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"description": "Invoke Node.js modules at runtime in ASP.NET Core applications.",
|
||||
"version": "1.0.0-*",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,26 +21,18 @@
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"NETStandard.Library": "1.6.0"
|
||||
"NETStandard.Library": "1.6.1-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
"frameworkAssemblies": {
|
||||
"System.Net.Http": "4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.Tpl.Dataflow": "4.5.24"
|
||||
}
|
||||
},
|
||||
"net451": {},
|
||||
"netstandard1.6": {
|
||||
"dependencies": {
|
||||
"System.Diagnostics.Process": "4.1.0",
|
||||
"System.IO.Pipes": "4.0.0",
|
||||
"System.Threading.Tasks.Dataflow": "4.6.0"
|
||||
"System.Diagnostics.Process": "4.3.0",
|
||||
"System.IO.FileSystem.Watcher": "4.3.0",
|
||||
"System.Runtime.Loader": "4.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,8 +10,7 @@ module.exports = {
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
'entrypoint-http': ['./TypeScript/HttpNodeInstanceEntryPoint'],
|
||||
'entrypoint-socket': ['./TypeScript/SocketNodeInstanceEntryPoint'],
|
||||
'entrypoint-http': ['./TypeScript/HttpNodeInstanceEntryPoint']
|
||||
},
|
||||
output: {
|
||||
libraryTarget: 'commonjs',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"description": "Helpers for building React applications on ASP.NET Core.",
|
||||
"version": "1.0.0-*",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -18,8 +18,8 @@
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
||||
@@ -119,7 +119,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
unencodedAbsoluteUrl,
|
||||
unencodedPathAndQuery,
|
||||
CustomDataParameter,
|
||||
TimeoutMillisecondsParameter);
|
||||
TimeoutMillisecondsParameter,
|
||||
request.PathBase.ToString());
|
||||
|
||||
if (!string.IsNullOrEmpty(result.RedirectUrl))
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
/// <param name="requestPathAndQuery">The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
||||
/// <param name="customDataParameter">An optional JSON-serializable parameter to be supplied to the prerendering code.</param>
|
||||
/// <param name="timeoutMilliseconds">The maximum duration to wait for prerendering to complete.</param>
|
||||
/// <param name="requestPathBase">The PathBase for the currently-executing HTTP request.</param>
|
||||
/// <returns></returns>
|
||||
public static Task<RenderToStringResult> RenderToString(
|
||||
string applicationBasePath,
|
||||
@@ -38,7 +39,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
string requestAbsoluteUrl,
|
||||
string requestPathAndQuery,
|
||||
object customDataParameter,
|
||||
int timeoutMilliseconds)
|
||||
int timeoutMilliseconds,
|
||||
string requestPathBase)
|
||||
{
|
||||
return nodeServices.InvokeExportAsync<RenderToStringResult>(
|
||||
NodeScript.Value.FileName,
|
||||
@@ -48,7 +50,8 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
requestAbsoluteUrl,
|
||||
requestPathAndQuery,
|
||||
customDataParameter,
|
||||
timeoutMilliseconds);
|
||||
timeoutMilliseconds,
|
||||
requestPathBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,11 +48,14 @@ Instead, what `SpaServices` offers is ASP.NET Core APIs that know how to invoke
|
||||
|
||||
### 1. Enable the asp-prerender-* tag helpers
|
||||
|
||||
Make sure you've installed the `Microsoft.AspNetCore.SpaServices` NuGet package and the `aspnet-prerendering` NPM package. Together these contain the server-side and client-side library code you'll need.
|
||||
Make sure you've installed into your project:
|
||||
|
||||
Now go to your `Views/_ViewImports.cshtml` file, and add the following line:
|
||||
* The `Microsoft.AspNetCore.SpaServices` NuGet package, version 1.1.0-* or later
|
||||
* The `aspnet-prerendering` NPM package, version 2.0.1 or later
|
||||
|
||||
@addTagHelper *, Microsoft.AspNetCore.SpaServices
|
||||
Together these contain the server-side and client-side library code you'll need. Now go to your `Views/_ViewImports.cshtml` file, and add the following line:
|
||||
|
||||
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"
|
||||
|
||||
### 2. Use asp-prerender-* in a view
|
||||
|
||||
@@ -67,7 +70,9 @@ If you run your application now, and browse to whatever page renders the view yo
|
||||
Create a JavaScript file at the path matching the `asp-prerender-module` value you specified above. In this example, that means creating a folder called `ClientApp` at the root of your project, and creating a file inside it called `boot-server.js`. Try putting the following into it:
|
||||
|
||||
```javascript
|
||||
module.exports = function(params) {
|
||||
var prerendering = require('aspnet-prerendering');
|
||||
|
||||
module.exports = prerendering.createServerRenderer(function(params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var result = '<h1>Hello world!</h1>'
|
||||
+ '<p>Current time in Node is: ' + new Date() + '</p>'
|
||||
@@ -76,7 +81,7 @@ module.exports = function(params) {
|
||||
|
||||
resolve({ html: result });
|
||||
});
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
If you try running your app now, you should see the HTML snippet generated by your JavaScript getting injected into your page.
|
||||
@@ -98,7 +103,9 @@ For example, in your `cshtml`,
|
||||
Now in your JavaScript prerendering function, you can access this data by reading `params.data`, e.g.:
|
||||
|
||||
```javascript
|
||||
module.exports = function(params) {
|
||||
var prerendering = require('aspnet-prerendering');
|
||||
|
||||
module.exports = prerendering.createServerRenderer(function(params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var result = '<h1>Hello world!</h1>'
|
||||
+ '<p>Is gold user: ' + params.data.isGoldUser + '</p>'
|
||||
@@ -106,7 +113,7 @@ module.exports = function(params) {
|
||||
|
||||
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.
|
||||
@@ -182,7 +189,9 @@ If you don't already have a `tsconfig.json` file at the root of your project, ad
|
||||
Now you can delete `ClientApp/boot-server.js`, and in its place, create `ClientApp/boot-server.ts`, containing the TypeScript equivalent of what you had before:
|
||||
|
||||
```javascript
|
||||
export default function (params: any): Promise<{ html: string}> {
|
||||
import { createServerRenderer } from 'aspnet-prerendering';
|
||||
|
||||
export default createServerRenderer(params => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const html = `
|
||||
<h1>Hello world!</h1>
|
||||
@@ -192,7 +201,7 @@ export default function (params: any): Promise<{ html: string}> {
|
||||
|
||||
resolve({ html });
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Finally, run `webpack` on the command line to build `ClientApp/dist/main-server.js`. Then you can tell `SpaServices` to use that file for server-side prerendering. In your MVC view where you use `aspnet-prerender-module`, update the attribute value:
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Microsoft.AspNetCore.SpaServices.Webpack
|
||||
_pathPrefix = pathPrefix;
|
||||
_options = options;
|
||||
_httpClient = new HttpClient(new HttpClientHandler());
|
||||
_httpClient.Timeout = _options.RequestTimeout;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Webpack
|
||||
{
|
||||
internal class ConditionalProxyMiddlewareOptions
|
||||
{
|
||||
public ConditionalProxyMiddlewareOptions(string scheme, string host, string port)
|
||||
public ConditionalProxyMiddlewareOptions(string scheme, string host, string port, TimeSpan requestTimeout)
|
||||
{
|
||||
Scheme = scheme;
|
||||
Host = host;
|
||||
Port = port;
|
||||
RequestTimeout = requestTimeout;
|
||||
}
|
||||
|
||||
public string Scheme { get; }
|
||||
public string Host { get; }
|
||||
public string Port { get; }
|
||||
public TimeSpan RequestTimeout { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices;
|
||||
using Microsoft.AspNetCore.SpaServices.Webpack;
|
||||
@@ -7,6 +8,7 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
@@ -15,8 +17,6 @@ namespace Microsoft.AspNetCore.Builder
|
||||
/// </summary>
|
||||
public static class WebpackDevMiddleware
|
||||
{
|
||||
private const string WebpackDevMiddlewareScheme = "http";
|
||||
private const string WebpackHotMiddlewareEndpoint = "/__webpack_hmr";
|
||||
private const string DefaultConfigFile = "webpack.config.js";
|
||||
|
||||
/// <summary>
|
||||
@@ -75,12 +75,18 @@ namespace Microsoft.AspNetCore.Builder
|
||||
"/Content/Node/webpack-dev-middleware.js");
|
||||
var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
|
||||
|
||||
// Ideally, this would be relative to the application's PathBase (so it could work in virtual directories)
|
||||
// but it's not clear that such information exists during application startup, as opposed to within the context
|
||||
// of a request.
|
||||
var hmrEndpoint = "/__webpack_hmr";
|
||||
|
||||
// Tell Node to start the server hosting webpack-dev-middleware
|
||||
var devServerOptions = new
|
||||
{
|
||||
webpackConfigPath = Path.Combine(nodeServicesOptions.ProjectPath, options.ConfigFile ?? DefaultConfigFile),
|
||||
suppliedOptions = options,
|
||||
understandsMultiplePublicPaths = true
|
||||
understandsMultiplePublicPaths = true,
|
||||
hotModuleReplacementEndpointUrl = hmrEndpoint
|
||||
};
|
||||
var devServerInfo =
|
||||
nodeServices.InvokeExportAsync<WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer",
|
||||
@@ -94,33 +100,30 @@ namespace Microsoft.AspNetCore.Builder
|
||||
}
|
||||
|
||||
// Proxy the corresponding requests through ASP.NET and into the Node listener
|
||||
// Anything under /<publicpath> (e.g., /dist) is proxied as a normal HTTP request with a typical timeout (100s is the default from HttpClient),
|
||||
// plus /__webpack_hmr is proxied with infinite timeout, because it's an EventSource (long-lived request).
|
||||
foreach (var publicPath in devServerInfo.PublicPaths)
|
||||
{
|
||||
appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath, devServerInfo.Port, TimeSpan.FromSeconds(100));
|
||||
}
|
||||
appBuilder.UseProxyToLocalWebpackDevMiddleware(hmrEndpoint, devServerInfo.Port, Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
|
||||
private static void UseProxyToLocalWebpackDevMiddleware(this IApplicationBuilder appBuilder, string publicPath, int proxyToPort, TimeSpan requestTimeout)
|
||||
{
|
||||
// Note that this is hardcoded to make requests to "localhost" regardless of the hostname of the
|
||||
// server as far as the client is concerned. This is because ConditionalProxyMiddlewareOptions is
|
||||
// the one making the internal HTTP requests, and it's going to be to some port on this machine
|
||||
// because aspnet-webpack hosts the dev server there. We can't use the hostname that the client
|
||||
// sees, because that could be anything (e.g., some upstream load balancer) and we might not be
|
||||
// able to make outbound requests to it from here.
|
||||
var proxyOptions = new ConditionalProxyMiddlewareOptions(WebpackDevMiddlewareScheme,
|
||||
"localhost", devServerInfo.Port.ToString());
|
||||
foreach (var publicPath in devServerInfo.PublicPaths)
|
||||
{
|
||||
appBuilder.UseMiddleware<ConditionalProxyMiddleware>(publicPath, proxyOptions);
|
||||
}
|
||||
|
||||
// While it would be nice to proxy the /__webpack_hmr requests too, these return an EventStream,
|
||||
// and the Microsoft.AspNetCore.Proxy code doesn't handle that entirely - it throws an exception after
|
||||
// a while. So, just serve a 302 for those. But note that we must use the hostname that the client
|
||||
// sees, not "localhost", so that it works even when you're not running on localhost (e.g., Docker).
|
||||
appBuilder.Map(WebpackHotMiddlewareEndpoint, builder =>
|
||||
{
|
||||
builder.Use(next => ctx =>
|
||||
{
|
||||
var hostname = ctx.Request.Host.Host;
|
||||
ctx.Response.Redirect(
|
||||
$"{WebpackDevMiddlewareScheme}://{hostname}:{devServerInfo.Port.ToString()}{WebpackHotMiddlewareEndpoint}");
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
// Also note that the webpack HMR service always uses HTTP, even if your app server uses HTTPS,
|
||||
// because the HMR service has no need for HTTPS (the client doesn't see it directly - all traffic
|
||||
// to it is proxied), and the HMR service couldn't use HTTPS anyway (in general it wouldn't have
|
||||
// the necessary certificate).
|
||||
var proxyOptions = new ConditionalProxyMiddlewareOptions(
|
||||
"http", "localhost", proxyToPort.ToString(), requestTimeout);
|
||||
appBuilder.UseMiddleware<ConditionalProxyMiddleware>(publicPath, proxyOptions);
|
||||
}
|
||||
|
||||
#pragma warning disable CS0649
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aspnet-prerendering",
|
||||
"version": "2.0.0",
|
||||
"version": "2.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": {
|
||||
@@ -17,7 +17,7 @@
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"domain-task": "^2.0.1"
|
||||
"domain-task": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.42",
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import * as domain from 'domain';
|
||||
import { run as domainTaskRun } from 'domain-task/main';
|
||||
import { baseUrl } from 'domain-task/fetch';
|
||||
import { run as domainTaskRun, baseUrl as domainTaskBaseUrl } from 'domain-task/main';
|
||||
|
||||
const defaultTimeoutMilliseconds = 30 * 1000;
|
||||
|
||||
export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
|
||||
const resultFunc = (callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) => {
|
||||
const resultFunc = (callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number, requestPathBase: string) => {
|
||||
// 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.
|
||||
let domainTaskCompletionPromiseResolve;
|
||||
@@ -20,6 +19,7 @@ export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
|
||||
location: url.parse(requestPathAndQuery),
|
||||
origin: parsedAbsoluteRequestUrl.protocol + '//' + parsedAbsoluteRequestUrl.host,
|
||||
url: requestPathAndQuery,
|
||||
baseUrl: (requestPathBase || '') + '/',
|
||||
absoluteUrl: absoluteRequestUrl,
|
||||
domainTasks: domainTaskCompletionPromise,
|
||||
data: customDataParameter
|
||||
@@ -33,7 +33,7 @@ export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
|
||||
bindPromiseContinuationsToDomain(domainTaskCompletionPromise, domain['active']);
|
||||
|
||||
// Make the base URL available to the 'domain-tasks/fetch' helper within this execution context
|
||||
baseUrl(absoluteRequestUrl);
|
||||
domainTaskBaseUrl(absoluteRequestUrl);
|
||||
|
||||
// Begin rendering, and apply a timeout
|
||||
const bootFuncPromise = bootFunc(params);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
interface RenderToStringFunc {
|
||||
(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number): void;
|
||||
(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number, requestPathBase: string): void;
|
||||
}
|
||||
|
||||
interface RenderToStringCallback {
|
||||
@@ -23,6 +23,7 @@ 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'
|
||||
baseUrl: string; // e.g., '' or '/myVirtualDir'
|
||||
absoluteUrl: string; // e.g., 'https://example.com:1234/some/path'
|
||||
domainTasks: Promise<any>;
|
||||
data: any; // any custom object passed through from .NET
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aspnet-webpack",
|
||||
"version": "1.0.24",
|
||||
"version": "1.0.25",
|
||||
"description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface CreateDevServerCallback {
|
||||
interface CreateDevServerOptions {
|
||||
webpackConfigPath: string;
|
||||
suppliedOptions: DevServerOptions;
|
||||
hotModuleReplacementEndpointUrl: string;
|
||||
}
|
||||
|
||||
// These are the options configured in C# and then JSON-serialized, hence the C#-style naming
|
||||
@@ -28,7 +29,7 @@ interface DevServerOptions {
|
||||
ReactHotModuleReplacement: boolean;
|
||||
}
|
||||
|
||||
function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configuration, enableHotModuleReplacement: boolean, enableReactHotModuleReplacement: boolean, hmrEndpoint: string) {
|
||||
function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configuration, enableHotModuleReplacement: boolean, enableReactHotModuleReplacement: boolean, hmrClientEndpoint: string, hmrServerEndpoint: string) {
|
||||
// Build the final Webpack config based on supplied options
|
||||
if (enableHotModuleReplacement) {
|
||||
// For this, we only support the key/value config format, not string or string[], since
|
||||
@@ -44,7 +45,7 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
|
||||
// Augment all entry points so they support HMR (unless they already do)
|
||||
Object.getOwnPropertyNames(entryPoints).forEach(entryPointName => {
|
||||
const webpackHotMiddlewareEntryPoint = 'webpack-hot-middleware/client';
|
||||
const webpackHotMiddlewareOptions = `?path=` + encodeURIComponent(hmrEndpoint);
|
||||
const webpackHotMiddlewareOptions = `?path=` + encodeURIComponent(hmrClientEndpoint);
|
||||
if (typeof entryPoints[entryPointName] === 'string') {
|
||||
entryPoints[entryPointName] = [webpackHotMiddlewareEntryPoint + webpackHotMiddlewareOptions, entryPoints[entryPointName]];
|
||||
} else if (firstIndexOfStringStartingWith(entryPoints[entryPointName], webpackHotMiddlewareEntryPoint) < 0) {
|
||||
@@ -117,7 +118,9 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
|
||||
} catch (ex) {
|
||||
throw new Error('HotModuleReplacement failed because of an error while loading \'webpack-hot-middleware\'. Error was: ' + ex.stack);
|
||||
}
|
||||
app.use(webpackHotMiddlewareModule(compiler));
|
||||
app.use(webpackHotMiddlewareModule(compiler, {
|
||||
path: hmrServerEndpoint
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,8 +201,16 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
|
||||
}
|
||||
normalizedPublicPaths.push(removeTrailingSlash(publicPath));
|
||||
|
||||
const hmrEndpoint = `http://localhost:${listener.address().port}/__webpack_hmr`;
|
||||
attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrEndpoint);
|
||||
// Newer versions of Microsoft.AspNetCore.SpaServices will explicitly pass an HMR endpoint URL
|
||||
// (because it's relative to the app's URL space root, which the client doesn't otherwise know).
|
||||
// For back-compatibility, fall back on connecting directly to the underlying HMR server (though
|
||||
// that won't work if the app is hosted on HTTPS because of the mixed-content rule, and we can't
|
||||
// run the HMR server itself on HTTPS because in general it has no valid cert).
|
||||
const hmrClientEndpoint = options.hotModuleReplacementEndpointUrl // The URL that we'll proxy (e.g., /__asp_webpack_hmr)
|
||||
|| `http://localhost:${listener.address().port}/__webpack_hmr`; // Fall back on absolute URL to bypass proxying
|
||||
const hmrServerEndpoint = options.hotModuleReplacementEndpointUrl
|
||||
|| '/__webpack_hmr'; // URL is relative to webpack dev server root
|
||||
attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrClientEndpoint, hmrServerEndpoint);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "domain-task",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"description": "Tracks outstanding operations for a logical thread of execution",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import * as url from 'url';
|
||||
import * as domain from 'domain';
|
||||
import * as domainContext from 'domain-context';
|
||||
import { baseUrl } from './main';
|
||||
const isomorphicFetch = require('isomorphic-fetch');
|
||||
const isNode = typeof process === 'object' && process.versions && !!process.versions.node;
|
||||
|
||||
// Not using a symbol, because this may need to run in a version of Node.js that doesn't support them
|
||||
const domainTaskStateKey = '__DOMAIN_TASK_INTERNAL_FETCH_BASEURL__DO_NOT_REFERENCE_THIS__';
|
||||
let noDomainBaseUrl: string;
|
||||
|
||||
function issueRequest(baseUrl: string, req: string | Request, init?: RequestInit): Promise<any> {
|
||||
// Resolve relative URLs
|
||||
if (baseUrl) {
|
||||
@@ -70,16 +67,6 @@ export function fetch(url: string | Request, init?: RequestInit): Promise<any> {
|
||||
return issueRequest(baseUrl(), url, init);
|
||||
}
|
||||
|
||||
export function baseUrl(url?: string): string {
|
||||
if (url) {
|
||||
if (domain.active) {
|
||||
// There's an active domain (e.g., in Node.js), so associate the base URL with it
|
||||
domainContext.set(domainTaskStateKey, url);
|
||||
} else {
|
||||
// There's no active domain (e.g., in browser), so there's just one shared base URL
|
||||
noDomainBaseUrl = url;
|
||||
}
|
||||
}
|
||||
|
||||
return domain.active ? domainContext.get(domainTaskStateKey) : noDomainBaseUrl;
|
||||
}
|
||||
// Re-exporting baseUrl from this module for back-compatibility only
|
||||
// Newer code that wants to access baseUrl should use the version exported from the root of this package
|
||||
export { baseUrl } from './main';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// This file determines the top-level package exports
|
||||
export { addTask, run } from './main';
|
||||
export { addTask, run, baseUrl } from './main';
|
||||
export { fetch } from './fetch';
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import * as domain from 'domain';
|
||||
import * as domainContext from 'domain-context';
|
||||
|
||||
// Not using symbols, because this may need to run in a version of Node.js that doesn't support them
|
||||
const domainTasksStateKey = '__DOMAIN_TASKS';
|
||||
const domainTaskBaseUrlStateKey = '__DOMAIN_TASK_INTERNAL_FETCH_BASEURL__DO_NOT_REFERENCE_THIS__';
|
||||
|
||||
let noDomainBaseUrl: string;
|
||||
|
||||
export function addTask(task: PromiseLike<any>) {
|
||||
if (task && domain.active) {
|
||||
@@ -57,6 +62,20 @@ export function run<T>(codeToRun: () => T, completionCallback: (error: any) => v
|
||||
return synchronousResult;
|
||||
}
|
||||
|
||||
export function baseUrl(url?: string): string {
|
||||
if (url) {
|
||||
if (domain.active) {
|
||||
// There's an active domain (e.g., in Node.js), so associate the base URL with it
|
||||
domainContext.set(domainTaskBaseUrlStateKey, url);
|
||||
} else {
|
||||
// There's no active domain (e.g., in browser), so there's just one shared base URL
|
||||
noDomainBaseUrl = url;
|
||||
}
|
||||
}
|
||||
|
||||
return domain.active ? domainContext.get(domainTaskBaseUrlStateKey) : noDomainBaseUrl;
|
||||
}
|
||||
|
||||
interface DomainTasksState {
|
||||
numRemainingTasks: number;
|
||||
hasIssuedSuccessCallback: boolean;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"description": "Helpers for building single-page applications on ASP.NET MVC Core",
|
||||
"version": "1.0.0-*",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,8 +21,8 @@
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.NodeServices": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AppComponent } from './components/app/app.component'
|
||||
import { NavMenuComponent } from './components/navmenu/navmenu.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
|
||||
import { CounterComponent } from './components/counter/counter.component';
|
||||
import { CounterComponent } from 'ClientApp/app/components/counter/counter.component';
|
||||
|
||||
@NgModule({
|
||||
bootstrap: [ AppComponent ],
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
FROM microsoft/dotnet:1.0.0-preview2-onbuild
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
RUN apt-get update
|
||||
RUN wget -qO- https://deb.nodesource.com/setup_4.x | bash -
|
||||
RUN apt-get install -y build-essential nodejs
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"es6-shim": "^0.35.1",
|
||||
"event-source-polyfill": "^0.0.7",
|
||||
"expose-loader": "^0.7.1",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"extract-text-webpack-plugin": "^2.0.0-beta",
|
||||
"file-loader": "^0.9.0",
|
||||
"html-loader": "^0.4.4",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
@@ -39,10 +39,10 @@
|
||||
"rxjs": "5.0.0-beta.12",
|
||||
"style-loader": "^0.13.1",
|
||||
"to-string-loader": "^1.1.5",
|
||||
"ts-loader": "^0.8.2",
|
||||
"typescript": "^2.0.3",
|
||||
"ts-loader": "^1.3.0",
|
||||
"typescript": "^2.1.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.13.2",
|
||||
"webpack": "^2.1.0-beta",
|
||||
"webpack-hot-middleware": "^2.12.2",
|
||||
"webpack-merge": "^0.14.1",
|
||||
"zone.js": "^0.6.25"
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.AngularServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"*": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"sourceMap": true,
|
||||
|
||||
@@ -6,7 +6,13 @@ var merge = require('webpack-merge');
|
||||
// Configuration in common to both client-side and server-side bundles
|
||||
var sharedConfig = {
|
||||
context: __dirname,
|
||||
resolve: { extensions: [ '', '.js', '.ts' ] },
|
||||
resolve: {
|
||||
extensions: [ '.js', '.ts' ],
|
||||
modules: [
|
||||
'node_modules',
|
||||
'.'
|
||||
]
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
|
||||
@@ -46,7 +52,7 @@ var clientBundleConfig = merge(sharedConfig, {
|
||||
|
||||
// Configuration for server-side (prerendering) bundle suitable for running in Node
|
||||
var serverBundleConfig = merge(sharedConfig, {
|
||||
resolve: { packageMains: ['main'] },
|
||||
resolve: { mainFields: ['main'] },
|
||||
entry: { 'main-server': './ClientApp/boot-server.ts' },
|
||||
plugins: [
|
||||
new webpack.DllReferencePlugin({
|
||||
|
||||
@@ -6,7 +6,7 @@ var merge = require('webpack-merge');
|
||||
var extractCSS = new ExtractTextPlugin('vendor.css');
|
||||
|
||||
var sharedConfig = {
|
||||
resolve: { extensions: [ '', '.js' ] },
|
||||
resolve: { extensions: [ '.js' ] },
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.json$/, loader: require.resolve('json-loader') },
|
||||
@@ -68,7 +68,7 @@ var clientBundleConfig = merge(sharedConfig, {
|
||||
|
||||
var serverBundleConfig = merge(sharedConfig, {
|
||||
target: 'node',
|
||||
resolve: { packageMains: ['main'] },
|
||||
resolve: { mainFields: ['main'] },
|
||||
output: {
|
||||
path: path.join(__dirname, 'ClientApp', 'dist'),
|
||||
libraryTarget: 'commonjs2',
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
FROM microsoft/dotnet:1.0.0-preview2-onbuild
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
RUN apt-get update
|
||||
RUN wget -qO- https://deb.nodesource.com/setup_4.x | bash -
|
||||
RUN apt-get install -y build-essential nodejs
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
@@ -40,7 +40,10 @@
|
||||
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true
|
||||
"preserveCompilationContext": true,
|
||||
"compile": {
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
},
|
||||
|
||||
"runtimeOptions": {
|
||||
@@ -52,10 +55,12 @@
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"ClientApp/dist",
|
||||
"Views",
|
||||
"web.config",
|
||||
"wwwroot"
|
||||
],
|
||||
"exclude": [
|
||||
"wwwroot/dist/*.map"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -65,7 +70,7 @@
|
||||
"node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod",
|
||||
"node node_modules/webpack/bin/webpack.js --env.prod"
|
||||
],
|
||||
"postpublish": "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
},
|
||||
|
||||
"tooling": {
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
FROM microsoft/dotnet:latest
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
RUN apt-get update
|
||||
RUN wget -qO- https://deb.nodesource.com/setup_4.x | bash -
|
||||
RUN apt-get install -y build-essential nodejs
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
@@ -55,7 +55,6 @@
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"node_modules",
|
||||
"Views",
|
||||
"web.config",
|
||||
"wwwroot"
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
FROM microsoft/dotnet:latest
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
RUN apt-get update
|
||||
RUN wget -qO- https://deb.nodesource.com/setup_4.x | bash -
|
||||
RUN apt-get install -y build-essential nodejs
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
FROM microsoft/dotnet:latest
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
RUN apt-get update
|
||||
RUN wget -qO- https://deb.nodesource.com/setup_4.x | bash -
|
||||
RUN apt-get install -y build-essential nodejs
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
@@ -55,7 +55,6 @@
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"node_modules",
|
||||
"Views",
|
||||
"web.config",
|
||||
"wwwroot"
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
FROM microsoft/dotnet:latest
|
||||
FROM microsoft/dotnet:1.1.0-sdk-projectjson
|
||||
|
||||
COPY . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY project.json .
|
||||
RUN ["dotnet", "restore"]
|
||||
|
||||
COPY . /app
|
||||
RUN ["dotnet", "build"]
|
||||
|
||||
EXPOSE 5000/tcp
|
||||
|
||||
ENTRYPOINT ["dotnet", "run", "--server.urls", "http://0.0.0.0:5000"]
|
||||
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"sdk": { "version": "1.0.0-preview2-003121" }
|
||||
"sdk": { "version": "1.0.0-preview2-1-003177" }
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0"
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"netcoreapp1.1": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generator-aspnetcore-spa",
|
||||
"version": "0.6.2",
|
||||
"version": "0.7.1",
|
||||
"description": "Single-Page App templates for ASP.NET Core",
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
Reference in New Issue
Block a user