Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Blazor] libman libraries not included in first build #680

Open
javiercn opened this issue May 2, 2022 · 5 comments
Open

[Blazor] libman libraries not included in first build #680

javiercn opened this issue May 2, 2022 · 5 comments

Comments

@javiercn
Copy link
Member

javiercn commented May 2, 2022


Issue moved from dotnet/maui#6709


From @campersau on Saturday, April 30, 2022 6:31:24 PM

Description

Adding some client javascript libraries via libman does not include them in the first build.
When comparing the binlog with a blazor wasm build I can see that there is a _IncludePrePublishGeneratedContent target which is not present in the blazor maui build and thus any files which are generated under the wwwroot folder during the build are missing.

Here are the binlogs:
blazorbinlogs.zip

I only tested windows.

Steps to Reproduce

  1. New Blazor Maui App
  2. Add <PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.161" PrivateAssets="all" /> to the csproj
  3. Add libman.json with the following content:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "library": "twitter-bootstrap@5.1.3",
      "files": [
        "css/bootstrap.min.css"
      ],
      "destination": "wwwroot/libs/bootstrap"
    }
  ]
}
  1. Update index.html and reference <link rel="stylesheet" href="libs/bootstrap/css/bootstrap.min.css" /> instead.
  2. Remove the wwwroot/libs folder and do a new build / run. This will add the libs folder back but the app does include the CSS file. If you run the app again without removing the wwwroot/libs folder the CSS is included correctly.

It would be great if the libman library files were included directly in the first build.

Alternatively you can clone https://github.com/campersau/blazor-maui-libmanbug and do step 5.

Version with bug

Release Candidate 2 (current)

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

net6.0-windows10.0.19041.0

Did you find any workaround?

Building the project a second time works correctly as the libraries are already restored.

Or copy the msbuild target from https://github.com/dotnet/sdk/blob/c53c8ac81e1bcb8118c31bc4f5622396c72e9959/src/WebSdk/Publish/Targets/ComputeTargets/Microsoft.NET.Sdk.Publish.ComputeFiles.targets#L48-L60 into the csproj.

<Target Name="_IncludePrePublishGeneratedContent" BeforeTargets="GetCopyToPublishDirectoryItems" Condition=" '$(EnableDefaultItems)' == 'true' And '$(EnableDefaultContentItems)' == 'true' ">
    <ItemGroup>
        <!-- First, clean up previously generated content that may have been removed. -->
        <ContentWithTargetPath Remove="@(ContentWithTargetPath)" Condition="!Exists('%(Identity)')" />
        <!-- Next, include any newly generated content. -->
        <_WebProjectGeneratedContent Include="wwwroot\**" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);@(_ContentIncludedByDefault)" />
        <ContentWithTargetPath Include="@(_WebProjectGeneratedContent)" TargetPath="%(Identity)" CopyToPublishDirectory="PreserveNewest" />
    </ItemGroup>
</Target>

Relevant log output

No response

@jimmylewis
Copy link
Contributor

@javiercn this is not an issue limited to libman. The issue is that MAUI does not refresh items in wwwroot that were generated during the build (libman is one tool for generating those files). Any other task that writes a file to wwwroot should have the same problem - the file will not be included in publish from a clean build. In subsequent builds, the default glob would include the file as it would then be present on disk.

As shown by the workaround, the WebSdk addresses this by refreshing the wwwroot\** glob in the quoted target. Does MAUI have an equivalent target?

(I can't transfer this back nor reactivate/comment on dotnet/maui#6709 as I'm not a collaborator on that project.)

@jimmylewis
Copy link
Contributor

Alternatively, is there another ItemGroup we could add these items to? In the legacy (WAP/WSP, i.e. pre-dotnet sdk) web publish pipeline, we add the files to @(FilesForPackagingFromProject). We could do something similar if MAUI has an item group intended for extension in this manner.

(But if there's already a default glob for wwwroot, as indicated in dotnet/maui#4537, then it seems simpler to just refresh that.)

@javiercn
Copy link
Member Author

javiercn commented May 3, 2022

@javiercn this is not an issue limited to libman. The issue is that MAUI does not refresh items in wwwroot that were generated during the build (libman is one tool for generating those files). Any other task that writes a file to wwwroot should have the same problem - the file will not be included in publish from a clean build. In subsequent builds, the default glob would include the file as it would then be present on disk.

I do think the issue here is that the code (that is the MSBuild target) for "correctly" integrating libman with the build system lives in the Web SDK, which is not going to play a role when run in a non-web SDK context (like MAUI).

I'm not convinced this is the best way to approach this problem since you are asking every SDK to include web specific concepts/targets to support this scenario. As things stand this won't work with WPF nor Windows Forms apps either.

In addition to that, if some other SDK like Maui were to include a target like that one, it wouldn't work either because it would run to late, on platforms like Maui, those files need to be converted to MauiAsset at the right time for the build to properly pack them.

You are likely better off including a target in the Build.targets file of the libman package that knows how to deal with the environments you are expected to run in and possibly finding a "point in time" early enough during the build process that allows you to use the same targets in the different target environments.

@jimmylewis
Copy link
Contributor

jimmylewis commented May 3, 2022

In addition to that, if some other SDK like Maui were to include a target like that one, it wouldn't work either because it would run to late, on platforms like Maui, those files need to be converted to MauiAsset at the right time for the build to properly pack them.

Generating content files during build is a common scenario, especially with web-like assets (compiling SCSS or minifying JS). Libman is certainly not the only case this will come up, so providing some measure of this in the SDK will benefit lots of other tasks.

Does MAUI have a documented convention we can use to insert these assets into the build at the right time? We already run before the Build target as a catch-all, but if there's an ItemGroup we need to add these to, that's easily added.

For legacy Web publish it's @(FilesForPackagingFromProject).
For WebSdk, they refresh the wwwroot\** glob.
For MAUI, it's ...?

@campersau
Copy link
Contributor

The issue also exists with Razor Class Libraries. My workaround for that is to just add the FilesForPackagingFromProject as Content items like this:

  <Target Name="_LibraryManagerRestoreContentItems" AfterTargets="LibraryManagerRestore">
    <ItemGroup>
      <Content Remove="@(FilesForPackagingFromProject)" />
      <Content Include="@(FilesForPackagingFromProject)" CopyToPublishDirectory="PreserveNewest" />
    </ItemGroup>
  </Target>

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

No branches or pull requests

3 participants