dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.19k stars 9.93k forks source link

Isolating CSS for component use from Razor class library not working #49881

Open WhitWaldo opened 1 year ago

WhitWaldo commented 1 year ago

I'm using Blazor Server with Tailwind CSS for my front-end. If I have all my components in the same project, the Tailwind CLI will scan all my Razor files and produce a single purged and minified CSS file. That's great, but I want to shuffle out my components and use them from a separate shared Razor Class Library across all my web projects and this is where I'm running into difficulty.

Tailwind provides you with a set of classes that are attached to each HTML element to set up whatever look you're aiming for. An application of this might then look like:

<button type="button" class="bg-red-50 px-2 py-1 text-sm font-normal text-red-500 shadow-sm rounded-sm">Click me</button>

At build time, the Tailwind CLI does what appears to be a really basic regex match across each file that matches a file glob to pull all the named classes then produces a single CSS output to a named location with all these classes and dependencies. Unfortunately, there doesn't appear to exist a tool that enables this on a per-file basis for purposes of Blazor per-component CSS isolation (asked and answered by myself yesterday).

Rather, I created a PowerShell script that runs as a pre-build MSBuild task that locates all the Razor file (excludes _Imports.razor), creates a temp Tailwind configuration file for each file pointing exclusively to the file's path, builds the minified Tailwind CSS and outputs as ".razor.css" alongside the file and deletes the Tailwind config file. Looking at the /obj directory after a build, it successfully produces a "/.bundle.scp.css" file filled with all the isolated values such as:

[type='checkbox']:checked[b-qlvx5tydtg],[type='radio']:checked[b-qlvx5tydtg] {
  border-color: transparent;
  background-color: currentColor;
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}

This builds to a private NuGet and upon import into my web project, I ensure that my _Host.cshtml is using the web project CSS file with <link href="<myProject>.styles.css" rel="stylesheet"/>

I launch in debug and upon closer inspection, the HTML comprising any of the imported components from the RCL isn't pointing to any of the isolated classes:

<div class="flex items-center space-x-8">
    <span class="inline-flex"><a href="#" class="-mx-1 rounded-full bg-gray-transparent p-1 text-gray-200 hover:text-gray-100"> 
    <span class="sr-only">View element</span>
</div>

Moreover, the <myProject>.styles.css 404s if I try to visit it in my browser.

What am I doing wrong here and how can I use these isolated stylesheets from my RCL in my other project?

Perhaps related to this issue

davidwengier commented 1 year ago

Moving this to the runtime, as I suspect that the best place for an answer, but if it ends up being a compiler issue feel free to send it back :)

gvreddy04 commented 1 year ago

We saw a similar issue while using the BlazorBootstrap component library with the Blazor Empty templates. The workaround is mentioned in the BlazorBootstrap demos. Hope this information helps as an interim fix.

Blazor WebAssembly: https://demos.blazorbootstrap.com/getting-started/blazor-webassembly#add-css-references Blazor Server: https://demos.blazorbootstrap.com/getting-started/blazor-server#add-css-references

<link href="_content/Blazor.Bootstrap/Blazor.Bootstrap.bundle.scp.css" rel="stylesheet" />
WhitWaldo commented 1 year ago

Oddly, despite adding the line for my own project and a similar one for my imported RCL project, I get a 404 for either one when loading in debug.

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

NathanVG commented 7 months ago

I would like to jump in on this, as my issue is similar, but I think the solution could be simpler.

I'm trying to build a Razor Class Library with components to use in several other projects. I would like to build the components with Tailwind, just like @WhitWaldo. Ideally I would not have to run Tailwind in the RCL, but only in the projects consuming the RCL.

To achieve this I made a package out of my RCL, which works great, except Tailwind can't access the classes used in the components and as such doesn't generate the css.

I have tried setting up the package in such a way that the .razor files are included in a subfolder in the package, which I can then point my tailwind config to. However after spending a day trying I cannot get the files to output into the eventual package, all I see in visual studio under packages in the project consuming the RCL package is a .dll file.

Am I missing something? Is it possible to have for instance:

desmondinho commented 5 months ago

I would like to jump in on this, as my issue is similar, but I think the solution could be simpler.

I'm trying to build a Razor Class Library with components to use in several other projects. I would like to build the components with Tailwind, just like @WhitWaldo. Ideally I would not have to run Tailwind in the RCL, but only in the projects consuming the RCL.

To achieve this I made a package out of my RCL, which works great, except Tailwind can't access the classes used in the components and as such doesn't generate the css.

I have tried setting up the package in such a way that the .razor files are included in a subfolder in the package, which I can then point my tailwind config to. However after spending a day trying I cannot get the files to output into the eventual package, all I see in visual studio under packages in the project consuming the RCL package is a .dll file.

Am I missing something? Is it possible to have for instance:

  • ComponentLibraryPackage

    • Compile Time Assemblies

    • ComponentLibraryPackage.dll

    • Components

    • Button.razor

    • ...

Hi!

Did you solve your problem in the end? I am facing the same thing right now. I've managed to modify .nuspec file in order to include desired components into the package, but then I realized that all the packages sit somewhere on the client's machine. So, I am struggling with the path to these files...

NathanVG commented 5 months ago

Hey @desmondinho , no I did not manage to solve this, but I did find a workaround in the end.

I generate my tailwind classes for my RCL, and expose the resulting css file, which I then include in the consuming project. This means I kind of lose one of the benefits of tailwind (smaller css file sizes) but any classes not generated in the consuming project are at least caught with the css file from the RCL library.

Basically the css files for nuget packages (if configured that way) can be accessed from _content/YOUR_PACKAGE/.../styles.css after building the consuming project. If you just include the <link> to that file in your consuming projects' header it should be accessible.

Some more info here.