Skip to content

Add Asset Groups support for static web assets#53187

Merged
javiercn merged 20 commits into
mainfrom
javiercn/asset-groups
Mar 28, 2026
Merged

Add Asset Groups support for static web assets#53187
javiercn merged 20 commits into
mainfrom
javiercn/asset-groups

Conversation

@javiercn
Copy link
Copy Markdown
Member

@javiercn javiercn commented Feb 27, 2026

  • Investigate all PR comments
  • Fix StaticWebAssetPathPattern.cs line 135: Change IsPreferred = true to IsPreferred = false for pack-only tokens and update ReplaceTokens skip logic (comment 2987371603)
  • Fix DefineStaticWebAssets.cs: Remove redundant null-check for includeMatcher since IncludePattern is already validated (comment 2947602098)
  • Validate required group definition properties throw are enforced in ParseGroupDefinitions (comment 2947579304 - already addressed by existing validation)
  • Run tests to validate changes - 108 tests pass

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Comment thread src/StaticWebAssetsSdk/Tasks/Data/StaticWebAssetPackageManifest.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/Data/StaticWebAssetTokenResolver.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/Utils/StaticWebAssetGroupFilter.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/Utils/StaticWebAssetGroupFilter.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/Utils/StaticWebAssetGroupFilter.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/GeneratePackageAssetsManifestFile.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/GenerateStaticWebAssetsPropsFile.cs
Comment thread src/StaticWebAssetsSdk/Tasks/GenerateStaticWebAssetsPropsFile.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs Outdated
Comment thread src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Pack.targets Outdated
Comment thread src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets.Pack.targets Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs
Comment thread src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetGroups.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetGroups.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/GenerateStaticWebAssetsPropsFile.cs
Comment thread src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs
Comment thread src/StaticWebAssetsSdk/Tasks/Data/StaticWebAsset.cs
Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs
Comment thread src/StaticWebAssetsSdk/Tasks/ComputeReferenceStaticWebAssetItems.cs
Comment thread src/StaticWebAssetsSdk/Tasks/ComputeStaticWebAssetsTargetPaths.cs
Comment thread src/StaticWebAssetsSdk/Tasks/UpdatePackageStaticWebAssets.cs
@javiercn javiercn force-pushed the javiercn/asset-groups branch from af7dca6 to 0d2f054 Compare March 13, 2026 11:37
Comment thread src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetGroups.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/GeneratePackageAssetsManifestFile.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/GenerateStaticWebAssetsPropsFile.cs
Comment thread src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/UpdateExternallyDefinedStaticWebAssets.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/UpdateExternallyDefinedStaticWebAssets.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/UpdatePackageStaticWebAssets.cs
@javiercn javiercn force-pushed the javiercn/asset-groups branch from 5b4128e to dcd7410 Compare March 17, 2026 14:14
@javiercn javiercn marked this pull request as ready for review March 17, 2026 14:14
@javiercn javiercn requested review from a team as code owners March 17, 2026 14:14
Copilot AI review requested due to automatic review settings March 17, 2026 14:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces Static Web Asset Groups support to the Static Web Assets pipeline, enabling libraries to ship multiple asset variants (e.g., Bootstrap V4/V5) and allowing consuming projects to declaratively select which variant is used. It also adds a new JSON-manifest + lightweight .targets packaging path (for newer TFMs) and integrates group-based filtering into build/publish endpoint generation.

Changes:

  • Add group tagging/filtering support across project, package, and P2P static web assets (including deferred group support and cascading exclusion of related assets/endpoints).
  • Introduce JSON package manifest generation + consumption and generate lightweight .targets files to reference the manifest.
  • Add new unit + integration tests and update existing baselines to reflect new manifest/path behavior.

Reviewed changes

