Compare commits

..

1 Commits

Author SHA1 Message Date
Smit Patel
1e19873874 Cleanup NuGet.config 2017-07-10 17:15:22 -07:00
79 changed files with 389 additions and 18813 deletions

2
.gitignore vendored
View File

@@ -28,8 +28,6 @@ nuget.exe
.vs/ .vs/
npm-debug.log npm-debug.log
/.build/ /.build/
global.json
*.g.targets
# The templates can't contain their own .gitignore files, because Yeoman has strange default handling for # The templates can't contain their own .gitignore files, because Yeoman has strange default handling for
# files with that name (https://github.com/npm/npm/issues/1862). So, each template instead has a template_gitignore # files with that name (https://github.com/npm/npm/issues/1862). So, each template instead has a template_gitignore

View File

@@ -1,9 +0,0 @@
<Project>
<Import Project="version.props" />
<Import Project="build\dependencies.props" />
<Import Project="build\sources.props" />
<PropertyGroup>
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
</PropertyGroup>
</Project>

View File

@@ -1,6 +0,0 @@
<Project>
<PropertyGroup>
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
</PropertyGroup>
</Project>

View File

@@ -1,12 +1,10 @@
Copyright (c) .NET Foundation and Contributors Copyright (c) .NET Foundation. All rights reserved.
All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the these files except in compliance with the License. You may obtain a copy of the
License at License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR

View File

@@ -2,6 +2,7 @@
<configuration> <configuration>
<packageSources> <packageSources>
<clear /> <clear />
<!-- Restore sources should be defined in build/sources.props. --> <add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-master/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
</packageSources> </packageSources>
</configuration> </configuration>

View File

@@ -94,7 +94,7 @@ If you're interested in contributing to the various packages, samples, and proje
* Run `dotnet restore` at the repo root dir * Run `dotnet restore` at the repo root dir
* Go to whatever sample or template you want to run (for example, `cd templates/AngularSpa`) * Go to whatever sample or template you want to run (for example, `cd templates/AngularSpa`)
* Restore NPM dependencies (run `npm install`) * Restore NPM dependencies (run `npm install`)
* If the sample/template you're trying to run has a file called `webpack.config.vendor.js` at its root, run `webpack --config webpack.config.vendor.js`. If it has a file called `webpack.config.js`, run `webpack` (no args). You might need to install webpack first, by running `npm install -g webpack`. * If the sample/template you're trying to run has a file called `webpack.config.vendor.js` at its root, run `webpack --config webpack.config.vendor.js`. It it has a file called `webpack.config.js`, run `webpack` (no args). You might need to install webpack first, by running `npm install -g webpack`.
* Launch it (`dotnet run`) * Launch it (`dotnet run`)
If you're planning to submit a pull request, and if it's more than a trivial fix (for example, for a typo), it's usually a good idea first to file an issue describing what you're proposing to do and how it will work. Then you can find out if it's likely that such a pull request will be accepted, and how it fits into wider ongoing plans. If you're planning to submit a pull request, and if it's more than a trivial fix (for example, for a typo), it's usually a good idea first to file an issue describing what you're proposing to do and how it will work. Then you can find out if it's likely that such a pull request will be accepted, and how it fits into wider ongoing plans.

View File

@@ -3,11 +3,11 @@ init:
install: install:
- ps: Install-Product node 6.9.2 x64 - ps: Install-Product node 6.9.2 x64
# .NET Core SDK binaries # .NET Core SDK binaries
# Download .NET Core 2.0 Preview 3 SDK and add to PATH # Download .NET Core 2.0 Preview 1 SDK and add to PATH
- ps: $urlCurrent = "https://dotnetcli.azureedge.net/dotnet/Sdk/2.0.0-preview3-006729/dotnet-sdk-2.0.0-preview3-006729-win-x64.zip" - ps: $urlCurrent = "https://download.microsoft.com/download/0/6/5/0656B047-5F2F-4281-A851-F30776F8616D/dotnet-dev-win-x64.2.0.0-preview1-005977.zip"
- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetsdk" - ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetsdk"
- ps: mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null - ps: mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null
- ps: $tempFileCurrent = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) - ps: $tempFileCurrent = [System.IO.Path]::GetTempFileName()
- ps: (New-Object System.Net.WebClient).DownloadFile($urlCurrent, $tempFileCurrent) - ps: (New-Object System.Net.WebClient).DownloadFile($urlCurrent, $tempFileCurrent)
- ps: Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFileCurrent, $env:DOTNET_INSTALL_DIR) - ps: Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory($tempFileCurrent, $env:DOTNET_INSTALL_DIR)
- ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path" - ps: $env:Path = "$env:DOTNET_INSTALL_DIR;$env:Path"

View File

@@ -1,2 +1,2 @@
@ECHO OFF @ECHO OFF
PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE"

223
build.ps1
View File

@@ -1,186 +1,67 @@
#!/usr/bin/env powershell $ErrorActionPreference = "Stop"
#requires -version 4
<# function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries)
.SYNOPSIS
Build this repository
.DESCRIPTION
Downloads korebuild if required. Then builds the repository.
.PARAMETER Path
The folder to build. Defaults to the folder containing this script.
.PARAMETER Channel
The channel of KoreBuild to download. Overrides the value from the config file.
.PARAMETER DotNetHome
The directory where .NET Core tools will be stored.
.PARAMETER ToolsSource
The base url where build tools can be downloaded. Overrides the value from the config file.
.PARAMETER Update
Updates KoreBuild to the latest version even if a lock file is present.
.PARAMETER ConfigFile
The path to the configuration file that stores values. Defaults to version.props.
.PARAMETER MSBuildArgs
Arguments to be passed to MSBuild
.NOTES
This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
in the file are overridden by command line parameters.
.EXAMPLE
Example config file:
```json
{ {
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json", while($true)
"channel": "dev", {
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools" try
} {
``` Invoke-WebRequest $url -OutFile $downloadLocation
#> break
[CmdletBinding(PositionalBinding = $false)] }
param( catch
[string]$Path = $PSScriptRoot, {
[Alias('c')] $exceptionMessage = $_.Exception.Message
[string]$Channel, Write-Host "Failed to download '$url': $exceptionMessage"
[Alias('d')] if ($retries -gt 0) {
[string]$DotNetHome, $retries--
[Alias('s')] Write-Host "Waiting 10 seconds before retrying. Retries left: $retries"
[string]$ToolsSource, Start-Sleep -Seconds 10
[Alias('u')]
[switch]$Update,
[string]$ConfigFile = $null,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$MSBuildArgs
)
Set-StrictMode -Version 2
$ErrorActionPreference = 'Stop'
#
# Functions
#
function Get-KoreBuild {
$lockFile = Join-Path $Path 'korebuild-lock.txt'
if (!(Test-Path $lockFile) -or $Update) {
Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile
}
$version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
if (!$version) {
Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
}
$version = $version.TrimStart('version:').Trim()
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
if (!(Test-Path $korebuildPath)) {
Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
New-Item -ItemType Directory -Path $korebuildPath | Out-Null
$remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile
if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
# Use built-in commands where possible as they are cross-plat compatible
Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
} }
else { else
# Fallback to old approach for old installations of PowerShell {
Add-Type -AssemblyName System.IO.Compression.FileSystem $exception = $_.Exception
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath) throw $exception
} }
} }
catch {
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
throw
}
finally {
Remove-Item $tmpfile -ErrorAction Ignore
}
}
return $korebuildPath
}
function Join-Paths([string]$path, [string[]]$childPaths) {
$childPaths | ForEach-Object { $path = Join-Path $path $_ }
return $path
}
function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
if ($RemotePath -notlike 'http*') {
Copy-Item $RemotePath $LocalPath
return
}
$retries = 10
while ($retries -gt 0) {
$retries -= 1
try {
Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
return
}
catch {
Write-Verbose "Request failed. $retries retries remaining"
}
}
Write-Error "Download failed: '$RemotePath'."
}
#
# Main
#
# Load configuration or set defaults
$Path = Resolve-Path $Path
if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
if (Test-Path $ConfigFile) {
try {
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
if ($config) {
if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
}
} catch {
Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
Write-Warning $Error[0]
} }
} }
if (!$DotNetHome) { cd $PSScriptRoot
$DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} ` $repoFolder = $PSScriptRoot
elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}` $env:REPO_FOLDER = $repoFolder
else { Join-Path $PSScriptRoot '.dotnet'}
$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview2.zip"
if ($env:KOREBUILD_ZIP)
{
$koreBuildZip=$env:KOREBUILD_ZIP
} }
if (!$Channel) { $Channel = 'dev' } $buildFolder = ".build"
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' } $buildFile="$buildFolder\KoreBuild.ps1"
# Execute if (!(Test-Path $buildFolder)) {
Write-Host "Downloading KoreBuild from $koreBuildZip"
$korebuildPath = Get-KoreBuild $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid()
Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1') New-Item -Path "$tempFolder" -Type directory | Out-Null
try { $localZipFile="$tempFolder\korebuild.zip"
Install-Tools $ToolsSource $DotNetHome
Invoke-RepositoryBuild $Path @MSBuildArgs DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6
}
finally { Add-Type -AssemblyName System.IO.Compression.FileSystem
Remove-Module 'KoreBuild' -ErrorAction Ignore [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder)
New-Item -Path "$buildFolder" -Type directory | Out-Null
copy-item "$tempFolder\**\build\*" $buildFolder -Recurse
# Cleanup
if (Test-Path $tempFolder) {
Remove-Item -Recurse -Force $tempFolder
}
} }
&"$buildFile" @args

