Selaa lähdekoodia

Revert "Revert "Improve components infrastructure (#12145)" (#12679)" (#12744)

* Revert "Revert "Improve components infrastructure (#12145)" (#12679)"

This reverts commit e2d57e2806eeeedd91400665985996706ac3ac71. The improvement to components infrastructure is now reinstated with the following changes:

* Check in release JS artifacts and use them as a fallback when it's not possible to build npmproj.
* Dont' build nodejs in source build.
John Luo 6 vuotta sitten
vanhempi
sitoutus
43350b57b9

+ 17 - 3
.azure/pipelines/ci.yml

@@ -29,7 +29,9 @@ variables:
 - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
 - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
   - name: _BuildArgs
   - name: _BuildArgs
     value: ''
     value: ''
+
 jobs:
 jobs:
+# Code check
 - template: jobs/default-build.yml
 - template: jobs/default-build.yml
   parameters:
   parameters:
     jobName: Code_check
     jobName: Code_check
@@ -38,6 +40,10 @@ jobs:
     steps:
     steps:
     - powershell: ./eng/scripts/CodeCheck.ps1 -ci
     - powershell: ./eng/scripts/CodeCheck.ps1 -ci
       displayName: Run eng/scripts/CodeCheck.ps1
       displayName: Run eng/scripts/CodeCheck.ps1
+    artifacts:
+    - name: Code_Check_Logs
+      path: artifacts/log/
+      publishOnError: true
 
 
 # Build Windows (x64/x86)
 # Build Windows (x64/x86)
 - template: jobs/default-build.yml
 - template: jobs/default-build.yml
@@ -171,6 +177,7 @@ jobs:
       -bl:artifacts/log/build.macos.binlog
       -bl:artifacts/log/build.macos.binlog
       $(_BuildArgs)
       $(_BuildArgs)
     installNodeJs: false
     installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: MacOS_x64_Packages
     - name: MacOS_x64_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -191,7 +198,6 @@ jobs:
     jobName: Linux_x64_build
     jobName: Linux_x64_build
     jobDisplayName: "Build: Linux x64"
     jobDisplayName: "Build: Linux x64"
     agentOs: Linux
     agentOs: Linux
-    installNodeJs: false
     steps:
     steps:
     - script: ./build.sh
     - script: ./build.sh
           --ci
           --ci
@@ -211,6 +217,7 @@ jobs:
           --arch x64 \
           --arch x64 \
           --build-installers \
           --build-installers \
           --no-build-deps \
           --no-build-deps \
+          --no-build-nodejs \
           -p:OnlyPackPlatformSpecificPackages=true \
           -p:OnlyPackPlatformSpecificPackages=true \
           -p:BuildRuntimeArchive=false \
           -p:BuildRuntimeArchive=false \
           -p:LinuxInstallerType=deb \
           -p:LinuxInstallerType=deb \
@@ -224,12 +231,15 @@ jobs:
           --arch x64 \
           --arch x64 \
           --build-installers \
           --build-installers \
           --no-build-deps \
           --no-build-deps \
+          --no-build-nodejs \
           -p:OnlyPackPlatformSpecificPackages=true \
           -p:OnlyPackPlatformSpecificPackages=true \
           -p:BuildRuntimeArchive=false \
           -p:BuildRuntimeArchive=false \
           -p:LinuxInstallerType=rpm \
           -p:LinuxInstallerType=rpm \
           -bl:artifacts/log/build.rpm.binlog \
           -bl:artifacts/log/build.rpm.binlog \
           $(_BuildArgs)
           $(_BuildArgs)
       displayName: Build RPM installers
       displayName: Build RPM installers
+    installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: Linux_x64_Packages
     - name: Linux_x64_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -260,6 +270,7 @@ jobs:
       -bl:artifacts/log/build.linux-arm.binlog
       -bl:artifacts/log/build.linux-arm.binlog
       $(_BuildArgs)
       $(_BuildArgs)
     installNodeJs: false
     installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: Linux_arm_Packages
     - name: Linux_arm_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -290,6 +301,7 @@ jobs:
       -bl:artifacts/log/build.arm64.binlog
       -bl:artifacts/log/build.arm64.binlog
       $(_BuildArgs)
       $(_BuildArgs)
     installNodeJs: false
     installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: Linux_arm64_Packages
     - name: Linux_arm64_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -323,6 +335,7 @@ jobs:
       -bl:artifacts/log/build.musl.binlog
       -bl:artifacts/log/build.musl.binlog
       $(_BuildArgs)
       $(_BuildArgs)
     installNodeJs: false
     installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: Linux_musl_x64_Packages
     - name: Linux_musl_x64_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -337,7 +350,7 @@ jobs:
   parameters:
   parameters:
     inputName: Linux_musl_x64
     inputName: Linux_musl_x64
 
 
-# Build Linux Musl arm64
+# Build Linux Musl ARM64
 - template: jobs/default-build.yml
 - template: jobs/default-build.yml
   parameters:
   parameters:
     jobName: Linux_musl_arm64_build
     jobName: Linux_musl_arm64_build
@@ -356,6 +369,7 @@ jobs:
       -bl:artifacts/log/build.musl.binlog
       -bl:artifacts/log/build.musl.binlog
       $(_BuildArgs)
       $(_BuildArgs)
     installNodeJs: false
     installNodeJs: false
+    installJdk: false
     artifacts:
     artifacts:
     - name: Linux_musl_arm64_Packages
     - name: Linux_musl_arm64_Packages
       path: artifacts/packages/
       path: artifacts/packages/
@@ -499,7 +513,7 @@ jobs:
       version: 3.0.x
       version: 3.0.x
       installationPath: $(DotNetCoreSdkDir)
       installationPath: $(DotNetCoreSdkDir)
       includePreviewVersions: true
       includePreviewVersions: true
-  - script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true
+  - script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true /p:BuildNodeJs=false
     displayName: Run ci-source-build.sh
     displayName: Run ci-source-build.sh
   - task: PublishBuildArtifacts@1
   - task: PublishBuildArtifacts@1
     displayName: Upload logs
     displayName: Upload logs

+ 20 - 1
build.ps1

@@ -183,7 +183,7 @@ elseif ($Projects) {
 }
 }
 # When adding new sub-group build flags, add them to this check.
 # When adding new sub-group build flags, add them to this check.
 elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -and (-not $BuildInstallers) -and (-not $BuildJava)) {
 elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -and (-not $BuildInstallers) -and (-not $BuildJava)) {
-    Write-Warning "No default group of projects was specified, so building the 'managed' subsets of projects. Run ``build.cmd -help`` for more details."
+    Write-Warning "No default group of projects was specified, so building the 'managed' and its dependent subsets of projects. Run ``build.cmd -help`` for more details."
 
 
     # This goal of this is to pick a sensible default for `build.cmd` with zero arguments.
     # This goal of this is to pick a sensible default for `build.cmd` with zero arguments.
     # Now that we support subfolder invokations of build.cmd, we will be pushing to have build.cmd build everything (-all) by default
     # Now that we support subfolder invokations of build.cmd, we will be pushing to have build.cmd build everything (-all) by default
@@ -191,6 +191,25 @@ elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -a
     $BuildManaged = $true
     $BuildManaged = $true
 }
 }
 
 