Copilot reviewed 80 out of 80 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs Adds group definition parsing and applies group tagging + path/content-root rewriting during asset definition.
src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetGroups.cs New task to filter assets/endpoints by group declarations, supporting deferred groups.
src/StaticWebAssetsSdk/Tasks/ReadPackageAssetsManifest.cs New task to read JSON package manifests, apply group filtering, and materialize framework assets.
src/StaticWebAssetsSdk/Tasks/GeneratePackageAssetsManifestFile.cs New task to emit JSON package manifest (assets + endpoints) with remapped asset references.
src/StaticWebAssetsSdk/Tasks/GeneratePackageAssetsTargetsFile.cs New task to generate lightweight .targets that points to the JSON manifest.
src/StaticWebAssetsSdk/Targets/Microsoft.NET.Sdk.StaticWebAssets*.targets Wires group filtering into build/publish and adds JSON packaging + restore-time manifest reading.
src/StaticWebAssetsSdk/Tasks/UpdateExternallyDefinedStaticWebAssets.cs Applies group filtering at the P2P boundary with SkipDeferred=true and filters endpoints accordingly.
src/StaticWebAssetsSdk/Tasks/Data/StaticWebAssetPathPattern.cs / StaticWebAssetPathSegment.cs Adds ~ file-only token modifier to hide segments from endpoint routes while keeping file resolution.
test/Microsoft.NET.Sdk.StaticWebAssets.Tests/* Adds unit + integration coverage for group filtering, deferred groups, and JSON packaging; updates baselines.
test/TestAssets/TestProjects/AssetGroupsSample/* Adds sample producer/consumer projects and convention targets file for groups.
test/TestAssets/TestProjects/...AppWithPackageAndP2PReference.csproj Updates test target ordering to ensure package-manifest reading happens before checks.
src/BlazorWasmSdk/Tasks/Microsoft.NET.Sdk.BlazorWebAssembly.Tasks.csproj Updates linked StaticWebAssets task data files list (includes group data + OSPath).

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +6 to +37
using System.Xml;
using Microsoft.AspNetCore.StaticWebAssets.Tasks.Utils;
using Microsoft.Build.Framework;

namespace Microsoft.AspNetCore.StaticWebAssets.Tasks;

// Generates a lightweight .targets file that adds a single StaticWebAssetPackageManifest
// item pointing to the JSON manifest file. This replaces the heavyweight XML .props files
// that contained all asset/endpoint data as MSBuild items.
public class GeneratePackageAssetsTargetsFile : Task
{
[Required]
public string PackageId { get; set; }

[Required]
public string TargetFilePath { get; set; }

public string PackagePathPrefix { get; set; } = "staticwebassets";

[Required]
public string ManifestFileName { get; set; }

public override bool Execute()
{
var normalizedPrefix = PackagePathPrefix.Replace("/", "\\").TrimStart('\\');

var itemGroup = new XElement("ItemGroup");
var manifestItem = new XElement("StaticWebAssetPackageManifest",
new XAttribute("Include", $@"$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory){ManifestFileName}'))"),
new XElement("SourceId", PackageId),
new XElement("ContentRoot", $@"$(MSBuildThisFileDirectory)..\{normalizedPrefix}\"),
new XElement("PackageRoot", @"$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..'))"));
Comment on lines +17 to +27
[Required]
public ITaskItem[] PackageManifests { get; set; }

public ITaskItem[] StaticWebAssetGroups { get; set; }

public string IntermediateOutputPath { get; set; }

public string ProjectPackageId { get; set; }

public string ProjectBasePath { get; set; }

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Make them required

Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs
Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs
Comment on lines +171 to +172
}
manifestEndpoints.Add(endpoint);
Comment on lines +659 to +663
public string Name { get; }
public string Value { get; }
public string SourceId { get; }
public int Order { get; }
public StaticWebAssetGlobMatcher IncludeMatcher { get; }
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are required, we should throw if not provided

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The required field validation (Value, SourceId, Order, IncludePattern) is enforced in ParseGroupDefinitions via Log.LogError + return null — the idiomatic MSBuild pattern for fatal validation errors. The struct is private and only constructed from that one validation site, so constructor-level guards would be redundant and would also conflict with CA1510 (which requires using ThrowIfNull instead of explicit throws on multi-target projects). The existing validation in ParseGroupDefinitions is the appropriate place.

Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs Outdated
Comment thread src/StaticWebAssetsSdk/Tasks/DefineStaticWebAssets.cs Outdated
javiercn and others added 18 commits March 28, 2026 16:10
Unit tests covering:
- AssetGroupFilteringTest: end-to-end group filtering scenarios
- FilterStaticWebAssetGroupsTest: two-pass filtering logic (SkipDeferred)
- GeneratePackageAssetsManifestFileTest: JSON manifest serialization
- GeneratePackageAssetsTargetsFileTest: lightweight .targets generation
- ReadPackageAssetsManifestTest: manifest deserialization and group filtering
- ResolveCompressedAssetsTest: compression with asset groups
- StaticWebAssetTest: AssetGroups property and related asset sorting
Integration tests:
- AssetGroupsIntegrationTest: build/publish with asset group selection,
  verifies correct assets appear in output based on selected group
- DeferredAssetGroupsIntegrationTest: deferred group resolution during
  restore and P2P reference scenarios
- FrameworkAssetsIntegrationTest: framework asset materialization from
  JSON manifests with group filtering
- StaticWebAssetsPackIntegrationTest: pack produces JSON manifest with
  correct asset group metadata and .targets entry point

Regenerate 32 baseline files to incorporate AssetGroups metadata and
new JSON manifest packaging output.
Move ParseGroupDefinitions() call from ApplyGroupDefinitions() to the
beginning of Execute(). The parsed definitions list is now a local
variable passed into ApplyGroupDefinitions(definitions) rather than
re-parsed on every call. Validation errors (duplicate Order+SourceId)
are caught before any asset processing begins.
Replace the post-loop ApplyGroupDefinitions() bulk operation with a
per-asset ApplyGroupToAsset() call inside the main processing loop.
Group definitions are now applied to each StaticWebAsset instance
before it is serialized via ToTaskItem(), eliminating the need to
re-parse ITaskItem back to StaticWebAsset after the fact.

This means group-modified RelativePath and ContentRoot values are
visible to UpdateAssetKindIfNecessary for dedup/conflict detection.
Group definitions can rewrite RelativePath so that assets from
different groups (e.g. V4/css/site.css and V5/css/site.css) collapse
to the same post-group path (css/site.css). UpdateAssetKindIfNecessary
must use the original pre-group path for its conflict detection, since
group variants are not true conflicts — they are resolved at runtime
by FilterStaticWebAssetGroups.
Introduce TokenResolveMode (None/Pack/Serve) to control how token
expressions are resolved during path computation. The ~ modifier
now means 'pack-only' — the segment appears in physical NuGet
package paths (Pack mode) but is stripped from HTTP routes and
dev manifests (Serve mode).

- Rename IsFileOnly to IsPackOnly on StaticWebAssetPathSegment
- Rename PatternFileOnly to PatternPackOnly
- Replace bool applyPreferences with TokenResolveMode resolveMode
  on StaticWebAssetPathPattern.ReplaceTokens()
- Add resolveMode parameter to ComputeTargetPath and ReplaceTokens
  on StaticWebAsset, defaulting to Serve
- Update all pack call sites to use TokenResolveMode.Pack:
  GenerateStaticWebAssetsPropsFile, GenerateStaticWebAssetEndpointsPropsFile,
  GeneratePackageAssetsManifestFile
When multiple group definitions with different names (e.g., version and
theme) match the same asset, their ContentRootSuffix values now compose
sequentially instead of erroring. Definitions are sorted by Order so
composition is deterministic. For example, version=v4 (suffix 'v4') +
theme=light (suffix 'light') produces 'OriginalRoot/v4/light'.

Updated test to verify composition behavior.
ComputeStaticWebAssetsTargetPaths was using TokenResolveMode.Serve
(the default) when computing pack target paths, which strips
pack-only (~) segments from relative paths. This caused group
token expressions like #[{BootstrapVersion}]~/ to be stripped,
resulting in nupkg entries like staticwebassets//css/site.css
instead of staticwebassets/V4/css/site.css.

Use TokenResolveMode.Pack when AdjustPathsForPack is true so
pack-only segments are resolved rather than stripped.
…deMatcher null-check

Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/sdk/sessions/c0028270-f89a-4a4f-b579-24b447712cd4
@javiercn javiercn force-pushed the javiercn/asset-groups branch from 3aef97f to 876614f Compare March 28, 2026 15:10
@javiercn javiercn merged commit 6c36567 into main Mar 28, 2026
24 checks passed
@javiercn javiercn deleted the javiercn/asset-groups branch March 28, 2026 18:20
javiercn added a commit to dotnet/aspnetcore that referenced this pull request Apr 21, 2026
Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove BlazorWebAssemblyJSPath (no longer needed with framework assets)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets import (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets

Validated: 89 E2E + functional tests pass (0 failures)
javiercn added a commit to dotnet/aspnetcore that referenced this pull request Apr 21, 2026
….WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)
- blazor.webassembly.js flows to Blazor Web Apps through client P2P reference chain

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets import (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets
javiercn added a commit to dotnet/aspnetcore that referenced this pull request Apr 21, 2026
….WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Add StaticWebAssetGroupDefinition + StaticWebAssets.Groups.targets
  (group keyed on UsingMicrosoftNETSdkBlazorWebAssembly)
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets imports (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets
javiercn added a commit to dotnet/aspnetcore that referenced this pull request Apr 21, 2026
….WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Add StaticWebAssetGroupDefinition + StaticWebAssets.Groups.targets
  (group keyed on UsingMicrosoftNETSdkBlazorWebAssembly)
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets imports (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets
javiercn added a commit to dotnet/aspnetcore that referenced this pull request May 18, 2026
….WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Add StaticWebAssetGroupDefinition + StaticWebAssets.Groups.targets
  (group keyed on UsingMicrosoftNETSdkBlazorWebAssembly)
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets imports (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets
javiercn added a commit to dotnet/aspnetcore that referenced this pull request May 28, 2026
….WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Add StaticWebAssetGroupDefinition + StaticWebAssets.Groups.targets
  (group keyed on UsingMicrosoftNETSdkBlazorWebAssembly)
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets imports (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets
javiercn added a commit to dotnet/aspnetcore that referenced this pull request Jun 1, 2026
…6412)

* Use SDK Asset Groups for Assets.Internal, Identity UI, and Components.WebAssembly

Replace custom build/props/targets packaging with SDK StaticWebAssetGroupDefinition
and StaticWebAssetGroup items (dotnet/sdk#53187).

Assets.Internal changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata instead of custom _BlazorJSFile
- Add StaticWebAssets.Groups.targets for consumer-side conditional inclusion
- Remove blazor.webassembly.js (now provided by Components.WebAssembly)
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Components.WebAssembly changes:
- Switch to Microsoft.NET.Sdk.Razor SDK
- Add StaticWebAssetFrameworkPattern=**/*.js for framework asset marking
- Use Content items with Link/ContentRoot metadata for blazor.webassembly.js
- Add StaticWebAssetGroupDefinition + StaticWebAssets.Groups.targets
  (group keyed on UsingMicrosoftNETSdkBlazorWebAssembly)