248
build.sh
View File

@@ -1,220 +1,46 @@
#!/usr/bin/env bash #!/usr/bin/env bash
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $repoFolder
set -euo pipefail koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0-preview2.zip"
if [ ! -z $KOREBUILD_ZIP ]; then
# koreBuildZip=$KOREBUILD_ZIP
# variables
#
RESET="\033[0m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
MAGENTA="\033[0;95m"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet"
config_file="$DIR/korebuild.json"
verbose=false
update=false
repo_path="$DIR"
channel=''
tools_source=''
#
# Functions
#
__usage() {
echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] <MSBUILD_ARG>...]"
echo ""
echo "Arguments:"
echo " <MSBUILD_ARG>... Arguments passed to MSBuild. Variable number of arguments allowed."
echo ""
echo "Options:"
echo " --verbose Show verbose output."
echo " -c|--channel <CHANNEL> The channel of KoreBuild to download. Overrides the value from the config file.."
echo " --config-file <FILE> The path to the configuration file that stores values. Defaults to korebuild.json."
echo " -d|--dotnet-home <DIR> The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
echo " --path <PATH> The directory to build. Defaults to the directory containing the script."
echo " -s|--tools-source <URL> The base url where build tools can be downloaded. Overrides the value from the config file."
echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
echo ""
echo "Description:"
echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
if [[ "${1:-}" != '--no-exit' ]]; then
exit 2
fi
}
get_korebuild() {
local version
local lock_file="$repo_path/korebuild-lock.txt"
if [ ! -f "$lock_file" ] || [ "$update" = true ]; then
__get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file"
fi
version="$(grep 'version:*' -m 1 "$lock_file")"
if [[ "$version" == '' ]]; then
__error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
return 1
fi
version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
{
if [ ! -d "$korebuild_path" ]; then
mkdir -p "$korebuild_path"
local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
tmpfile="$(mktemp)"
echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
if __get_remote_file "$remote_path" "$tmpfile"; then
unzip -q -d "$korebuild_path" "$tmpfile"
fi
rm "$tmpfile" || true
fi
source "$korebuild_path/KoreBuild.sh"
} || {
if [ -d "$korebuild_path" ]; then
echo "Cleaning up after failed installation"
rm -rf "$korebuild_path" || true
fi
return 1
}
}
__error() {
echo -e "${RED}error: $*${RESET}" 1>&2
}
__warn() {
echo -e "${YELLOW}warning: $*${RESET}"
}
__machine_has() {
hash "$1" > /dev/null 2>&1
return $?
}
__get_remote_file() {
local remote_path=$1
local local_path=$2
if [[ "$remote_path" != 'http'* ]]; then
cp "$remote_path" "$local_path"
return 0
fi
local failed=false
if __machine_has wget; then
wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true
else
failed=true
fi
if [ "$failed" = true ] && __machine_has curl; then
failed=false
curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true
fi
if [ "$failed" = true ]; then
__error "Download failed: $remote_path" 1>&2
return 1
fi
}
#
# main
#
while [[ $# -gt 0 ]]; do
case $1 in
-\?|-h|--help)
__usage --no-exit
exit 0
;;
-c|--channel|-Channel)
shift
channel="${1:-}"
[ -z "$channel" ] && __usage
;;
--config-file|-ConfigFile)
shift
config_file="${1:-}"
[ -z "$config_file" ] && __usage
if [ ! -f "$config_file" ]; then
__error "Invalid value for --config-file. $config_file does not exist."
exit 1
fi
;;
-d|--dotnet-home|-DotNetHome)
shift
DOTNET_HOME="${1:-}"
[ -z "$DOTNET_HOME" ] && __usage
;;
--path|-Path)
shift
repo_path="${1:-}"
[ -z "$repo_path" ] && __usage
;;
-s|--tools-source|-ToolsSource)
shift
tools_source="${1:-}"
[ -z "$tools_source" ] && __usage
;;
-u|--update|-Update)
update=true
;;
--verbose|-Verbose)
verbose=true
;;
--)
shift
break
;;
*)
break
;;
esac
shift
done
if ! __machine_has unzip; then
__error 'Missing required command: unzip'
exit 1
fi fi
if ! __machine_has curl && ! __machine_has wget; then buildFolder=".build"
__error 'Missing required command. Either wget or curl is required.' buildFile="$buildFolder/KoreBuild.sh"
exit 1
fi
[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json" if test ! -d $buildFolder; then
if [ -f "$config_file" ]; then echo "Downloading KoreBuild from $koreBuildZip"
if __machine_has jq ; then
if jq '.' "$config_file" >/dev/null ; then tempFolder="/tmp/KoreBuild-$(uuidgen)"
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")" mkdir $tempFolder
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else localZipFile="$tempFolder/korebuild.zip"
__warn "$config_file is invalid JSON. Its settings will be ignored."
retries=6
until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null)
do
echo "Failed to download '$koreBuildZip'"
if [ "$retries" -le 0 ]; then
exit 1
fi fi
elif __machine_has python ; then retries=$((retries - 1))
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then echo "Waiting 10 seconds before retrying. Retries left: $retries"
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")" sleep 10s
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")" done
else
__warn "$config_file is invalid JSON. Its settings will be ignored." unzip -q -d $tempFolder $localZipFile
fi
else mkdir $buildFolder
__warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.' cp -r $tempFolder/**/build/** $buildFolder
chmod +x $buildFile
# Cleanup
if test -d $tempFolder; then
rm -rf $tempFolder
fi fi
[ ! -z "${config_channel:-}" ] && channel="$config_channel"
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
fi fi
[ -z "$channel" ] && channel='dev' $buildFile -r $repoFolder "$@"
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild
install_tools "$tools_source" "$DOTNET_HOME"
invoke_repository_build "$repo_path" "$@"

View File

@@ -1,4 +1,6 @@
<Project> <Project>
<Import Project="dependencies.props" />
<Import Project="..\version.props" />
<PropertyGroup> <PropertyGroup>
<Product>Microsoft ASP.NET Core</Product> <Product>Microsoft ASP.NET Core</Product>
@@ -7,11 +9,15 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Key.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign> <PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <VersionSuffix Condition="'$(VersionSuffix)'!='' AND '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkPackageVersion)" PrivateAssets="All" /> <PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkVersion)" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'">
<PackageReference Include="NETStandard.Library" Version="$(BundledNETStandardPackageVersion)" />
<PackageReference Include="NETStandard.Library.NETFramework" Version="$(NETStandardLibraryNETFrameworkVersion)" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,23 +1,12 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<InternalAspNetCoreSdkPackageVersion>2.0.2-rc1-15526</InternalAspNetCoreSdkPackageVersion> <AspNetCoreVersion>2.0.0-preview2-*</AspNetCoreVersion>
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreDiagnosticsPackageVersion> <AutoMapperVersion>5.0.2</AutoMapperVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreHostingAbstractionsPackageVersion> <InternalAspNetCoreSdkVersion>2.1.0-*</InternalAspNetCoreSdkVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreHostingPackageVersion> <JsonNetVersion>10.0.1</JsonNetVersion>
<MicrosoftAspNetCoreMvcPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcPackageVersion> <NETStandardImplicitPackageVersion>$(BundledNETStandardPackageVersion)</NETStandardImplicitPackageVersion>
<MicrosoftAspNetCoreMvcTagHelpersPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcTagHelpersPackageVersion> <NETStandardLibraryNETFrameworkVersion>2.0.0-*</NETStandardLibraryNETFrameworkVersion>
<MicrosoftAspNetCoreMvcViewFeaturesPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcViewFeaturesPackageVersion> <RuntimeFrameworkVersion Condition="'$(TargetFramework)'=='netcoreapp2.0'">2.0.0-*</RuntimeFrameworkVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreServerIISIntegrationPackageVersion> <ThreadingDataflowVersion>4.7.0</ThreadingDataflowVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreStaticFilesPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.0.0</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.0.0</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.0.0</MicrosoftExtensionsLoggingDebugPackageVersion>
<NewtonsoftJsonRuntimePackageVersion>10.0.1</NewtonsoftJsonRuntimePackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.5</MicrosoftNETCoreApp20PackageVersion>
<NETStandardLibrary20PackageVersion>2.0.1</NETStandardLibrary20PackageVersion>
<SystemThreadingTasksDataflowPackageVersion>4.8.0</SystemThreadingTasksDataflowPackageVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
</Project> </Project>