+if ($BuildManaged -or ($All -and (-not $NoBuildManaged))) {
+    if ((-not $BuildNodeJS) -and (-not $NoBuildNodeJS)) {
+        $node = Get-Command node -ErrorAction Ignore -CommandType Application
+
+        if ($node) {
+            $nodeHome = Split-Path -Parent (Split-Path -Parent $node.Path)
+            Write-Host -f Magenta "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected in $nodeHome."
+        }
+        else {
+            Write-Host -f Magenta "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly."
+            $NoBuildNodeJS = $true
+        }
+    }
+
+    if ($NoBuildNodeJS){
+        Write-Warning "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date."
+    }
+}
+
 if ($BuildInstallers) { $MSBuildArguments += "/p:BuildInstallers=true" }
 if ($BuildInstallers) { $MSBuildArguments += "/p:BuildInstallers=true" }
 if ($BuildManaged) { $MSBuildArguments += "/p:BuildManaged=true" }
 if ($BuildManaged) { $MSBuildArguments += "/p:BuildManaged=true" }
 if ($BuildNative) { $MSBuildArguments += "/p:BuildNative=true" }
 if ($BuildNative) { $MSBuildArguments += "/p:BuildNative=true" }

+ 16 - 1
build.sh

@@ -213,7 +213,7 @@ elif [ ! -z "$build_projects" ]; then
 elif [ -z "$build_managed" ] && [ -z "$build_nodejs" ] && [ -z "$build_java" ] && [ -z "$build_native" ] && [ -z "$build_installers" ]; then
 elif [ -z "$build_managed" ] && [ -z "$build_nodejs" ] && [ -z "$build_java" ] && [ -z "$build_native" ] && [ -z "$build_installers" ]; then
     # This goal of this is to pick a sensible default for `build.sh` with zero arguments.
     # This goal of this is to pick a sensible default for `build.sh` with zero arguments.
     # We believe the most common thing our contributors will work on is C#, so if no other build group was picked, build the C# projects.
     # We believe the most common thing our contributors will work on is C#, so if no other build group was picked, build the C# projects.
-    __warn "No default group of projects was specified, so building the 'managed' subset of projects. Run ``build.sh --help`` for more details."
+    __warn "No default group of projects was specified, so building the 'managed' and its dependent subset of projects. Run ``build.sh --help`` for more details."
     build_managed=true
     build_managed=true
 fi
 fi
 
 
@@ -221,6 +221,21 @@ if [ "$build_deps" = false ]; then
     msbuild_args[${#msbuild_args[*]}]="-p:BuildProjectReferences=false"
     msbuild_args[${#msbuild_args[*]}]="-p:BuildProjectReferences=false"
 fi
 fi
 
 
+if [ "$build_managed" = true ] || (["$build_all" = true ] && [ "$build_managed" != false ]); then
+    if [ -z "$build_nodejs" ]; then
+        if [ -x "$(command -v node)" ]; then
+            __warn "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected on PATH."
+        else
+            __warn "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly."
+            build_nodejs=false
+        fi
+    fi
+
+    if [ "$build_nodejs" = false ]; then
+        __warn "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date."
+    fi
+fi
+
 # Only set these MSBuild properties if they were explicitly set by build parameters.
 # Only set these MSBuild properties if they were explicitly set by build parameters.
 [ ! -z "$build_java" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildJava=$build_java"
 [ ! -z "$build_java" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildJava=$build_java"
 [ ! -z "$build_native" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNative=$build_native"
 [ ! -z "$build_native" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNative=$build_native"

+ 4 - 2
docs/BuildFromSource.md

@@ -97,14 +97,14 @@ The cause of this problem is that the solution you are using does not include th
    ```
    ```
 
 
 ### Common error: Unable to locate the .NET Core SDK
 ### Common error: Unable to locate the .NET Core SDK
-  
+
 Executing `.\restore.cmd` or `.\build.cmd` may produce these errors:
 Executing `.\restore.cmd` or `.\build.cmd` may produce these errors:
 
 
 > error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version.
 > error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version.
 > error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found.
 > error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found.
 
 
 In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_.
 In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_.
-  
+
 ## Building with Visual Studio Code
 ## Building with Visual Studio Code
 
 
 Using Visual Studio Code with this repo requires setting environment variables on command line first.
 Using Visual Studio Code with this repo requires setting environment variables on command line first.
@@ -138,6 +138,8 @@ On macOS/Linux:
 ./build.sh
 ./build.sh
 ```
 ```
 
 
+By default, all of the C# projects are built. Some C# projects requires NodeJS to be installed to compile JavaScript assets which are then checked in as source. If NodeJS is detected on the path, the NodeJS projects will be compiled as part of building C# projects. If NodeJS is not detected on the path, the JavaScript assets checked in previously will be used instead. To disable building NodeJS projects, specify /p:BuildNodeJs=false on the command line.
+
 ### Using `dotnet` on command line in this repo
 ### Using `dotnet` on command line in this repo
 
 
 Because we are using pre-release versions of .NET Core, you have to set a handful of environment variables
 Because we are using pre-release versions of .NET Core, you have to set a handful of environment variables

+ 8 - 5
eng/Build.props

@@ -4,14 +4,16 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <PropertyGroup Condition=" '$(BuildAllProjects)' == 'true' ">
   <PropertyGroup Condition=" '$(BuildAllProjects)' == 'true' ">
-    <BuildNative>true</BuildNative>
-    <BuildManaged>true</BuildManaged>
-    <BuildNodeJS>true</BuildNodeJS>
-    <BuildJava>true</BuildJava>
+    <BuildNative Condition="'$(BuildNative)' == ''">true</BuildNative>
+    <BuildManaged Condition="'$(BuildManaged)' == ''">true</BuildManaged>
+    <BuildNodeJS Condition="'$(BuildNodeJS)' == ''">true</BuildNodeJS>
+    <BuildJava Condition="'$(BuildJava)' == ''">true</BuildJava>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <!-- These projects are always excluded, even when -projects is specified on command line. -->
   <!-- These projects are always excluded, even when -projects is specified on command line. -->
   <ItemGroup>
   <ItemGroup>
+    <!-- Explicitly excluded projects -->
+    <ProjectToExclude Include="$(ProjectToExclude)" />
 
 
     <!-- These projects use 'legacy' csproj, which is not supported by dotnet-msbuild. -->
     <!-- These projects use 'legacy' csproj, which is not supported by dotnet-msbuild. -->
     <ProjectToExclude Include="
     <ProjectToExclude Include="
@@ -31,6 +33,7 @@
                       $(RepoRoot)src\submodules\**\*.*proj;
                       $(RepoRoot)src\submodules\**\*.*proj;
                       $(RepoRoot)src\Installers\**\*.*proj;
                       $(RepoRoot)src\Installers\**\*.*proj;
                       $(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
                       $(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
+                      $(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
                       $(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj;
                       $(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
                       $(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
@@ -43,7 +46,6 @@
                       $(RepoRoot)src\Servers\Kestrel\perf\PlatformBenchmarks\**\*.csproj;
                       $(RepoRoot)src\Servers\Kestrel\perf\PlatformBenchmarks\**\*.csproj;
                       $(RepoRoot)src\SignalR\perf\benchmarkapps\**\*.csproj;
                       $(RepoRoot)src\SignalR\perf\benchmarkapps\**\*.csproj;
                       " />
                       " />
-
   </ItemGroup>
   </ItemGroup>
 
 
   <Choose>
   <Choose>
@@ -102,6 +104,7 @@
         <ProjectToExclude Condition=" '$(BuildNative)' != 'true'" Include="@(NativeProjects)" />
         <ProjectToExclude Condition=" '$(BuildNative)' != 'true'" Include="@(NativeProjects)" />
 
 
         <NodeJsProjects Include="
         <NodeJsProjects Include="
+                          $(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj;
                           $(RepoRoot)src\SignalR\**\*.npmproj;
                           $(RepoRoot)src\SignalR\**\*.npmproj;
                           $(RepoRoot)src\Middleware\**\*.npmproj;
                           $(RepoRoot)src\Middleware\**\*.npmproj;
                           "
                           "

+ 0 - 5
eng/scripts/CodeCheck.ps1

@@ -166,11 +166,6 @@ try {
         & dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/"
         & dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/"
     }
     }
 
 
-    Write-Host "Re-generating Web.JS files"
-    Invoke-Block {
-        & dotnet build "$repoRoot\src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
-    }
-
     Write-Host "Run git diff to check for pending changes"
     Write-Host "Run git diff to check for pending changes"
 
 
     # Redirect stderr to stdout because PowerShell does not consistently handle output to stderr
     # Redirect stderr to stdout because PowerShell does not consistently handle output to stderr

+ 15 - 2
eng/targets/Npm.Common.targets

@@ -11,15 +11,28 @@
     <IntermediateOutputPath>$([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\</IntermediateOutputPath>
     <IntermediateOutputPath>$([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\</IntermediateOutputPath>
     <InstallArgs Condition="'$(RestoreLockedMode)' == 'true'">--frozen-lockfile</InstallArgs>
     <InstallArgs Condition="'$(RestoreLockedMode)' == 'true'">--frozen-lockfile</InstallArgs>
     <_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak</_BackupPackageJson>
     <_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak</_BackupPackageJson>
+    <BuildDependsOn>
+      PrepareForBuild;
+      ResolveProjectReferences;
+      _Build;
+    </BuildDependsOn>
+    <NpmBuildArgs Condition="'$(NpmBuildArgs)' == ''">run build</NpmBuildArgs>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
     <TSFiles Include="$(MSBuildProjectDirectory)\*\*.ts" />
     <TSFiles Include="$(MSBuildProjectDirectory)\*\*.ts" />
     <TSFiles Include="$(MSBuildProjectDirectory)\package.json" />
     <TSFiles Include="$(MSBuildProjectDirectory)\package.json" />
+    <TSFiles Include="$(MSBuildProjectDirectory)\*.npmproj" />
   </ItemGroup>
   </ItemGroup>
 
 
   <Target Name="_CheckForInvalidConfiguration">
   <Target Name="_CheckForInvalidConfiguration">
     <Error Text="Missing expected property: PackageId" Condition="'$(IsPackable)' != 'false' and '$(PackageId)' == ''" />
     <Error Text="Missing expected property: PackageId" Condition="'$(IsPackable)' != 'false' and '$(PackageId)' == ''" />
+
+    <Exec ContinueOnError="true" Command="node -v">
+       <Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
+    </Exec>
+
+    <Error Text="Building *.npmproj but NodeJS was not detected on path. Ensure NodeJS is on path or disable building NodeJS projects with /p:BuildNodeJs=false. Skipping NodeJS projects will also skip managed projects depending on them, including Components, Mvc and Analysers." Condition="'$(ErrorCode)' != '0'"/>
   </Target>
   </Target>
 
 
   <Target Name="Restore">
   <Target Name="Restore">
@@ -36,13 +49,13 @@
              BuildInParallel="true" />
              BuildInParallel="true" />
   </Target>
   </Target>
 
 
-  <Target Name="Build" DependsOnTargets="PrepareForBuild;ResolveProjectReferences;_Build" />
+  <Target Name="Build" DependsOnTargets="$(BuildDependsOn)" />
 
 
   <Target Name="_Build"
   <Target Name="_Build"
     Condition="'$(IsBuildable)' != 'false'"
     Condition="'$(IsBuildable)' != 'false'"
     Inputs="@(TSFiles)"
     Inputs="@(TSFiles)"
     Outputs="$(BaseIntermediateOutputPath)\build-sentinel" >
     Outputs="$(BaseIntermediateOutputPath)\build-sentinel" >
-    <Yarn Command="run build" StandardOutputImportance="High" StandardErrorImportance="High" />
+    <Yarn Command="$(NpmBuildArgs)" StandardOutputImportance="High" StandardErrorImportance="High" />
     <WriteLinesToFile Overwrite="true" File="$(BaseIntermediateOutputPath)\build-sentinel" />
     <WriteLinesToFile Overwrite="true" File="$(BaseIntermediateOutputPath)\build-sentinel" />
   </Target>
   </Target>
 
 

+ 0 - 3
src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj

@@ -11,7 +11,4 @@
     <!-- loader.js is hard-coded to assume it can load .pdbs regardless of Debug/Release configuration -->
     <!-- loader.js is hard-coded to assume it can load .pdbs regardless of Debug/Release configuration -->
     <BlazorEnableDebugging>true</BlazorEnableDebugging>
     <BlazorEnableDebugging>true</BlazorEnableDebugging>
   </PropertyGroup>
   </PropertyGroup>
-
-  <ItemGroup>
-  </ItemGroup>
 </Project>
 </Project>

+ 10 - 0
src/Components/Directory.Build.targets

@@ -5,6 +5,16 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <None Include="$(MSBuildThisFileDirectory)THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="." />
     <None Include="$(MSBuildThisFileDirectory)THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="." />
+
+    <!-- Add a project dependency without reference output assemblies to enforce build order -->
+    <!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
+    <ProjectReference
+      Condition="'$(ReferenceBlazorBuildLocally)' == 'true' and '$(BuildNodeJS)' != 'false'"
+      Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
+      ReferenceOutputAssemblies="false"
+      SkipGetTargetFrameworkProperties="true"
+      UndefineProperties="TargetFramework"
+      Private="false" />
   </ItemGroup>
   </ItemGroup>
 
 
   <Import Project="Blazor\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />
   <Import Project="Blazor\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />

+ 11 - 6
src/Components/Server/src/Microsoft.AspNetCore.Components.Server.csproj

@@ -21,6 +21,16 @@
     <Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
     <Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
     <Reference Include="Microsoft.Extensions.Logging" />
     <Reference Include="Microsoft.Extensions.Logging" />
     <Reference Include="Microsoft.Extensions.ValueStopwatch.Sources" PrivateAssets="All" />
     <Reference Include="Microsoft.Extensions.ValueStopwatch.Sources" PrivateAssets="All" />
+
+    <!-- Add a project dependency without reference output assemblies to enforce build order -->
+    <!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
+    <ProjectReference
+      Include="..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
+      ReferenceOutputAssemblies="false"
+      SkipGetTargetFrameworkProperties="true"
+      UndefineProperties="TargetFramework"
+      Private="false"
+      Condition="'$(BuildNodeJS)' != 'false'" />
   </ItemGroup>
   </ItemGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>
@@ -53,12 +63,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <!--
-      We check in the Release / Production build of blazor.*.js, but not the Debug builds. Consequently the former is always available to embed, the latter is only available
-      if Web.JS was built locally. Use the Debug build when available and building in Debug configuration.
-    -->
-    <BlazorServerJSFile>..\..\Web.JS\dist\Release\blazor.server.js</BlazorServerJSFile>
-    <BlazorServerJSFile Condition="'$(Configuration)' == 'Debug' AND Exists('..\..\Web.JS\dist\Debug\blazor.server.js')">..\..\Web.JS\dist\Debug\blazor.server.js</BlazorServerJSFile>
+    <BlazorServerJSFile>..\..\Web.JS\dist\$(Configuration)\blazor.server.js</BlazorServerJSFile>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>

+ 12 - 2
src/Components/Web.JS/Microsoft.AspNetCore.Components.Web.JS.npmproj

@@ -7,8 +7,18 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\SignalR\clients\ts\signalr\signalr.npmproj" />
-    <ProjectReference Include="..\..\SignalR\clients\ts\signalr-protocol-msgpack\signalr-protocol-msgpack.npmproj" />
+    <ProjectReference
+      Include="..\..\SignalR\clients\ts\signalr\signalr.npmproj"
+      ReferenceOutputAssemblies="false"
+      SkipGetTargetFrameworkProperties="true"
+      UndefineProperties="TargetFramework"
+      Private="false" />
+    <ProjectReference
+      Include="..\..\SignalR\clients\ts\signalr-protocol-msgpack\signalr-protocol-msgpack.npmproj"
+      ReferenceOutputAssemblies="false"
+      SkipGetTargetFrameworkProperties="true"
+      UndefineProperties="TargetFramework"
+      Private="false" />
   </ItemGroup>
   </ItemGroup>
 
 
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />

+ 6 - 2
src/Components/Web.JS/package.json

@@ -5,9 +5,12 @@
   "description": "",
   "description": "",
   "main": "index.js",
   "main": "index.js",
   "scripts": {
   "scripts": {
+    "preclean": "yarn install --mutex network",
+    "clean": "node node_modules/rimraf/bin.js ./dist/Debug ./dist/Release",
+    "prebuild": "yarn run clean && yarn install --mutex network",
     "build": "yarn run build:debug && yarn run build:production",
     "build": "yarn run build:debug && yarn run build:production",
-    "build:debug": "cd src && webpack --mode development --config ./webpack.config.js",
-    "build:production": "cd src && webpack --mode production --config ./webpack.config.js",
+    "build:debug": "cd src && node ../node_modules/webpack-cli/bin/cli.js --mode development --config ./webpack.config.js",
+    "build:production": "cd src && node ../node_modules/webpack-cli/bin/cli.js --mode production --config ./webpack.config.js",
     "test": "jest"
     "test": "jest"
   },
   },
   "devDependencies": {
   "devDependencies": {
@@ -21,6 +24,7 @@
     "@typescript-eslint/parser": "^1.5.0",
     "@typescript-eslint/parser": "^1.5.0",
     "eslint": "^5.16.0",
     "eslint": "^5.16.0",
     "jest": "^24.8.0",
     "jest": "^24.8.0",
+    "rimraf": "^2.6.2",
     "ts-jest": "^24.0.0",
     "ts-jest": "^24.0.0",
     "ts-loader": "^4.4.1",
     "ts-loader": "^4.4.1",
     "typescript": "^3.5.3",
     "typescript": "^3.5.3",

+ 18 - 17
src/Components/Web.JS/tests/DefaultReconnectionHandler.test.ts

@@ -58,23 +58,24 @@ describe('DefaultReconnectionHandler', () => {
     expect(reconnect).toHaveBeenCalledTimes(1);
     expect(reconnect).toHaveBeenCalledTimes(1);
   });
   });
 
 
-  it('invokes failed if reconnect fails', async () => {
-    const testDisplay = createTestDisplay();
-    const reconnect = jest.fn().mockRejectedValue(null);
-    const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
-    window.console.error = jest.fn();
-
-    handler.onConnectionDown({
-      maxRetries: 3,
-      retryIntervalMilliseconds: 20,
-      dialogId: 'ignored'
-    });
-
-    await delay(100);
-    expect(testDisplay.show).toHaveBeenCalled();
-    expect(testDisplay.failed).toHaveBeenCalled();
-    expect(reconnect).toHaveBeenCalledTimes(3);
-  });
+  // Skipped while under investigation: https://github.com/aspnet/AspNetCore/issues/12578
+  // it('invokes failed if reconnect fails', async () => {
+  //   const testDisplay = createTestDisplay();
+  //   const reconnect = jest.fn().mockRejectedValue(null);
+  //   const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
+  //   window.console.error = jest.fn();
+
+  //   handler.onConnectionDown({
+  //     maxRetries: 3,
+  //     retryIntervalMilliseconds: 20,
+  //     dialogId: 'ignored'
+  //   });
+
+  //   await delay(500);
+  //   expect(testDisplay.show).toHaveBeenCalled();
+  //   expect(testDisplay.failed).toHaveBeenCalled();
+  //   expect(reconnect).toHaveBeenCalledTimes(3);
+  // });
 });
 });
 
 
 function attachUserSpecifiedUI(options: ReconnectionOptions): Element {
 function attachUserSpecifiedUI(options: ReconnectionOptions): Element {

+ 22 - 5
src/Components/Web.JS/yarn.lock

@@ -2141,7 +2141,7 @@ glob-parent@^3.1.0:
     is-glob "^3.1.0"
     is-glob "^3.1.0"
     path-dirname "^1.0.0"
     path-dirname "^1.0.0"
 
 
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
+glob@^7.1.1, glob@^7.1.2:
   version "7.1.3"
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
   integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
   integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@@ -2153,6 +2153,18 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
     once "^1.3.0"
     once "^1.3.0"
     path-is-absolute "^1.0.0"
     path-is-absolute "^1.0.0"
 
 
+glob@^7.1.3:
+  version "7.1.4"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
+  integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
 [email protected]:
 [email protected]:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
   resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
@@ -2402,16 +2414,21 @@ inflight@^1.0.4:
     once "^1.3.0"
     once "^1.3.0"
     wrappy "1"
     wrappy "1"
 
 
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
-  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 
 
 [email protected]:
 [email protected]:
   version "2.0.1"
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
   integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
   integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
 
 
[email protected]:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+  integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
 ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
 ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
   version "1.3.5"
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"

+ 1 - 1
src/Shared/E2ETesting/E2ETesting.targets

@@ -11,7 +11,7 @@
       Importance="High"
       Importance="High"
       Text="Prerequisites were not enforced at build time. Running Yarn or the E2E tests might fail as a result. Check /src/Shared/E2ETesting/Readme.md for instructions." />
       Text="Prerequisites were not enforced at build time. Running Yarn or the E2E tests might fail as a result. Check /src/Shared/E2ETesting/Readme.md for instructions." />
 
 
-    <Yarn Command="install --mutex network" />
+    <Yarn Command="install --mutex network" Condition="'$(EnforceE2ETestPrerequisites)' == 'true'"/>
   </Target>
   </Target>
 
 
   <Target
   <Target

+ 1 - 0
src/SignalR/clients/ts/FunctionalTests/SignalR.Npm.FunctionalTests.npmproj

@@ -8,6 +8,7 @@
     <_TestSauceArgs>--verbose --no-color --configuration $(Configuration) --sauce-user "$(SauceUser)" --sauce-key "$(SauceKey)"</_TestSauceArgs>
     <_TestSauceArgs>--verbose --no-color --configuration $(Configuration) --sauce-user "$(SauceUser)" --sauce-key "$(SauceKey)"</_TestSauceArgs>
     <_TestSauceArgs Condition="'$(BrowserTestHostName)' != ''">$(_TestSauceArgs) --use-hostname "$(BrowserTestHostName)"</_TestSauceArgs>
     <_TestSauceArgs Condition="'$(BrowserTestHostName)' != ''">$(_TestSauceArgs) --use-hostname "$(BrowserTestHostName)"</_TestSauceArgs>
     <NpmTestArgs Condition="'$(DailyTests)' != 'true'">run test:inner --no-color --configuration $(Configuration)</NpmTestArgs>
     <NpmTestArgs Condition="'$(DailyTests)' != 'true'">run test:inner --no-color --configuration $(Configuration)</NpmTestArgs>
+    <NpmBuildArgs>run build:inner</NpmBuildArgs>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>