- Remove BlazorWebAssemblyJSPath from package props (SWA pipeline handles it)

Identity UI changes:
- Replace custom GetIdentityUIAssets target with StaticWebAssetGroupDefinition
  for Bootstrap V4/V5 variants
- Add StaticWebAssets.Groups.targets for consumer-side group selection
- Delete old build/, buildMultiTargeting/, buildTransitive/ directories

Consumer migration:
- Components/Directory.Build.props: ProjectReference with PrivateAssets=All
  + Groups.targets imports (replaces workaround properties)
- Components/Directory.Build.targets: Remove BlazorWebAssemblyJSPath override
- Identity samples/testassets: Import Groups.targets, remove old targets

* Fix build: move Assets.Internal ref to targets, add RelativePathPrefix for Identity UI pack

* Move Assets.Internal ProjectReference metadata to evaluation time

The _ConfigureAssetsInternalReference target set ReferenceOutputAssembly=false
during target execution (BeforeTargets=ResolveProjectReferences), but the E2E
test pipeline invokes Components.TestServer and Wasm.Prerendered.Server with
Targets='Build;Publish' and custom Properties, creating separate MSBuild project
instances where the target-based approach didn't reliably prevent the compiler
from trying to reference the non-existent Assets.Internal DLL.

By setting the metadata via ProjectReference Update at evaluation time (outside
any target), the metadata is always in effect regardless of which targets run or
how many times the project is built with different global properties.