View File

@@ -1,17 +0,0 @@
<Project>
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
<PropertyGroup>
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
$(RestoreSources);
https://dotnet.myget.org/F/aspnet-2-0-2-october2017-patch/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-master/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
$(RestoreSources);
https://api.nuget.org/v3/index.json;
</RestoreSources>
</PropertyGroup>
</Project>

View File

@@ -1,2 +0,0 @@
version:2.0.5-rtm-10016
commithash:02bda79ac9c564229da734a836f258d6c1321eb7

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.0/tools/korebuild.schema.json",
"channel": "release/2.0"
}

View File

@@ -14,7 +14,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,7 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.NodeServices; using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.SpaServices.Prerendering;
namespace NodeServicesExamples.Controllers namespace NodeServicesExamples.Controllers
{ {
@@ -35,20 +34,6 @@ namespace NodeServicesExamples.Controllers
return View(); return View();
} }
public async Task<IActionResult> Prerendering([FromServices] ISpaPrerenderer prerenderer)
{
var result = await prerenderer.RenderToString("./Node/prerenderPage");
if (!string.IsNullOrEmpty(result.RedirectUrl))
{
return Redirect(result.RedirectUrl);
}
ViewData["PrerenderedHtml"] = result.Html;
ViewData["PrerenderedGlobals"] = result.CreateGlobalsAssignmentScript();
return View();
}
public IActionResult Error() public IActionResult Error()
{ {
return View("~/Views/Shared/Error.cshtml"); return View("~/Views/Shared/Error.cshtml");

View File

@@ -1,14 +0,0 @@
var createServerRenderer = require('aspnet-prerendering').createServerRenderer;
module.exports = createServerRenderer(function(params) {
return new Promise(function (resolve, reject) {
var message = 'The HTML was returned by the prerendering boot function. '
+ 'The boot function received the following params:'
+ '<pre>' + JSON.stringify(params, null, 4) + '</pre>';
resolve({
html: '<h3>Hello, world!</h3>' + message,
globals: { sampleData: { nodeVersion: process.version } }
});
});
});

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\common.props" /> <Import Project="..\..\..\build\common.props" />
@@ -9,17 +9,17 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.SpaServices\Microsoft.AspNetCore.SpaServices.csproj" /> <ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish"> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">

View File

@@ -17,7 +17,6 @@ namespace NodeServicesExamples
// Enable Node Services // Enable Node Services
services.AddNodeServices(); services.AddNodeServices();
services.AddSpaPrerenderer();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@@ -9,5 +9,4 @@
<ul> <ul>
<li><a asp-action="ES2015Transpilation">ES2015 transpilation</a></li> <li><a asp-action="ES2015Transpilation">ES2015 transpilation</a></li>
<li><a asp-action="Chart">Server-side chart rendering</a></li> <li><a asp-action="Chart">Server-side chart rendering</a></li>
<li><a asp-action="Prerendering">Server-side SPA prerendering</a></li>
</ul> </ul>

View File

@@ -1,21 +0,0 @@
<h1>Server-side prerendering</h1>
<p>
This sample demonstrates how you can invoke a JavaScript module that contains
prerendering logic for a Single-Page Application framework.
</p>
</p>
Your prerendering boot function will receive parameters that describe the page
being rendered and any data supplied by the .NET code. The return value should be
a promise that resolves with data to be injected into the page, such as the
rendered HTML and any global data that should be made available to client-side code.
</p>
@Html.Raw(ViewData["PrerenderedHtml"])
<script>@Html.Raw(ViewData["PrerenderedGlobals"])</script>
<script>
// Demonstrates how client-side code can receive data from the prerendering process
console.log('Received Node version from prerendering logic: ' + sampleData.nodeVersion);
</script>

View File

@@ -2,7 +2,6 @@
"name": "nodeservicesexamples", "name": "nodeservicesexamples",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"aspnet-prerendering": "^2.0.6",
"babel-core": "^6.7.4", "babel-core": "^6.7.4",
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.6.0",
"node-chartist": "^1.0.2" "node-chartist": "^1.0.2"

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\common.props" /> <Import Project="..\..\..\build\common.props" />
@@ -13,13 +13,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish"> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">

View File

@@ -10,13 +10,12 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="node_modules\**\*" />
<EmbeddedResource Include="Content\**\*" /> <EmbeddedResource Include="Content\**\*" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" /> <ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(SystemThreadingTasksDataflowPackageVersion)" /> <PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(ThreadingDataflowVersion)" />
</ItemGroup> </ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' "> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -55,11 +55,10 @@
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive, // 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. // but simplifies things for the consumer of this module.
__webpack_require__(2); __webpack_require__(2);
__webpack_require__(4); var http = __webpack_require__(3);
var http = __webpack_require__(5); var path = __webpack_require__(4);
var path = __webpack_require__(3); var ArgsUtil_1 = __webpack_require__(5);
var ArgsUtil_1 = __webpack_require__(6); var ExitWhenParentExits_1 = __webpack_require__(6);
var ExitWhenParentExits_1 = __webpack_require__(7);
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct // Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
// reference to Node's runtime 'require' function. // reference to Node's runtime 'require' function.
var dynamicRequire = eval('require'); var dynamicRequire = eval('require');
@@ -134,73 +133,12 @@
} }
function respondWithError(res, errorValue) { function respondWithError(res, errorValue) {
res.statusCode = 500; res.statusCode = 500;
res.end(JSON.stringify({ res.end(errorValue.stack || errorValue.toString());
errorMessage: errorValue.message || errorValue,
errorDetails: errorValue.stack || null
}));
} }
/***/ }, /***/ },
/* 2 */ /* 2 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
var path = __webpack_require__(3);
var startsWith = function (str, prefix) { return str.substring(0, prefix.length) === prefix; };
var appRootDir = process.cwd();
function patchedLStat(pathToStatLong, fsReqWrap) {
try {
// If the lstat completes without errors, we don't modify its behavior at all
return origLStat.apply(this, arguments);
}
catch (ex) {
var shouldOverrideError = startsWith(ex.message, 'EPERM') // It's a permissions error
&& typeof appRootDirLong === 'string'
&& startsWith(appRootDirLong, pathToStatLong) // ... for an ancestor directory
&& ex.stack.indexOf('Object.realpathSync ') >= 0; // ... during symlink resolution
if (shouldOverrideError) {
// Fake the result to give the same result as an 'lstat' on the app root dir.
// This stops Node failing to load modules just because it doesn't know whether
// ancestor directories are symlinks or not. If there's a genuine file
// permissions issue, it will still surface later when Node actually
// tries to read the file.
return origLStat.call(this, appRootDir, fsReqWrap);
}
else {
// In any other case, preserve the original error
throw ex;
}
}
}
;
// It's only necessary to apply this workaround on Windows
var appRootDirLong = null;
var origLStat = null;
if (/^win/.test(process.platform)) {
try {
// Get the app's root dir in Node's internal "long" format (e.g., \\?\C:\dir\subdir)
appRootDirLong = path._makeLong(appRootDir);
// Actually apply the patch, being as defensive as possible
var bindingFs = process.binding('fs');
origLStat = bindingFs.lstat;
if (typeof origLStat === 'function') {
bindingFs.lstat = patchedLStat;
}
}
catch (ex) {
}
}
/***/ },
/* 3 */
/***/ function(module, exports) {
module.exports = require("path");
/***/ },
/* 4 */
/***/ function(module, exports) { /***/ function(module, exports) {
// When Node writes to stdout/strerr, we capture that and convert the lines into calls on the // When Node writes to stdout/strerr, we capture that and convert the lines into calls on the
@@ -241,13 +179,19 @@
/***/ }, /***/ },
/* 5 */ /* 3 */
/***/ function(module, exports) { /***/ function(module, exports) {
module.exports = require("http"); module.exports = require("http");
/***/ }, /***/ },
/* 6 */ /* 4 */
/***/ function(module, exports) {
module.exports = require("path");
/***/ },
/* 5 */
/***/ function(module, exports) { /***/ function(module, exports) {
"use strict"; "use strict";
@@ -273,7 +217,7 @@
/***/ }, /***/ },
/* 7 */ /* 6 */
/***/ function(module, exports) { /***/ function(module, exports) {
/* /*

View File

@@ -67,10 +67,8 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
// Unfortunately there's no true way to cancel ReadAsStringAsync calls, hence AbandonIfCancelled // Unfortunately there's no true way to cancel ReadAsStringAsync calls, hence AbandonIfCancelled
var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken); var responseErrorString = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);
var responseError = JsonConvert.DeserializeObject<RpcJsonResponse>(responseJson, jsonSerializerSettings); throw new Exception("Call to Node module failed with error: " + responseErrorString);
throw new NodeInvocationException(responseError.ErrorMessage, responseError.ErrorDetails);
} }
var responseContentType = response.Content.Headers.ContentType; var responseContentType = response.Content.Headers.ContentType;
@@ -138,13 +136,5 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
_disposed = true; _disposed = true;
} }
} }
#pragma warning disable 649 // These properties are populated via JSON deserialization
private class RpcJsonResponse
{
public string ErrorMessage { get; set; }
public string ErrorDetails { get; set; }
}
#pragma warning restore 649
} }
} }

View File

@@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
// Make sure the Node process is finished // Make sure the Node process is finished
// TODO: Is there a more graceful way to end it? Or does this still let it perform any cleanup? // TODO: Is there a more graceful way to end it? Or does this still let it perform any cleanup?
if (_nodeProcess != null && !_nodeProcess.HasExited) if (!_nodeProcess.HasExited)
{ {
_nodeProcess.Kill(); _nodeProcess.Kill();
} }

View File

@@ -11,14 +11,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="node_modules\**\*" />
<EmbeddedResource Include="Content\**\*" /> <EmbeddedResource Include="Content\**\*" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonRuntimePackageVersion)" /> <PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
</ItemGroup> </ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' "> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -1,6 +1,5 @@
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive, // 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. // but simplifies things for the consumer of this module.
import './Util/PatchModuleResolutionLStat';
import './Util/OverrideStdOutputs'; import './Util/OverrideStdOutputs';
import * as http from 'http'; import * as http from 'http';
import * as path from 'path'; import * as path from 'path';
@@ -87,8 +86,5 @@ function readRequestBodyAsJson(request, callback) {
function respondWithError(res: http.ServerResponse, errorValue: any) { function respondWithError(res: http.ServerResponse, errorValue: any) {
res.statusCode = 500; res.statusCode = 500;
res.end(JSON.stringify({ res.end(errorValue.stack || errorValue.toString());
errorMessage: errorValue.message || errorValue,
errorDetails: errorValue.stack || null
}));
} }

View File

@@ -1,48 +0,0 @@
import * as path from 'path';
const startsWith = (str: string, prefix: string) => str.substring(0, prefix.length) === prefix;
const appRootDir = process.cwd();
function patchedLStat(pathToStatLong: string, fsReqWrap?: any) {
try {
// If the lstat completes without errors, we don't modify its behavior at all
return origLStat.apply(this, arguments);
} catch(ex) {
const shouldOverrideError =
startsWith(ex.message, 'EPERM') // It's a permissions error
&& typeof appRootDirLong === 'string'
&& startsWith(appRootDirLong, pathToStatLong) // ... for an ancestor directory
&& ex.stack.indexOf('Object.realpathSync ') >= 0; // ... during symlink resolution
if (shouldOverrideError) {
// Fake the result to give the same result as an 'lstat' on the app root dir.
// This stops Node failing to load modules just because it doesn't know whether
// ancestor directories are symlinks or not. If there's a genuine file
// permissions issue, it will still surface later when Node actually
// tries to read the file.
return origLStat.call(this, appRootDir, fsReqWrap);
} else {
// In any other case, preserve the original error
throw ex;
}
}
};
// It's only necessary to apply this workaround on Windows
let appRootDirLong: string = null;
let origLStat: Function = null;
if (/^win/.test(process.platform)) {
try {
// Get the app's root dir in Node's internal "long" format (e.g., \\?\C:\dir\subdir)
appRootDirLong = (path as any)._makeLong(appRootDir);
// Actually apply the patch, being as defensive as possible
const bindingFs = (process as any).binding('fs');
origLStat = bindingFs.lstat;
if (typeof origLStat === 'function') {
bindingFs.lstat = patchedLStat;
}
} catch(ex) {
// If some future version of Node throws (e.g., to prevent use of process.binding()),
// don't apply the patch, but still let the application run.
}
}

View File

@@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.NodeServices
/// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param> /// <param name="applicationStoppingToken">A token that indicates when the host application is stopping.</param>
public StringAsTempFile(string content, CancellationToken applicationStoppingToken) public StringAsTempFile(string content, CancellationToken applicationStoppingToken)
{ {
FileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); FileName = Path.GetTempFileName();
File.WriteAllText(FileName, content); File.WriteAllText(FileName, content);
// Because .NET finalizers don't reliably run when the process is terminating, also // Because .NET finalizers don't reliably run when the process is terminating, also

View File

@@ -11,11 +11,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="node_modules\**\*" />
<EmbeddedResource Include="Content\**\*" /> <EmbeddedResource Include="Content\**\*" />
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" /> <ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(MicrosoftAspNetCoreMvcTagHelpersPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="$(MicrosoftAspNetCoreMvcViewFeaturesPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="$(AspNetCoreVersion)" />
</ItemGroup> </ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' "> <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -1,49 +0,0 @@
using System.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.NodeServices;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SpaServices.Prerendering
{
/// <summary>
/// Default implementation of a DI service that provides convenient access to
/// server-side prerendering APIs. This is an alternative to prerendering via
/// the asp-prerender-module tag helper.
/// </summary>
internal class DefaultSpaPrerenderer : ISpaPrerenderer
{
private readonly string _applicationBasePath;
private readonly CancellationToken _applicationStoppingToken;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly INodeServices _nodeServices;
public DefaultSpaPrerenderer(
INodeServices nodeServices,
IApplicationLifetime applicationLifetime,
IHostingEnvironment hostingEnvironment,
IHttpContextAccessor httpContextAccessor)
{
_applicationBasePath = hostingEnvironment.ContentRootPath;
_applicationStoppingToken = applicationLifetime.ApplicationStopping;
_httpContextAccessor = httpContextAccessor;
_nodeServices = nodeServices;
}
public Task<RenderToStringResult> RenderToString(
string moduleName,
string exportName = null,
object customDataParameter = null,
int timeoutMilliseconds = default(int))
{
return Prerenderer.RenderToString(
_applicationBasePath,
_nodeServices,
_applicationStoppingToken,
new JavaScriptModuleExport(moduleName) { ExportName = exportName },
_httpContextAccessor.HttpContext,
customDataParameter,
timeoutMilliseconds);
}
}
}

View File

@@ -1,28 +0,0 @@
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SpaServices.Prerendering
{
/// <summary>
/// Represents a service that can perform server-side prerendering for
/// JavaScript-based Single Page Applications. This is an alternative
/// to using the 'asp-prerender-module' tag helper.
/// </summary>
public interface ISpaPrerenderer
{
/// <summary>
/// Invokes JavaScript code to perform server-side prerendering for a
/// Single-Page Application. This is an alternative to using the
/// 'asp-prerender-module' tag helper.
/// </summary>
/// <param name="moduleName">The JavaScript module that exports a prerendering function.</param>
/// <param name="exportName">The name of the export from the JavaScript module, if it is not the default export.</param>
/// <param name="customDataParameter">An optional JSON-serializable object to pass to the JavaScript prerendering function.</param>
/// <param name="timeoutMilliseconds">If specified, the prerendering task will time out after this duration if not already completed.</param>
/// <returns></returns>
Task<RenderToStringResult> RenderToString(
string moduleName,
string exportName = null,
object customDataParameter = null,
int timeoutMilliseconds = default(int));
}
}

View File

@@ -1,11 +1,14 @@
using System; using System;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.NodeServices; using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.SpaServices.Prerendering namespace Microsoft.AspNetCore.SpaServices.Prerendering
{ {
@@ -87,6 +90,19 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
/// <returns>A <see cref="Task"/> representing the operation.</returns> /// <returns>A <see cref="Task"/> representing the operation.</returns>
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{ {
// We want to pass the original, unencoded incoming URL data through to Node, so that
// server-side code has the same view of the URL as client-side code (on the client,
// location.pathname returns an unencoded string).
// The following logic handles special characters in URL paths in the same way that
// Node and client-side JS does. For example, the path "/a=b%20c" gets passed through
// unchanged (whereas other .NET APIs do change it - Path.Value will return it as
// "/a=b c" and Path.ToString() will return it as "/a%3db%20c")
var requestFeature = ViewContext.HttpContext.Features.Get<IHttpRequestFeature>();
var unencodedPathAndQuery = requestFeature.RawTarget;
var request = ViewContext.HttpContext.Request;
var unencodedAbsoluteUrl = $"{request.Scheme}://{request.Host}{unencodedPathAndQuery}";
var result = await Prerenderer.RenderToString( var result = await Prerenderer.RenderToString(
_applicationBasePath, _applicationBasePath,
_nodeServices, _nodeServices,
@@ -95,9 +111,11 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
{ {
ExportName = ExportName ExportName = ExportName
}, },
ViewContext.HttpContext, unencodedAbsoluteUrl,
unencodedPathAndQuery,
CustomDataParameter, CustomDataParameter,
TimeoutMillisecondsParameter); TimeoutMillisecondsParameter,
request.PathBase.ToString());
if (!string.IsNullOrEmpty(result.RedirectUrl)) if (!string.IsNullOrEmpty(result.RedirectUrl))
{ {
@@ -116,10 +134,19 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
// Also attach any specified globals to the 'window' object. This is useful for transferring // Also attach any specified globals to the 'window' object. This is useful for transferring
// general state between server and client. // general state between server and client.
var globalsScript = result.CreateGlobalsAssignmentScript(); if (result.Globals != null)
if (!string.IsNullOrEmpty(globalsScript))
{ {
output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>"); var stringBuilder = new StringBuilder();
foreach (var property in result.Globals.Properties())
{
stringBuilder.AppendFormat("window.{0} = {1};",
property.Name,
property.Value.ToString(Formatting.None));
}
if (stringBuilder.Length > 0)
{
output.PostElement.SetHtmlContent($"<script>{stringBuilder}</script>");
}
} }
} }
} }

View File

@@ -2,8 +2,6 @@ using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.NodeServices; using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.SpaServices.Prerendering namespace Microsoft.AspNetCore.SpaServices.Prerendering
{ {
@@ -16,40 +14,6 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
private static StringAsTempFile NodeScript; private static StringAsTempFile NodeScript;
internal static Task<RenderToStringResult> RenderToString(
string applicationBasePath,
INodeServices nodeServices,
CancellationToken applicationStoppingToken,
JavaScriptModuleExport bootModule,
HttpContext httpContext,
object customDataParameter,
int timeoutMilliseconds)
{
// We want to pass the original, unencoded incoming URL data through to Node, so that
// server-side code has the same view of the URL as client-side code (on the client,
// location.pathname returns an unencoded string).
// The following logic handles special characters in URL paths in the same way that
// Node and client-side JS does. For example, the path "/a=b%20c" gets passed through
// unchanged (whereas other .NET APIs do change it - Path.Value will return it as
// "/a=b c" and Path.ToString() will return it as "/a%3db%20c")
var requestFeature = httpContext.Features.Get<IHttpRequestFeature>();
var unencodedPathAndQuery = requestFeature.RawTarget;
var request = httpContext.Request;
var unencodedAbsoluteUrl = $"{request.Scheme}://{request.Host}{unencodedPathAndQuery}";
return RenderToString(
applicationBasePath,
nodeServices,
applicationStoppingToken,
bootModule,
unencodedAbsoluteUrl,
unencodedPathAndQuery,
customDataParameter,
timeoutMilliseconds,
request.PathBase.ToString());
}
/// <summary> /// <summary>
/// Performs server-side prerendering by invoking code in Node.js. /// Performs server-side prerendering by invoking code in Node.js.
/// </summary> /// </summary>

View File

@@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.NodeServices;
using Microsoft.AspNetCore.SpaServices.Prerendering;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for setting up prerendering features in an <see cref="IServiceCollection" />.
/// </summary>
public static class PrerenderingServiceCollectionExtensions
{
/// <summary>
/// Configures the dependency injection system to supply an implementation
/// of <see cref="ISpaPrerenderer"/>.
/// </summary>
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
public static void AddSpaPrerenderer(this IServiceCollection serviceCollection)
{
serviceCollection.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
serviceCollection.AddSingleton<ISpaPrerenderer, DefaultSpaPrerenderer>();
}
}
}

View File

@@ -1,6 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Text;
namespace Microsoft.AspNetCore.SpaServices.Prerendering namespace Microsoft.AspNetCore.SpaServices.Prerendering
{ {
@@ -32,29 +30,5 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
/// If set, specifies the HTTP status code that should be sent back with the server response. /// If set, specifies the HTTP status code that should be sent back with the server response.
/// </summary> /// </summary>
public int? StatusCode { get; set; } public int? StatusCode { get; set; }
/// <summary>
/// Constructs a block of JavaScript code that assigns data from the
/// <see cref="Globals"/> property to the global namespace.
/// </summary>
/// <returns>A block of JavaScript code.</returns>
public string CreateGlobalsAssignmentScript()
{
if (Globals == null)
{
return string.Empty;
}
var stringBuilder = new StringBuilder();
foreach (var property in Globals.Properties())
{
stringBuilder.AppendFormat("window.{0} = {1};",
property.Name,
property.Value.ToString(Formatting.None));
}
return stringBuilder.ToString();
}
} }
} }

View File

@@ -20,7 +20,7 @@ Behind the scenes, it uses the [`Microsoft.AspNetCore.NodeServices`](https://git
### Installation into existing projects ### Installation into existing projects
* Install the `Microsoft.AspNetCore.SpaServices` NuGet package * Add `Microsoft.AspNetCore.SpaServices` to the dependencies list in your `project.json` file
* Run `dotnet restore` (or if you use Visual Studio, just wait a moment - it will restore dependencies automatically) * Run `dotnet restore` (or if you use Visual Studio, just wait a moment - it will restore dependencies automatically)
* Install supporting NPM packages for the features you'll be using: * Install supporting NPM packages for the features you'll be using:
* For **server-side prerendering**, install `aspnet-prerendering` * For **server-side prerendering**, install `aspnet-prerendering`

View File

@@ -28,11 +28,6 @@ namespace Microsoft.AspNetCore.SpaServices.Webpack
string pathPrefix, string pathPrefix,
ConditionalProxyMiddlewareOptions options) ConditionalProxyMiddlewareOptions options)
{ {
if (!pathPrefix.StartsWith("/"))
{
pathPrefix = "/" + pathPrefix;
}
_next = next; _next = next;
_pathPrefix = pathPrefix; _pathPrefix = pathPrefix;
_options = options; _options = options;
@@ -70,7 +65,7 @@ namespace Microsoft.AspNetCore.SpaServices.Webpack
requestMessage.Headers.Host = _options.Host + ":" + _options.Port; requestMessage.Headers.Host = _options.Host + ":" + _options.Port;
var uriString = var uriString =
$"{_options.Scheme}://{_options.Host}:{_options.Port}{context.Request.Path}{context.Request.QueryString}"; $"{_options.Scheme}://{_options.Host}:{_options.Port}{context.Request.PathBase}{context.Request.Path}{context.Request.QueryString}";
requestMessage.RequestUri = new Uri(uriString); requestMessage.RequestUri = new Uri(uriString);
requestMessage.Method = new HttpMethod(context.Request.Method); requestMessage.Method = new HttpMethod(context.Request.Method);

View File

@@ -101,9 +101,9 @@ namespace Microsoft.AspNetCore.Builder
// plus /__webpack_hmr is proxied with infinite timeout, because it's an EventSource (long-lived request). // plus /__webpack_hmr is proxied with infinite timeout, because it's an EventSource (long-lived request).
foreach (var publicPath in devServerInfo.PublicPaths) foreach (var publicPath in devServerInfo.PublicPaths)
{ {
appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath + hmrEndpoint, devServerInfo.Port, Timeout.InfiniteTimeSpan);
appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath, devServerInfo.Port, TimeSpan.FromSeconds(100)); 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) private static void UseProxyToLocalWebpackDevMiddleware(this IApplicationBuilder appBuilder, string publicPath, int proxyToPort, TimeSpan requestTimeout)

View File

@@ -1,6 +1,6 @@
{ {
"name": "aspnet-prerendering", "name": "aspnet-prerendering",
"version": "2.0.6", "version": "2.0.5",
"description": "Helpers for server-side rendering of JavaScript applications in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.", "description": "Helpers for server-side rendering of JavaScript applications in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -1,8 +1,8 @@
/// <reference path="./PrerenderingInterfaces.d.ts" />
import * as url from 'url'; import * as url from 'url';
import * as path from 'path'; import * as path from 'path';
import * as domain from 'domain'; import * as domain from 'domain';
import { run as domainTaskRun, baseUrl as domainTaskBaseUrl } from 'domain-task/main'; import { run as domainTaskRun, baseUrl as domainTaskBaseUrl } from 'domain-task/main';
import { BootFunc, BootFuncParams, BootModuleInfo, RenderToStringCallback, RenderToStringFunc } from './PrerenderingInterfaces';
const defaultTimeoutMilliseconds = 30 * 1000; const defaultTimeoutMilliseconds = 30 * 1000;

View File

@@ -1,28 +1,26 @@
export interface RenderToStringFunc { interface RenderToStringFunc {
(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number, requestPathBase: string): void; (callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number, requestPathBase: string): void;
} }
export interface RenderToStringCallback { interface RenderToStringCallback {
(error: any, result?: RenderResult): void; (error: any, result?: RenderToStringResult): void;
} }
export interface RenderToStringResult { interface RenderToStringResult {
html: string; html: string;
statusCode?: number; statusCode?: number;
globals?: { [key: string]: any }; globals?: { [key: string]: any };
} }
export interface RedirectResult { interface RedirectResult {
redirectUrl: string; redirectUrl: string;
} }
export type RenderResult = RenderToStringResult | RedirectResult; interface BootFunc {
(params: BootFuncParams): Promise<RenderToStringResult>;
export interface BootFunc {
(params: BootFuncParams): Promise<RenderResult>;
} }
export interface BootFuncParams { interface BootFuncParams {
location: any; // e.g., Location object containing information '/some/path' location: any; // e.g., Location object containing information '/some/path'
origin: string; // e.g., 'https://example.com:1234' origin: string; // e.g., 'https://example.com:1234'
url: string; // e.g., '/some/path' url: string; // e.g., '/some/path'
@@ -32,7 +30,7 @@ export interface BootFuncParams {
data: any; // any custom object passed through from .NET data: any; // any custom object passed through from .NET
} }
export interface BootModuleInfo { interface BootModuleInfo {
moduleName: string; moduleName: string;
exportName?: string; exportName?: string;
webpackConfig?: string; webpackConfig?: string;

View File

@@ -1,2 +1,5 @@
/// <reference path="./PrerenderingInterfaces.d.ts" />
export * from './Prerendering'; export * from './Prerendering';
export * from './PrerenderingInterfaces';
export type RenderResult = RenderToStringResult | RedirectResult;

View File

@@ -1,6 +1,6 @@
{ {
"name": "aspnet-webpack-react", "name": "aspnet-webpack-react",
"version": "3.0.0-beta.1", "version": "2.0.0",
"description": "Helpers for using Webpack with React in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.", "description": "Helpers for using Webpack with React in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "domain-task", "name": "domain-task",
"version": "3.0.3", "version": "3.0.0",
"description": "Tracks outstanding operations for a logical thread of execution", "description": "Tracks outstanding operations for a logical thread of execution",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -18,7 +18,6 @@
}, },
"dependencies": { "dependencies": {
"domain-context": "^0.5.1", "domain-context": "^0.5.1",
"is-absolute-url": "^2.1.0",
"isomorphic-fetch": "^2.2.1" "isomorphic-fetch": "^2.2.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,17 +1,11 @@
import * as url from 'url'; import * as url from 'url';
import * as domain from 'domain'; import * as domain from 'domain';
import * as domainContext from 'domain-context'; import * as domainContext from 'domain-context';
import * as isAbsoluteUrl from 'is-absolute-url';
import { baseUrl } from './main'; import { baseUrl } from './main';
const isomorphicFetch = require('isomorphic-fetch'); const isomorphicFetch = require('isomorphic-fetch');
const isNode = typeof process === 'object' && process.versions && !!process.versions.node; const isNode = typeof process === 'object' && process.versions && !!process.versions.node;
const nodeHttps = isNode && require('https');
const isHttpsRegex = /^https\:/;
function issueRequest(baseUrl: string, req: string | Request, init?: RequestInit): Promise<any> { function issueRequest(baseUrl: string, req: string | Request, init?: RequestInit): Promise<any> {
const reqUrl = (req instanceof Request) ? req.url : req;
const isRelativeUrl = reqUrl && !isAbsoluteUrl(reqUrl);
// Resolve relative URLs // Resolve relative URLs
if (baseUrl) { if (baseUrl) {
if (req instanceof Request) { if (req instanceof Request) {
@@ -31,45 +25,9 @@ function issueRequest(baseUrl: string, req: string | Request, init?: RequestInit
`); `);
} }
init = applyHttpsAgentPolicy(init, isRelativeUrl, baseUrl);
return isomorphicFetch(req, init); return isomorphicFetch(req, init);
} }
function applyHttpsAgentPolicy(init: RequestInit, isRelativeUrl: boolean, baseUrl: string): RequestInit {
// HTTPS is awkward in Node because it uses a built-in list of CAs, rather than recognizing
// the OS's system-level CA list. There are dozens of issues filed against Node about this,
// but still (as of v8.0.0) no resolution besides manually duplicating your CA config.
//
// The biggest problem for typical isomorphic-SPA development this causes is that if you're
// using a self-signed localhost cert in development, Node won't be able to make API calls
// to it (e.g., https://github.com/aspnet/JavaScriptServices/issues/1089). Developers could
// fix this by either manually configuring the cert in Node (which is extremely inconvenient,
// especially if multiple devs on a team have different self-signed localhost certs), or by
// disabling cert verification on their API requests.
//
// Fortunately, 'domain-task/fetch' knows when you're making a relative-URL request to your
// own web server (as opposed to an arbitrary request to anywhere else). In this specific case,
// there's no real point in cert verification, since the request never even leaves the machine
// so a MitM attack isn't meaningful. So by default, when your code is running in Node and
// is making a relative-URL request, *and* if you haven't explicitly configured any option
// for 'agent' (which would let you set up other HTTPS-handling policies), then we automatically
// disable cert verification for that request.
if (isNode && isRelativeUrl) {
const isHttps = baseUrl && isHttpsRegex.test(baseUrl);
if (isHttps) {
const hasAgentConfig = init && ('agent' in init);
if (!hasAgentConfig) {
const agentForRequest = new (nodeHttps.Agent)({ rejectUnauthorized: false });
init = init || {};
(init as any).agent = agentForRequest;
}
}
}
return init;
}
export function fetch(url: string | Request, init?: RequestInit): Promise<any> { export function fetch(url: string | Request, init?: RequestInit): Promise<any> {
// As of domain-task 2.0.0, we no longer auto-add the 'fetch' promise to the current domain task list. // As of domain-task 2.0.0, we no longer auto-add the 'fetch' promise to the current domain task list.
// This is because it's misleading to do so, and can result in race-condition bugs, e.g., // This is because it's misleading to do so, and can result in race-condition bugs, e.g.,

View File

@@ -5,21 +5,23 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-rtm-26190" /> <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -10,12 +10,8 @@ import { AppComponent } from './components/app/app.component';
AppModuleShared AppModuleShared
], ],
providers: [ providers: [
{ provide: 'ORIGIN_URL', useFactory: getOriginUrl } { provide: 'ORIGIN_URL', useValue: location.origin }
] ]
}) })
export class AppModule { export class AppModule {
} }
export function getOriginUrl() {
return location.origin;
}

View File

@@ -11,7 +11,7 @@ export class FetchDataComponent {
constructor(http: Http, @Inject('ORIGIN_URL') originUrl: string) { constructor(http: Http, @Inject('ORIGIN_URL') originUrl: string) {
http.get(originUrl + '/api/SampleData/WeatherForecasts').subscribe(result => { http.get(originUrl + '/api/SampleData/WeatherForecasts').subscribe(result => {
this.forecasts = result.json() as WeatherForecast[]; this.forecasts = result.json() as WeatherForecast[];
}, error => console.error(error)); });
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,33 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"scripts": { "scripts": {
"test": "karma start ClientApp/test/karma.conf.js" "test": "karma start ClientApp/test/karma.conf.js"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "4.2.5", "@angular/animations": "4.1.2",
"@angular/common": "4.2.5", "@angular/common": "4.1.2",
"@angular/compiler": "4.2.5", "@angular/compiler": "4.1.2",
"@angular/compiler-cli": "4.2.5", "@angular/core": "4.1.2",
"@angular/core": "4.2.5", "@angular/forms": "4.1.2",
"@angular/forms": "4.2.5", "@angular/http": "4.1.2",
"@angular/http": "4.2.5", "@angular/platform-browser": "4.1.2",
"@angular/platform-browser": "4.2.5", "@angular/platform-browser-dynamic": "4.1.2",
"@angular/platform-browser-dynamic": "4.2.5", "@angular/platform-server": "4.1.2",
"@angular/platform-server": "4.2.5", "@angular/router": "4.1.2",
"@angular/router": "4.2.5", "@types/node": "7.0.18",
"@ngtools/webpack": "1.5.0",
"@types/node": "8.0.8",
"angular2-template-loader": "0.6.2", "angular2-template-loader": "0.6.2",
"aspnet-prerendering": "^2.0.5", "aspnet-prerendering": "^2.0.5",
"aspnet-webpack": "^1.0.29", "aspnet-webpack": "^1.0.29",
"awesome-typescript-loader": "3.2.1", "awesome-typescript-loader": "3.1.3",
"bootstrap": "3.3.7", "bootstrap": "3.3.7",
"css": "2.2.1", "css": "2.2.1",
"css-loader": "0.28.4", "css-loader": "0.28.1",
"es6-shim": "0.35.3", "es6-shim": "0.35.3",
"event-source-polyfill": "0.0.9", "event-source-polyfill": "0.0.9",
"expose-loader": "0.7.3", "expose-loader": "0.7.3",
"extract-text-webpack-plugin": "2.1.2", "extract-text-webpack-plugin": "2.1.0",
"file-loader": "0.11.2", "file-loader": "0.11.1",
"html-loader": "0.4.5", "html-loader": "0.4.5",
"isomorphic-fetch": "2.2.1", "isomorphic-fetch": "2.2.1",
"jquery": "3.2.1", "jquery": "3.2.1",
@@ -38,24 +35,24 @@
"preboot": "4.5.2", "preboot": "4.5.2",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"reflect-metadata": "0.1.10", "reflect-metadata": "0.1.10",
"rxjs": "5.4.2", "rxjs": "5.4.0",
"style-loader": "0.18.2", "style-loader": "0.17.0",
"to-string-loader": "1.1.5", "to-string-loader": "1.1.5",
"typescript": "2.4.1", "typescript": "2.3.2",
"url-loader": "0.5.9", "url-loader": "0.5.8",
"webpack": "2.5.1", "webpack": "2.5.1",
"webpack-hot-middleware": "2.18.2", "webpack-hot-middleware": "2.18.0",
"webpack-merge": "4.1.0", "webpack-merge": "4.1.0",
"zone.js": "0.8.12" "zone.js": "0.8.10"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "4.0.1", "@types/chai": "3.5.2",
"@types/jasmine": "2.5.53", "@types/jasmine": "2.5.47",
"chai": "4.0.2", "chai": "3.5.0",
"jasmine-core": "2.6.4", "jasmine-core": "2.6.1",
"karma": "1.7.0", "karma": "1.7.0",
"karma-chai": "0.1.0", "karma-chai": "0.1.0",
"karma-chrome-launcher": "2.2.0", "karma-chrome-launcher": "2.1.1",
"karma-cli": "1.0.1", "karma-cli": "1.0.1",
"karma-jasmine": "1.1.0", "karma-jasmine": "1.1.0",
"karma-webpack": "2.0.3" "karma-webpack": "2.0.3"

View File

@@ -1,7 +1,6 @@
const path = require('path'); const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const merge = require('webpack-merge'); const merge = require('webpack-merge');
const AotPlugin = require('@ngtools/webpack').AotPlugin;
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
module.exports = (env) => { module.exports = (env) => {
@@ -17,7 +16,7 @@ module.exports = (env) => {
}, },
module: { module: {
rules: [ rules: [
{ test: /\.ts$/, include: /ClientApp/, use: isDevBuild ? ['awesome-typescript-loader?silent=true', 'angular2-template-loader'] : '@ngtools/webpack' }, { test: /\.ts$/, include: /ClientApp/, use: ['awesome-typescript-loader?silent=true', 'angular2-template-loader'] },
{ test: /\.html$/, use: 'html-loader?minimize=false' }, { test: /\.html$/, use: 'html-loader?minimize=false' },
{ test: /\.css$/, use: [ 'to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] }, { test: /\.css$/, use: [ 'to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' } { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
@@ -29,7 +28,7 @@ module.exports = (env) => {
// Configuration for client-side bundle suitable for running in browsers // Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist'; const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig, { const clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot.browser.ts' }, entry: { 'main-client': './ClientApp/boot-client.ts' },
output: { path: path.join(__dirname, clientBundleOutputDir) }, output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [ plugins: [
new webpack.DllReferencePlugin({ new webpack.DllReferencePlugin({
@@ -44,19 +43,14 @@ module.exports = (env) => {
}) })
] : [ ] : [
// Plugins that apply in production builds only // Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(), new webpack.optimize.UglifyJsPlugin()
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.module.browser#AppModule'),
exclude: ['./**/*.server.ts']
})
]) ])
}); });
// Configuration for server-side (prerendering) bundle suitable for running in Node // Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig, { const serverBundleConfig = merge(sharedConfig, {
resolve: { mainFields: ['main'] }, resolve: { mainFields: ['main'] },
entry: { 'main-server': './ClientApp/boot.server.ts' }, entry: { 'main-server': './ClientApp/boot-server.ts' },
plugins: [ plugins: [
new webpack.DllReferencePlugin({ new webpack.DllReferencePlugin({
context: __dirname, context: __dirname,
@@ -64,14 +58,7 @@ module.exports = (env) => {
sourceType: 'commonjs2', sourceType: 'commonjs2',
name: './vendor' name: './vendor'
}) })
].concat(isDevBuild ? [] : [ ],
// Plugins that apply in production builds only
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.module.server#AppModule'),
exclude: ['./**/*.browser.ts']
})
]),
output: { output: {
libraryTarget: 'commonjs', libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist') path: path.join(__dirname, './ClientApp/dist')

View File

@@ -2,27 +2,6 @@ const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge'); const merge = require('webpack-merge');
const treeShakableModules = [
'@angular/animations',
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'zone.js',
];
const nonTreeShakableModules = [
'bootstrap',
'bootstrap/dist/css/bootstrap.css',
'es6-promise',
'es6-shim',
'event-source-polyfill',
'jquery',
];
const allModules = treeShakableModules.concat(nonTreeShakableModules);
module.exports = (env) => { module.exports = (env) => {
const extractCSS = new ExtractTextPlugin('vendor.css'); const extractCSS = new ExtractTextPlugin('vendor.css');
@@ -35,6 +14,26 @@ module.exports = (env) => {
{ test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' } { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' }
] ]
}, },
entry: {
vendor: [
'@angular/animations',
'@angular/common',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/http',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'bootstrap',
'bootstrap/dist/css/bootstrap.css',
'es6-shim',
'es6-promise',
'event-source-polyfill',
'jquery',
'zone.js',
]
},
output: { output: {
publicPath: '/dist/', publicPath: '/dist/',
filename: '[name].js', filename: '[name].js',
@@ -49,11 +48,6 @@ module.exports = (env) => {
}; };
const clientBundleConfig = merge(sharedConfig, { const clientBundleConfig = merge(sharedConfig, {
entry: {
// To keep development builds fast, include all vendor dependencies in the vendor bundle.
// But for production builds, leave the tree-shakable ones out so the AOT compiler can produce a smaller bundle.
vendor: isDevBuild ? allModules : nonTreeShakableModules
},
output: { path: path.join(__dirname, 'wwwroot', 'dist') }, output: { path: path.join(__dirname, 'wwwroot', 'dist') },
module: { module: {
rules: [ rules: [
@@ -74,7 +68,6 @@ module.exports = (env) => {
const serverBundleConfig = merge(sharedConfig, { const serverBundleConfig = merge(sharedConfig, {
target: 'node', target: 'node',
resolve: { mainFields: ['main'] }, resolve: { mainFields: ['main'] },
entry: { vendor: allModules.concat(['aspnet-prerendering']) },
output: { output: {
path: path.join(__dirname, 'ClientApp', 'dist'), path: path.join(__dirname, 'ClientApp', 'dist'),
libraryTarget: 'commonjs2', libraryTarget: 'commonjs2',
@@ -82,6 +75,7 @@ module.exports = (env) => {
module: { module: {
rules: [ { test: /\.css(\?|$)/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] } ] rules: [ { test: /\.css(\?|$)/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] } ]
}, },
entry: { vendor: ['aspnet-prerendering'] },
plugins: [ plugins: [
new webpack.DllPlugin({ new webpack.DllPlugin({
path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'), path: path.join(__dirname, 'ClientApp', 'dist', '[name]-manifest.json'),

View File

@@ -5,17 +5,19 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"aurelia-bootstrapper": "^2.0.1", "aurelia-bootstrapper": "^2.0.1",

View File

@@ -5,17 +5,19 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"@types/core-js": "^0.9.34", "@types/core-js": "^0.9.34",

View File

@@ -62,8 +62,7 @@ export const actionCreators = {
const unloadedState: WeatherForecastsState = { startDateIndex: null, forecasts: [], isLoading: false }; const unloadedState: WeatherForecastsState = { startDateIndex: null, forecasts: [], isLoading: false };
export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState, incomingAction: Action) => { export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState, action: KnownAction) => {
const action = incomingAction as KnownAction;
switch (action.type) { switch (action.type) {
case 'REQUEST_WEATHER_FORECASTS': case 'REQUEST_WEATHER_FORECASTS':
return { return {

View File

@@ -5,17 +5,19 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,42 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@types/history": "4.6.0", "@types/history": "4.5.1",
"@types/react": "15.0.35", "@types/react": "15.0.24",
"@types/react-dom": "15.5.1", "@types/react-dom": "15.5.0",
"@types/react-redux": "4.4.45", "@types/react-redux": "4.4.40",
"@types/react-router": "4.0.12", "@types/react-router-dom": "4.0.4",
"@types/react-router-dom": "4.0.5", "@types/react-router-redux": "5.0.1",
"@types/react-router-redux": "5.0.3",
"@types/webpack": "2.2.15", "@types/webpack": "2.2.15",
"@types/webpack-env": "1.13.0", "@types/webpack-env": "1.13.0",
"aspnet-prerendering": "^2.0.5", "aspnet-prerendering": "^2.0.5",
"aspnet-webpack": "^1.0.29", "aspnet-webpack": "^1.0.29",
"aspnet-webpack-react": "^3.0.0-beta", "aspnet-webpack-react": "^2.0.0",
"awesome-typescript-loader": "3.2.1", "awesome-typescript-loader": "3.1.3",
"bootstrap": "3.3.7", "bootstrap": "3.3.7",
"css-loader": "0.28.4", "css-loader": "0.28.1",
"domain-task": "^3.0.3", "domain-task": "^3.0.0",
"event-source-polyfill": "0.0.9", "event-source-polyfill": "0.0.9",
"extract-text-webpack-plugin": "2.1.2", "extract-text-webpack-plugin": "2.1.0",
"file-loader": "0.11.2", "file-loader": "0.11.1",
"history": "4.6.3", "history": "4.6.1",
"jquery": "3.2.1", "jquery": "3.2.1",
"json-loader": "0.5.4", "json-loader": "0.5.4",
"node-noop": "1.0.0", "node-noop": "1.0.0",
"react": "15.6.1", "react": "15.5.4",
"react-dom": "15.6.1", "react-dom": "15.5.4",
"react-hot-loader": "3.0.0-beta.7", "react-hot-loader": "3.0.0-beta.7",
"react-redux": "5.0.5", "react-redux": "5.0.4",
"react-router-dom": "4.1.1", "react-router-dom": "4.1.1",
"react-router-redux": "5.0.0-alpha.6", "react-router-redux": "5.0.0-alpha.6",
"redux": "3.7.1", "redux": "3.6.0",
"redux-thunk": "2.2.0", "redux-thunk": "2.2.0",
"style-loader": "0.18.2", "style-loader": "0.17.0",
"typescript": "2.4.1", "typescript": "2.3.2",
"url-loader": "0.5.9", "url-loader": "0.5.8",
"webpack": "2.5.1", "webpack": "2.5.1",
"webpack-hot-middleware": "2.18.2", "webpack-hot-middleware": "2.18.0",
"webpack-merge": "4.1.0" "webpack-merge": "4.1.0"
} }
} }

View File

@@ -5,17 +5,19 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,31 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"@types/history": "4.6.0", "@types/history": "4.5.1",
"@types/react": "15.0.35", "@types/react": "15.0.24",
"@types/react-dom": "15.5.1", "@types/react-dom": "15.5.0",
"@types/react-router": "4.0.12", "@types/react-router": "4.0.9",
"@types/webpack-env": "1.13.0", "@types/webpack-env": "1.13.0",
"aspnet-webpack": "^1.0.29", "aspnet-webpack": "^1.0.29",
"aspnet-webpack-react": "^3.0.0-beta", "aspnet-webpack-react": "^2.0.0",
"awesome-typescript-loader": "3.2.1", "awesome-typescript-loader": "3.1.3",
"bootstrap": "3.3.7", "bootstrap": "3.3.7",
"css-loader": "0.28.4", "css-loader": "0.28.1",
"event-source-polyfill": "0.0.9", "event-source-polyfill": "0.0.9",
"extract-text-webpack-plugin": "2.1.2", "extract-text-webpack-plugin": "2.1.0",
"file-loader": "0.11.2", "file-loader": "0.11.1",
"isomorphic-fetch": "2.2.1", "isomorphic-fetch": "2.2.1",
"jquery": "3.2.1", "jquery": "3.2.1",
"json-loader": "0.5.4", "json-loader": "0.5.4",
"react": "15.6.1", "react": "15.5.4",
"react-dom": "15.6.1", "react-dom": "15.5.4",
"react-hot-loader": "3.0.0-beta.7", "react-hot-loader": "3.0.0-beta.7",
"react-router-dom": "4.1.1", "react-router-dom": "4.1.1",
"style-loader": "0.18.2", "style-loader": "0.17.0",
"typescript": "2.4.1", "typescript": "2.3.2",
"url-loader": "0.5.9", "url-loader": "0.5.8",
"webpack": "2.5.1", "webpack": "2.5.1",
"webpack-hot-middleware": "2.18.2" "webpack-hot-middleware": "2.18.0"
} }
} }

View File

@@ -5,17 +5,19 @@
<TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework> <TargetFramework Condition="'$(TargetFrameworkOverride)' != ''">TargetFrameworkOverride</TargetFramework>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion> <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''"> <ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" /> <PackageReference Include="NETStandard.Library.NETFramework" Version="2.0.0-preview2-25405-01" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" /> <PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-preview2-final" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-preview2-final" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
{ {
"name": "WebApplicationBasic", "name": "WebApplicationBasic",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"@types/requirejs": "^2.1.28", "@types/requirejs": "^2.1.28",

View File

@@ -7,6 +7,7 @@ const bundleOutputDir = './wwwroot/dist';
module.exports = (env) => { module.exports = (env) => {
const isDevBuild = !(env && env.prod); const isDevBuild = !(env && env.prod);
const bundleOutputDir = './wwwroot/dist';
return [{ return [{
stats: { modules: false }, stats: { modules: false },
context: __dirname, context: __dirname,

View File

@@ -206,10 +206,23 @@ function buildDotNetNewNuGetPackage(packageId: string) {
HostIdentifier: { HostIdentifier: {
type: 'bind', type: 'bind',
binding: 'HostIdentifier' binding: 'HostIdentifier'
},
skipRestore: {
type: 'parameter',
datatype: 'bool',
description: 'If specified, skips the automatic restore of packages on project creation.',
defaultValue: 'false'
} }
}, },
tags: { language: 'C#', type: 'project' }, tags: { language: 'C#', type: 'project' },
postActions: [ postActions: [
{
condition: '(!skipRestore)',
description: 'Restores NuGet packages required by this project.',
manualInstructions: [{ text: 'Run \'dotnet restore\'' }],
actionId: '210D431B-A78B-4D2F-B762-4ED3E3EA9025',
continueOnError: true
},
/* /*
// Currently it doesn't appear to be possible to run `npm install` from a // Currently it doesn't appear to be possible to run `npm install` from a
// postAction, due to https://github.com/dotnet/templating/issues/849 // postAction, due to https://github.com/dotnet/templating/issues/849
@@ -245,6 +258,10 @@ function buildDotNetNewNuGetPackage(packageId: string) {
}, },
Framework: { Framework: {
longName: 'framework' longName: 'framework'
},
skipRestore: {
longName: 'no-restore',
shortName: ''
} }
} }
}, null, 2)); }, null, 2));

View File

@@ -6,6 +6,7 @@ import * as glob from 'glob';
import * as semver from 'semver'; import * as semver from 'semver';
import * as chalk from 'chalk'; import * as chalk from 'chalk';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import npmWhich = require('npm-which');
const yosay = require('yosay'); const yosay = require('yosay');
const toPascalCase = require('to-pascal-case'); const toPascalCase = require('to-pascal-case');
const isWindows = /^win/.test(process.platform); const isWindows = /^win/.test(process.platform);
@@ -164,6 +165,15 @@ class MyGenerator extends yeoman.Base {
} }
installingDeps() { installingDeps() {
// If available, restore dependencies using Yarn instead of NPM
const yarnPath = getPathToExecutable('yarn');
if (!!yarnPath) {
this.log('Will restore NPM dependencies using \'yarn\' installed at ' + yarnPath);
this.npmInstall = (pkgs, options, cb) => {
return (this as any).runInstall(yarnPath, pkgs, options, cb);
};
}
this.installDependencies({ this.installDependencies({
npm: true, npm: true,
bower: false, bower: false,
@@ -176,6 +186,14 @@ class MyGenerator extends yeoman.Base {
} }
} }
function getPathToExecutable(executableName: string) {
try {
return npmWhich(__dirname).sync(executableName);
} catch(ex) {
return null;
}
}
function assertNpmVersionIsAtLeast(minVersion: string) { function assertNpmVersionIsAtLeast(minVersion: string) {
const runningVersion = execSync('npm -v').toString(); const runningVersion = execSync('npm -v').toString();
if (!semver.gte(runningVersion, minVersion, /* loose */ true)) { if (!semver.gte(runningVersion, minVersion, /* loose */ true)) {

View File

@@ -1,6 +1,6 @@
{ {
"name": "generator-aspnetcore-spa", "name": "generator-aspnetcore-spa",
"version": "0.9.4", "version": "0.9.3",
"description": "Single-Page App templates for ASP.NET Core", "description": "Single-Page App templates for ASP.NET Core",
"author": "Microsoft", "author": "Microsoft",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -21,6 +21,7 @@
"chalk": "^1.1.3", "chalk": "^1.1.3",
"glob": "^7.0.3", "glob": "^7.0.3",
"node-uuid": "^1.4.7", "node-uuid": "^1.4.7",
"npm-which": "^3.0.1",
"to-pascal-case": "^1.0.0", "to-pascal-case": "^1.0.0",
"yeoman-generator": "^0.20.2", "yeoman-generator": "^0.20.2",
"yeoman-option-or-prompt": "^1.0.2", "yeoman-option-or-prompt": "^1.0.2",

View File

@@ -1,9 +1,7 @@
<Project> <!-- This file may be overwritten by automation. Only values allowed here are VersionPrefix and VersionSuffix. -->
<Project>
<PropertyGroup> <PropertyGroup>
<VersionPrefix>2.0.3</VersionPrefix> <VersionPrefix>2.0.0</VersionPrefix>
<VersionSuffix>rtm</VersionSuffix> <VersionSuffix>preview2</VersionSuffix>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
<VersionSuffix Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
</PropertyGroup> </PropertyGroup>
</Project> </Project>