diff --git a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Compression.targets b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Compression.targets
index d14cea18509d..1042c438908f 100644
--- a/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Compression.targets
+++ b/src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Compression.targets
@@ -14,6 +14,7 @@ Copyright (c) .NET Foundation. All rights reserved.
+
@@ -225,7 +226,7 @@ Copyright (c) .NET Foundation. All rights reserved.
@@ -276,6 +277,27 @@ Copyright (c) .NET Foundation. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
();
+
+ var candidatesByIdentity = candidates.ToDictionary(asset => asset.Identity, OSPath.PathComparer);
+
+ foreach (var candidate in candidates)
+ {
+ if (HasCompressionExtension(candidate.RelativePath) &&
+ // We only care about assets that are not already considered compressed
+ !IsCompressedAsset(candidate) &&
+ // The candidate doesn't already have a related asset
+ string.IsNullOrEmpty(candidate.RelatedAsset))
+ {
+ Log.LogMessage(
+ MessageImportance.Low,
+ "The asset '{0}' was detected as compressed but it didn't specify a related asset.",
+ candidate.Identity);
+ var relatedAsset = FindRelatedAsset(candidate, candidatesByIdentity);
+ if (relatedAsset is null)
+ {
+ Log.LogMessage(
+ MessageImportance.Low,
+ "The asset '{0}' was detected as compressed but the related asset with relative path '{1}' was not found.",
+ candidate.Identity,
+ Path.GetFileNameWithoutExtension(candidate.RelativePath));
+ continue;
+ }
+
+ Log.LogMessage(
+ "The asset '{0}' was detected as compressed and the related asset '{1}' was found.",
+ candidate.Identity,
+ relatedAsset.Identity);
+ UpdateCompressedAsset(candidate, relatedAsset);
+ assetsToUpdate.Add(candidate.ToTaskItem());
+ }
+ }
+
+ DiscoveredCompressedAssets = [.. assetsToUpdate];
+
+ return !Log.HasLoggedErrors;
+ }
+
+ private StaticWebAsset FindRelatedAsset(StaticWebAsset candidate, IDictionary candidates)
+ {
+ // The only pattern that we support is a related asset that lives in the same directory, with the same name,
+ // but without the compression extension. In any other case we are not going to consider the assets related
+ // and an error will occur.
+ var identityWithoutExtension = candidate.Identity.Substring(0, candidate.Identity.Length - 3); // We take advantage we know the extension is .br or .gz.
+ return candidates.TryGetValue(identityWithoutExtension, out var relatedAsset) ? relatedAsset : null;
+ }
+
+ private bool HasCompressionExtension(string relativePath)
+ {
+ return relativePath.EndsWith(".gz", StringComparison.OrdinalIgnoreCase) ||
+ relativePath.EndsWith(".br", StringComparison.OrdinalIgnoreCase);
+ }
+
+ private static bool IsCompressedAsset(StaticWebAsset asset)
+ => string.Equals("Content-Encoding", asset.AssetTraitName, StringComparison.Ordinal);
+
+ private void UpdateCompressedAsset(StaticWebAsset asset, StaticWebAsset relatedAsset)
+ {
+ string fileExtension;
+ string assetTraitValue;
+
+ if (!asset.RelativePath.EndsWith(".gz", StringComparison.OrdinalIgnoreCase))
+ {
+ fileExtension = ".br";
+ assetTraitValue = BrotliAssetTraitValue;
+ }
+ else
+ {
+ fileExtension = ".gz";
+ assetTraitValue = GzipAssetTraitValue;
+ }
+
+ var originalItemSpec = asset.OriginalItemSpec;
+ var relativePath = relatedAsset.EmbedTokens(relatedAsset.RelativePath);
+
+ asset.RelativePath = $"{relativePath}{fileExtension}";
+ asset.OriginalItemSpec = relatedAsset.Identity;
+ asset.RelatedAsset = relatedAsset.Identity;
+ asset.AssetRole = "Alternative";
+ asset.AssetTraitName = "Content-Encoding";
+ asset.AssetTraitValue = assetTraitValue;
+ }
+}
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/DiscoverPrecompressedAssetsTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/DiscoverPrecompressedAssetsTest.cs
new file mode 100644
index 000000000000..e4019c5b1da9
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/DiscoverPrecompressedAssetsTest.cs
@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.AspNetCore.StaticWebAssets.Tasks;
+using Microsoft.Build.Framework;
+using Moq;
+
+namespace Microsoft.NET.Sdk.Razor.Tests;
+
+public class DiscoverPrecompressedAssetsTest
+{
+ public string ItemSpec { get; }
+
+ public string OriginalItemSpec { get; }
+
+ public string OutputBasePath { get; }
+
+ public DiscoverPrecompressedAssetsTest()
+ {
+ OutputBasePath = Path.Combine(TestContext.Current.TestExecutionDirectory, nameof(ResolveCompressedAssetsTest));
+ ItemSpec = Path.Combine(OutputBasePath, Guid.NewGuid().ToString("N") + ".tmp");
+ OriginalItemSpec = Path.Combine(OutputBasePath, Guid.NewGuid().ToString("N") + ".tmp");
+ }
+
+ [Fact]
+ public void DiscoversPrecompressedAssetsCorrectly()
+ {
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var uncompressedCandidate = new StaticWebAsset
+ {
+ Identity = Path.Combine(Environment.CurrentDirectory, "wwwroot", "js", "site.js"),
+ RelativePath = "js/site#[.{fingerprint}]?.js",
+ BasePath = "_content/Test",
+ AssetMode = StaticWebAsset.AssetModes.All,
+ AssetKind = StaticWebAsset.AssetKinds.All,
+ AssetMergeSource = string.Empty,
+ SourceId = "Test",
+ CopyToOutputDirectory = StaticWebAsset.AssetCopyOptions.Never,
+ Fingerprint = "uncompressed",
+ RelatedAsset = string.Empty,
+ ContentRoot = Path.Combine(Environment.CurrentDirectory,"wwwroot"),
+ SourceType = StaticWebAsset.SourceTypes.Discovered,
+ Integrity = "uncompressed-integrity",
+ AssetRole = StaticWebAsset.AssetRoles.Primary,
+ AssetMergeBehavior = string.Empty,
+ AssetTraitValue = string.Empty,
+ AssetTraitName = string.Empty,
+ OriginalItemSpec = Path.Combine("wwwroot", "js", "site.js"),
+ CopyToPublishDirectory = StaticWebAsset.AssetCopyOptions.PreserveNewest
+ };
+
+ var compressedCandidate = new StaticWebAsset
+ {
+ Identity = Path.Combine(Environment.CurrentDirectory, "wwwroot", "js", "site.js.gz"),
+ RelativePath = "js/site.js#[.{fingerprint}]?.gz",
+ BasePath = "_content/Test",
+ AssetMode = StaticWebAsset.AssetModes.All,
+ AssetKind = StaticWebAsset.AssetKinds.All,
+ AssetMergeSource = string.Empty,
+ SourceId = "Test",
+ CopyToOutputDirectory = StaticWebAsset.AssetCopyOptions.Never,
+ Fingerprint = "compressed",
+ RelatedAsset = string.Empty,
+ ContentRoot = Path.Combine(Environment.CurrentDirectory, "wwwroot"),
+ SourceType = StaticWebAsset.SourceTypes.Discovered,
+ Integrity = "compressed-integrity",
+ AssetRole = StaticWebAsset.AssetRoles.Primary,
+ AssetMergeBehavior = string.Empty,
+ AssetTraitValue = string.Empty,
+ AssetTraitName = string.Empty,
+ OriginalItemSpec = Path.Combine("wwwroot", "js", "site.js.gz"),
+ CopyToPublishDirectory = StaticWebAsset.AssetCopyOptions.PreserveNewest
+ };
+
+ var task = new DiscoverPrecompressedAssets
+ {
+ CandidateAssets = [uncompressedCandidate.ToTaskItem(), compressedCandidate.ToTaskItem()],
+ BuildEngine = buildEngine.Object
+ };
+
+ var result = task.Execute();
+
+ result.Should().BeTrue();
+ task.DiscoveredCompressedAssets.Should().ContainSingle();
+ var asset = task.DiscoveredCompressedAssets[0];
+ asset.ItemSpec.Should().Be(compressedCandidate.Identity);
+ asset.GetMetadata("RelatedAsset").Should().Be(uncompressedCandidate.Identity);
+ asset.GetMetadata("OriginalItemSpec").Should().Be(uncompressedCandidate.Identity);
+ asset.GetMetadata("RelativePath").Should().Be("js/site#[.{fingerprint=uncompressed}]?.js.gz");
+ asset.GetMetadata("AssetRole").Should().Be("Alternative");
+ asset.GetMetadata("AssetTraitName").Should().Be("Content-Encoding");
+ asset.GetMetadata("AssetTraitValue").Should().Be("gzip");
+ asset.GetMetadata("Fingerprint").Should().Be("compressed");
+ asset.GetMetadata("Integrity").Should().Be("compressed-integrity");
+ asset.GetMetadata("CopyToPublishDirectory").Should().Be("PreserveNewest");
+ asset.GetMetadata("CopyToOutputDirectory").Should().Be("Never");
+ asset.GetMetadata("AssetMergeSource").Should().Be(string.Empty);
+ asset.GetMetadata("AssetMergeBehavior").Should().Be(string.Empty);
+ asset.GetMetadata("AssetKind").Should().Be("All");
+ asset.GetMetadata("AssetMode").Should().Be("All");
+ asset.GetMetadata("SourceId").Should().Be("Test");
+ asset.GetMetadata("SourceType").Should().Be("Discovered");
+ asset.GetMetadata("ContentRoot").Should().Be(Path.Combine(Environment.CurrentDirectory, $"wwwroot{Path.DirectorySeparatorChar}"));
+ }
+}
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/ResolveCompressedAssetsTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/ResolveCompressedAssetsTest.cs
index bd164de346d6..67878b28dce1 100644
--- a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/ResolveCompressedAssetsTest.cs
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssets/ResolveCompressedAssetsTest.cs
@@ -1,11 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.Metrics;
using Microsoft.AspNetCore.StaticWebAssets.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Moq;
using NuGet.ContentModel;
+using NuGet.Packaging.Core;
namespace Microsoft.NET.Sdk.Razor.Tests;
@@ -70,6 +72,74 @@ public void ResolvesExplicitlyProvidedAssets()
task.AssetsToCompress[1].ItemSpec.Should().EndWith(".br");
}
+ [Fact]
+ public void InfersPreCompressedAssetsCorrectly()
+ {
+ var errorMessages = new List();
+ var buildEngine = new Mock();
+ buildEngine.Setup(e => e.LogErrorEvent(It.IsAny()))
+ .Callback(args => errorMessages.Add(args.Message));
+
+ var uncompressedCandidate = new StaticWebAsset
+ {
+ Identity = Path.Combine(Environment.CurrentDirectory, "wwwroot", "js", "site.js"),
+ RelativePath = "js/site#[.{fingerprint}]?.js",
+ BasePath = "_content/Test",
+ AssetMode = StaticWebAsset.AssetModes.All,
+ AssetKind = StaticWebAsset.AssetKinds.All,
+ AssetMergeSource = string.Empty,
+ SourceId = "Test",
+ CopyToOutputDirectory = StaticWebAsset.AssetCopyOptions.Never,
+ Fingerprint = "xtxxf3hu2r",
+ RelatedAsset = string.Empty,
+ ContentRoot = Path.Combine(Environment.CurrentDirectory,"wwwroot"),
+ SourceType = StaticWebAsset.SourceTypes.Discovered,
+ Integrity = "hRQyftXiu1lLX2P9Ly9xa4gHJgLeR1uGN5qegUobtGo=",
+ AssetRole = StaticWebAsset.AssetRoles.Primary,
+ AssetMergeBehavior = string.Empty,
+ AssetTraitValue = string.Empty,
+ AssetTraitName = string.Empty,
+ OriginalItemSpec = Path.Combine("wwwroot", "js", "site.js"),
+ CopyToPublishDirectory = StaticWebAsset.AssetCopyOptions.PreserveNewest
+ };
+
+ var compressedCandidate = new StaticWebAsset
+ {
+ Identity = Path.Combine(Environment.CurrentDirectory, "wwwroot", "js", "site.js.gz"),
+ RelativePath = "js/site.js#[.{fingerprint}]?.gz",
+ BasePath = "_content/Test",
+ AssetMode = StaticWebAsset.AssetModes.All,
+ AssetKind = StaticWebAsset.AssetKinds.All,
+ AssetMergeSource = string.Empty,
+ SourceId = "Test",
+ CopyToOutputDirectory = StaticWebAsset.AssetCopyOptions.Never,
+ Fingerprint = "es13vhk42b",
+ RelatedAsset = string.Empty,
+ ContentRoot = Path.Combine(Environment.CurrentDirectory, "wwwroot"),
+ SourceType = StaticWebAsset.SourceTypes.Discovered,
+ Integrity = "zs5Fd3XI6+g9f4N1SFLVdgghuiqdvq+nETAjTbvVxx4=",
+ AssetRole = StaticWebAsset.AssetRoles.Primary,
+ AssetMergeBehavior = string.Empty,
+ AssetTraitValue = string.Empty,
+ AssetTraitName = string.Empty,
+ OriginalItemSpec = Path.Combine("wwwroot", "js", "site.js.gz"),
+ CopyToPublishDirectory = StaticWebAsset.AssetCopyOptions.PreserveNewest
+ };
+
+ var task = new ResolveCompressedAssets
+ {
+ OutputPath = OutputBasePath,
+ CandidateAssets = [uncompressedCandidate.ToTaskItem(), compressedCandidate.ToTaskItem()],
+ Formats = "gzip",
+ BuildEngine = buildEngine.Object
+ };
+
+ var result = task.Execute();
+
+ result.Should().BeTrue();
+ task.AssetsToCompress.Should().HaveCount(0);
+ }
+
[Fact]
public void ResolvesAssetsMatchingIncludePattern()
{
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.files.json
new file mode 100644
index 000000000000..817adc62eec6
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.files.json
@@ -0,0 +1,4 @@
+[
+ "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css"
+]
\ No newline at end of file
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.staticwebassets.json
new file mode 100644
index 000000000000..d228706df30c
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/Build_Detects_PrecompressedAssets.Build.staticwebassets.json
@@ -0,0 +1,1209 @@
+{
+ "Version": 1,
+ "Hash": "__hash__",
+ "Source": "AppWithP2PReference",
+ "BasePath": "_content/AppWithP2PReference",
+ "Mode": "Default",
+ "ManifestType": "Build",
+ "ReferencedProjectsConfiguration": [
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\ClassLibrary.csproj",
+ "Version": 2,
+ "Source": "ClassLibrary",
+ "GetPublishAssetsTargets": "ComputeReferencedStaticWebAssetsPublishManifest;GetCurrentProjectPublishStaticWebAssetItems",
+ "AdditionalPublishProperties": "",
+ "AdditionalPublishPropertiesToRemove": "WebPublishProfileFile;TargetFramework;RuntimeIdentifier;SelfContained",
+ "GetBuildAssetsTargets": "GetCurrentProjectBuildStaticWebAssetItems",
+ "AdditionalBuildProperties": "",
+ "AdditionalBuildPropertiesToRemove": "WebPublishProfileFile;TargetFramework;RuntimeIdentifier;SelfContained"
+ }
+ ],
+ "DiscoveryPatterns": [
+ {
+ "Name": "ClassLibrary\\wwwroot",
+ "Source": "ClassLibrary",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "Pattern": "**"
+ }
+ ],
+ "Assets": [
+ {
+ "Identity": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "SourceId": "AppWithP2PReference",
+ "SourceType": "Computed",
+ "ContentRoot": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/AppWithP2PReference",
+ "RelativePath": "AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "AssetKind": "All",
+ "AssetMode": "CurrentProject",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "SourceId": "AppWithP2PReference",
+ "SourceType": "Computed",
+ "ContentRoot": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\",
+ "BasePath": "_content/AppWithP2PReference",
+ "RelativePath": "AppWithP2PReference#[.{fingerprint}]?.styles.css",
+ "AssetKind": "All",
+ "AssetMode": "CurrentProject",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "ScopedCss",
+ "AssetTraitValue": "ApplicationBundle",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "AssetKind": "All",
+ "AssetMode": "Reference",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.v4.js.gz",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "ClassLibrary#[.{fingerprint}]!.bundle.scp.css",
+ "AssetKind": "All",
+ "AssetMode": "Reference",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "ScopedCss",
+ "AssetTraitValue": "ProjectBundle",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js.br",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "br",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js.gz",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "",
+ "AssetTraitValue": "",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.v4.js",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "",
+ "AssetTraitValue": "",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js"
+ }
+ ],
+ "Endpoints": [
+ {
+ "Route": "AppWithP2PReference.styles.css.gz",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css.gz",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css.gz"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css.gz"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js.br",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "br"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "br",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "br"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.files.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.files.json
new file mode 100644
index 000000000000..4658dfcbf916
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.files.json
@@ -0,0 +1,18 @@
+[
+ "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "${OutputPath}\\wwwroot\\AppWithP2PReference.styles.css",
+ "${OutputPath}\\wwwroot\\AppWithP2PReference.styles.css.br",
+ "${OutputPath}\\wwwroot\\AppWithP2PReference.styles.css.gz",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\ClassLibrary.__fingerprint__.bundle.scp.css",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\ClassLibrary.__fingerprint__.bundle.scp.css.br",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\ClassLibrary.__fingerprint__.bundle.scp.css.gz",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.js",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.br",
+ "${OutputPath}\\wwwroot\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "${OutputPath}\\wwwroot\\js\\project-transitive-dep.js.br",
+ "${OutputPath}\\wwwroot\\js\\project-transitive-dep.js.gz"
+]
\ No newline at end of file
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.staticwebassets.json b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.staticwebassets.json
new file mode 100644
index 000000000000..d228706df30c
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsBaselines/PublishWorks_With_PrecompressedAssets.Build.staticwebassets.json
@@ -0,0 +1,1209 @@
+{
+ "Version": 1,
+ "Hash": "__hash__",
+ "Source": "AppWithP2PReference",
+ "BasePath": "_content/AppWithP2PReference",
+ "Mode": "Default",
+ "ManifestType": "Build",
+ "ReferencedProjectsConfiguration": [
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\ClassLibrary.csproj",
+ "Version": 2,
+ "Source": "ClassLibrary",
+ "GetPublishAssetsTargets": "ComputeReferencedStaticWebAssetsPublishManifest;GetCurrentProjectPublishStaticWebAssetItems",
+ "AdditionalPublishProperties": "",
+ "AdditionalPublishPropertiesToRemove": "WebPublishProfileFile;TargetFramework;RuntimeIdentifier;SelfContained",
+ "GetBuildAssetsTargets": "GetCurrentProjectBuildStaticWebAssetItems",
+ "AdditionalBuildProperties": "",
+ "AdditionalBuildPropertiesToRemove": "WebPublishProfileFile;TargetFramework;RuntimeIdentifier;SelfContained"
+ }
+ ],
+ "DiscoveryPatterns": [
+ {
+ "Name": "ClassLibrary\\wwwroot",
+ "Source": "ClassLibrary",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "Pattern": "**"
+ }
+ ],
+ "Assets": [
+ {
+ "Identity": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "SourceId": "AppWithP2PReference",
+ "SourceType": "Computed",
+ "ContentRoot": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/AppWithP2PReference",
+ "RelativePath": "AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "AssetKind": "All",
+ "AssetMode": "CurrentProject",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "SourceId": "AppWithP2PReference",
+ "SourceType": "Computed",
+ "ContentRoot": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\",
+ "BasePath": "_content/AppWithP2PReference",
+ "RelativePath": "AppWithP2PReference#[.{fingerprint}]?.styles.css",
+ "AssetKind": "All",
+ "AssetMode": "CurrentProject",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "ScopedCss",
+ "AssetTraitValue": "ApplicationBundle",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "AssetKind": "All",
+ "AssetMode": "Reference",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.v4.js.gz",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "ClassLibrary#[.{fingerprint}]!.bundle.scp.css",
+ "AssetKind": "All",
+ "AssetMode": "Reference",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "ScopedCss",
+ "AssetTraitValue": "ProjectBundle",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js.br",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "br",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js.gz",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Alternative",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "AssetTraitName": "Content-Encoding",
+ "AssetTraitValue": "gzip",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.js",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "",
+ "AssetTraitValue": "",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js"
+ },
+ {
+ "Identity": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "SourceId": "ClassLibrary",
+ "SourceType": "Project",
+ "ContentRoot": "${ProjectPath}\\ClassLibrary\\wwwroot\\",
+ "BasePath": "_content/ClassLibrary",
+ "RelativePath": "js/project-transitive-dep.v4.js",
+ "AssetKind": "All",
+ "AssetMode": "All",
+ "AssetRole": "Primary",
+ "AssetMergeBehavior": "",
+ "AssetMergeSource": "",
+ "RelatedAsset": "",
+ "AssetTraitName": "",
+ "AssetTraitValue": "",
+ "Fingerprint": "__fingerprint__",
+ "Integrity": "__integrity__",
+ "CopyToOutputDirectory": "Never",
+ "CopyToPublishDirectory": "PreserveNewest",
+ "OriginalItemSpec": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js"
+ }
+ ],
+ "Endpoints": [
+ {
+ "Route": "AppWithP2PReference.styles.css.gz",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css.gz",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css.gz"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\compressed\\_content\\AppWithP2PReference\\AppWithP2PReference#[.{fingerprint=__fingerprint__}]?.styles.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "AppWithP2PReference.__fingerprint__.styles.css",
+ "AssetFile": "${ProjectPath}\\AppWithP2PReference\\obj\\Debug\\${Tfm}\\scopedcss\\bundle\\AppWithP2PReference.styles.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Link",
+ "Value": "\u003C_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css\u003E; rel=\u0022preload\u0022; as=\u0022style\u0022"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "AppWithP2PReference.styles.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css.gz"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\ClassLibrary#[.{fingerprint=__fingerprint__}]!.bundle.scp.css.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\compressed\\_content\\ClassLibrary\\js\\project-transitive-dep.v4.js.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/ClassLibrary.__fingerprint__.bundle.scp.css",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\obj\\Debug\\${Tfm}\\scopedcss\\projectbundle\\ClassLibrary.bundle.scp.css",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "max-age=31536000, immutable"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/css"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "fingerprint",
+ "Value": "__fingerprint__"
+ },
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ },
+ {
+ "Name": "label",
+ "Value": "_content/ClassLibrary/ClassLibrary.bundle.scp.css"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js.br",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "br"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.br",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "br",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "br"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js.gz",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\_content\\ClassLibrary\\js\\project-transitive-dep.js.gz",
+ "Selectors": [
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip",
+ "Quality": "__quality__"
+ }
+ ],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Encoding",
+ "Value": "gzip"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ },
+ {
+ "Name": "Vary",
+ "Value": "Content-Encoding"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.js",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ },
+ {
+ "Route": "_content/ClassLibrary/js/project-transitive-dep.v4.js",
+ "AssetFile": "${ProjectPath}\\ClassLibrary\\wwwroot\\js\\project-transitive-dep.v4.js",
+ "Selectors": [],
+ "ResponseHeaders": [
+ {
+ "Name": "Accept-Ranges",
+ "Value": "bytes"
+ },
+ {
+ "Name": "Cache-Control",
+ "Value": "no-cache"
+ },
+ {
+ "Name": "Content-Length",
+ "Value": "__content-length__"
+ },
+ {
+ "Name": "Content-Type",
+ "Value": "text/javascript"
+ },
+ {
+ "Name": "ETag",
+ "Value": "__etag__"
+ },
+ {
+ "Name": "Last-Modified",
+ "Value": "__last-modified__"
+ }
+ ],
+ "EndpointProperties": [
+ {
+ "Name": "integrity",
+ "Value": "__integrity__"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsCompressionIntegrationTest.cs b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsCompressionIntegrationTest.cs
new file mode 100644
index 000000000000..94de9a5784dc
--- /dev/null
+++ b/test/Microsoft.NET.Sdk.Razor.Tests/StaticWebAssetsCompressionIntegrationTest.cs
@@ -0,0 +1,187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.IO.Compression;
+using System.Net.Http.Headers;
+using Microsoft.AspNetCore.StaticWebAssets.Tasks;
+
+namespace Microsoft.NET.Sdk.Razor.Tests
+{
+ public class StaticWebAssetsCompressionIntegrationTest : AspNetSdkBaselineTest
+ {
+ public StaticWebAssetsCompressionIntegrationTest(ITestOutputHelper log) : base(log, GenerateBaselines) { }
+
+ [Fact]
+ public void Build_Detects_PrecompressedAssets()
+ {
+ var expectedManifest = LoadBuildManifest();
+ var testAsset = "RazorAppWithP2PReference";
+ ProjectDirectory = CreateAspNetSdkTestAsset(testAsset);
+
+ var file = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js");
+ var gzipFile = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js.gz");
+ var brotliFile = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js.br");
+
+ // Compress file into gzip and brotli
+ using (var gzipStream = new GZipStream(File.Create(gzipFile), CompressionLevel.NoCompression))
+ {
+ using var stream = File.OpenRead(file);
+ stream.CopyTo(gzipStream);
+ }
+
+ using (var brotliStream = new BrotliStream(File.Create(brotliFile), CompressionLevel.NoCompression))
+ {
+ using var stream = File.OpenRead(file);
+ stream.CopyTo(brotliStream);
+ }
+
+ var build = CreateBuildCommand(ProjectDirectory, "AppWithP2PReference");
+ ExecuteCommand(build).Should().Pass();
+
+ var intermediateOutputPath = build.GetIntermediateDirectory(DefaultTfm, "Debug").ToString();
+ var outputPath = build.GetOutputDirectory(DefaultTfm, "Debug").ToString();
+
+ // GenerateStaticWebAssetsManifest should generate the manifest file.
+ var path = Path.Combine(intermediateOutputPath, "staticwebassets.build.json");
+ new FileInfo(path).Should().Exist();
+ var manifest = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(path));
+ AssertManifest(manifest, expectedManifest);
+
+ // GenerateStaticWebAssetsManifest should copy the file to the output folder.
+ var finalPath = Path.Combine(outputPath, "AppWithP2PReference.staticwebassets.runtime.json");
+ new FileInfo(finalPath).Should().Exist();
+
+ var manifest1 = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(Path.Combine(intermediateOutputPath, "staticwebassets.build.json")));
+ AssertManifest(manifest1, expectedManifest);
+ AssertBuildAssets(manifest1, outputPath, intermediateOutputPath);
+
+ var manifest2 = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(Path.Combine(intermediateOutputPath, "staticwebassets.build.json")));
+
+ var standardEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, file, StringComparison.Ordinal)).ToArray();
+ var gzipEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, gzipFile, StringComparison.Ordinal)).ToArray();
+ var brotliEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, brotliFile, StringComparison.Ordinal)).ToArray();
+
+ var gzipAsset = manifest2.Assets.Single(a => string.Equals(a.Identity, gzipFile, StringComparison.Ordinal));
+ var brotliAsset = manifest2.Assets.Single(a => string.Equals(a.Identity, brotliFile, StringComparison.Ordinal));
+
+ standardEndpoints.Should().HaveCount(1);
+ gzipEndpoints.Should().HaveCount(2);
+ brotliEndpoints.Should().HaveCount(2);
+
+ var expectedWeakEndpointEtag = new EntityTagHeaderValue(
+ EntityTagHeaderValue.Parse(standardEndpoints.First().ResponseHeaders.Single(h => h.Name == "ETag").Value).Tag,
+ isWeak: true);
+
+ foreach (var endpoint in gzipEndpoints)
+ {
+ endpoint.ResponseHeaders.Where(e => e.Name == "Content-Encoding").Select(e => e.Value).Single().Should().Be("gzip");
+
+ var etags = endpoint.ResponseHeaders.Where(e => e.Name == "ETag").Select(e => EntityTagHeaderValue.Parse(e.Value));
+ etags.Where(e=> !e.IsWeak).Select(e => e.Tag).Single().Should().BeEquivalentTo($"\"{gzipAsset.Integrity}\"");
+ if (endpoint.Route.EndsWith(".gz"))
+ {
+ continue;
+ }
+ etags.Should().Contain(expectedWeakEndpointEtag);
+ }
+
+ foreach (var endpoint in brotliEndpoints)
+ {
+ endpoint.ResponseHeaders.Where(e => e.Name == "Content-Encoding").Select(e => e.Value).Single().Should().Be("br");
+
+ var etags = endpoint.ResponseHeaders.Where(e => e.Name == "ETag").Select(e => EntityTagHeaderValue.Parse(e.Value));
+ etags.Where(e => !e.IsWeak).Select(e => e.Tag).Single().Should().BeEquivalentTo($"\"{brotliAsset.Integrity}\"");
+ if (endpoint.Route.EndsWith(".br"))
+ {
+ continue;
+ }
+ etags.Should().Contain(expectedWeakEndpointEtag);
+ }
+ }
+
+ [Fact]
+ public void PublishWorks_With_PrecompressedAssets()
+ {
+ var expectedManifest = LoadBuildManifest();
+ var testAsset = "RazorAppWithP2PReference";
+ ProjectDirectory = CreateAspNetSdkTestAsset(testAsset);
+
+ var file = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js");
+ var gzipFile = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js.gz");
+ var brotliFile = Path.Combine(ProjectDirectory.Path, "ClassLibrary", "wwwroot", "js", "project-transitive-dep.js.br");
+
+ // Compress file into gzip and brotli
+ using (var gzipStream = new GZipStream(File.Create(gzipFile), CompressionLevel.NoCompression))
+ {
+ using var stream = File.OpenRead(file);
+ stream.CopyTo(gzipStream);
+ }
+
+ using (var brotliStream = new BrotliStream(File.Create(brotliFile), CompressionLevel.NoCompression))
+ {
+ using var stream = File.OpenRead(file);
+ stream.CopyTo(brotliStream);
+ }
+
+ var build = CreatePublishCommand(ProjectDirectory, "AppWithP2PReference");
+ ExecuteCommand(build).Should().Pass();
+
+ var intermediateOutputPath = build.GetIntermediateDirectory(DefaultTfm, "Debug").ToString();
+ var outputPath = build.GetOutputDirectory(DefaultTfm, "Debug").ToString();
+
+ // GenerateStaticWebAssetsManifest should generate the manifest file.
+ var path = Path.Combine(intermediateOutputPath, "staticwebassets.build.json");
+ new FileInfo(path).Should().Exist();
+ var manifest = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(path));
+ AssertManifest(manifest, expectedManifest);
+
+
+ var manifest1 = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(Path.Combine(intermediateOutputPath, "staticwebassets.build.json")));
+ AssertManifest(manifest1, expectedManifest);
+ AssertBuildAssets(manifest1, outputPath, intermediateOutputPath);
+
+ var manifest2 = StaticWebAssetsManifest.FromJsonBytes(File.ReadAllBytes(Path.Combine(intermediateOutputPath, "staticwebassets.publish.json")));
+
+ var standardEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, file, StringComparison.Ordinal)).ToArray();
+ var gzipEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, gzipFile, StringComparison.Ordinal)).ToArray();
+ var brotliEndpoints = manifest2.Endpoints.Where(e => string.Equals(e.AssetFile, brotliFile, StringComparison.Ordinal)).ToArray();
+
+ var gzipAsset = manifest2.Assets.Single(a => string.Equals(a.Identity, gzipFile, StringComparison.Ordinal));
+ var brotliAsset = manifest2.Assets.Single(a => string.Equals(a.Identity, brotliFile, StringComparison.Ordinal));
+
+ standardEndpoints.Should().HaveCount(1);
+ gzipEndpoints.Should().HaveCount(2);
+ brotliEndpoints.Should().HaveCount(2);
+
+ var expectedWeakEndpointEtag = new EntityTagHeaderValue(
+ EntityTagHeaderValue.Parse(standardEndpoints.First().ResponseHeaders.Single(h => h.Name == "ETag").Value).Tag,
+ isWeak: true);
+
+ foreach (var endpoint in gzipEndpoints)
+ {
+ endpoint.ResponseHeaders.Where(e => e.Name == "Content-Encoding").Select(e => e.Value).Single().Should().Be("gzip");
+
+ var etags = endpoint.ResponseHeaders.Where(e => e.Name == "ETag").Select(e => EntityTagHeaderValue.Parse(e.Value));
+ etags.Where(e => !e.IsWeak).Select(e => e.Tag).Single().Should().BeEquivalentTo($"\"{gzipAsset.Integrity}\"");
+ if (endpoint.Route.EndsWith(".gz"))
+ {
+ continue;
+ }
+ etags.Should().Contain(expectedWeakEndpointEtag);
+ }
+
+ foreach (var endpoint in brotliEndpoints)
+ {
+ endpoint.ResponseHeaders.Where(e => e.Name == "Content-Encoding").Select(e => e.Value).Single().Should().Be("br");
+
+ var etags = endpoint.ResponseHeaders.Where(e => e.Name == "ETag").Select(e => EntityTagHeaderValue.Parse(e.Value));
+ etags.Where(e => !e.IsWeak).Select(e => e.Tag).Single().Should().BeEquivalentTo($"\"{brotliAsset.Integrity}\"");
+ if (endpoint.Route.EndsWith(".br"))
+ {
+ continue;
+ }
+ etags.Should().Contain(expectedWeakEndpointEtag);
+ }
+ }
+ }
+}