* Add BlazorWebAssembly asset group workaround to test/sample server projects

The BlazorWebAssembly group on blazor.webassembly.js should be cleared by
the SDK when the asset crosses project boundaries as a framework asset.
Until that SDK change is in place, declare the group in each hosting
server project so the asset passes filtering.

Simplify Assets.Internal groups to only declare BlazorFramework.
Restore WebAssembly groups to final form (BlazorWebAssembly SDK only).

* Fix BlazorFramework group condition to match original asset filtering

The original _AddBlazorFrameworkStaticWebAssets target required both
OutputType == Exe/WinExe AND UsingMicrosoftNETSdkWeb. The group
condition must match: only executable web apps should opt into the
BlazorFramework group for blazor.web.js and blazor.server.js.

* Move _framework from BasePath to RelativePath for asset groups

Change JS build output to include _framework/ in the directory structure
so that it becomes part of RelativePath rather than BasePath. This ensures
the _framework prefix survives framework asset materialization regardless
of the consumer's BasePath.

Changes:
- Rollup config outputs to dist/Debug/_framework/blazor.*.js
- Assets.Internal and WebAssembly csprojs: BasePath=/ with _framework in paths
- Remove StaticWebAssetGroup workarounds from test/sample projects (no longer
  needed since the SDK properly filters by group before materialization)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>

* Preserve IdentityDefaultUIFramework property name for backward compat

The StaticWebAssets.Groups.targets now falls back to the existing
IdentityDefaultUIFramework property if IdentityUIFrameworkVersion is
not explicitly set, so consuming projects don't need to rename their
property.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update SDK to preview.6, fix NU1510 pruning error, fix stale comment

- Update global.json to 11.0.100-preview.6.26277.116
- Remove redundant Microsoft.Extensions.Options reference in Validation
  Localization tests (NU1510 warns-as-error with new SDK pruning)
- Fix stale comment in Components Directory.Build.targets about which
  package provides blazor.webassembly.js

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants