Skip to content

Add Blazor SSR css stylesheet link append-version component #49678

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

Closed
1 task done
Markz878 opened this issue Jul 27, 2023 · 8 comments
Closed
1 task done

Add Blazor SSR css stylesheet link append-version component #49678

Markz878 opened this issue Jul 27, 2023 · 8 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-static-web-assets Pillar: Complete Blazor Web

Comments

@Markz878
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

Since Blazor SSR doesn't have tag helpers, there should be some components to help the move from Razor pages.
Please add a component to replace the 'append-version' option in the link-tag helper.

Describe the solution you'd like

Add a component, that takes the href parameter, and appends a version to it automatically or based on a boolean flag.

Additional context

Here is a crude example I hacked together:

@using System.Security.Cryptography;
@using Microsoft.Extensions.Caching.Memory;
@inject IWebHostEnvironment environment;
@inject IMemoryCache cache;

<link href="@GetHref()" rel="stylesheet" />

@code {
    [Parameter][EditorRequired] public required string Href { get; set; }

    private string GetHref()
    {
        string? href = cache.GetOrCreate(Href, (_ =>
        {
            string filePath = Path.Combine(environment.WebRootPath, Href);
            string version = GetVersion(filePath);
            return $"{Href}?v={version}";
        }));
        return href ?? Href;
    }

    private string GetVersion(string filePath)
    {
        try
        {
            using SHA1 sha1 = SHA1.Create();
            using FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            byte[] hash = sha1.ComputeHash(fs);
            return Convert.ToBase64String(hash);
        }
        catch (Exception)
        {
            byte[] hash = new byte[16];
            Random.Shared.NextBytes(hash);
            return Convert.ToBase64String(hash);
        }
    }
}
@ghost ghost added the area-blazor Includes: Blazor, Razor Components label Jul 27, 2023
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Jul 27, 2023
@danroth27 danroth27 added this to the Backlog milestone Aug 16, 2023
@ghost
Copy link

ghost commented Aug 16, 2023

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.

@Bartmax
Copy link

Bartmax commented Oct 16, 2023

I think this is very much needed. Blazor SSR needs many quality of life improvements like this one before being ready for production.

@Bartmax
Copy link

Bartmax commented Oct 16, 2023

Here's my implementation:

{ProjectName}.csproj:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0-*" />

Program.cs:

builder.Services.AddMvcCore().AddRazorViewEngine();

Link.razor

@using Microsoft.AspNetCore.Mvc.ViewFeatures
@inject IFileVersionProvider FileVersionProvider
@code {
    [Parameter] public bool AppendVersion { get; set; } = true; // Change if you don't want to append version by default.
    [Parameter] public required string Href { get; set; } = "";

    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> AdditionalAttributes { get; set; } = default!;
    string href = "";

    protected override void OnInitialized()
    {
        href = AppendVersion ? FileVersionProvider.AddFileVersionToPath("/", Href) : Href;
    }
}

<link href="@href" @attributes="AdditionalAttributes" />

Usage:

<Link Href="/css/app.css" rel="stylesheet" AppendVersion="true" />

@Bartmax
Copy link

Bartmax commented Oct 16, 2023

Or a more reusable version:

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace {APP};

public abstract class AppendableVersion : ComponentBase
{
    [Inject] public IFileVersionProvider FileVersionProvider { get; set; } = default!;
    [Parameter] public bool AppendVersion { get; set; } = true;
    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> AdditionalAttributes { get; set; } = default!;

    protected string Source { get; set; } = "";

    protected string Result { get; private set; } = "";

    protected override void OnInitialized()
    {
        base.OnInitialized();
        Result = AppendVersion ? FileVersionProvider.AddFileVersionToPath("/", Source) : Source;
    }

}

Link.razor:

@inherits AppendableVersion

@code {
#pragma warning disable BL0007 // Auto property
    [Parameter] public required string Href { get { return base.Source; } set { base.Source = value; } }
#pragma warning restore BL0007
}

<link Href="@base.Result" @attributes="AdditionalAttributes" />

Script.razor:

@inherits AppendableVersion

@code {
#pragma warning disable BL0007 // Auto property
    [Parameter] public required string Src { get { return base.Source; } set { base.Source = value; } }
#pragma warning restore BL0007 // Auto property
}
<script src="@base.Result" @attributes="AdditionalAttributes" />

@ghost
Copy link

ghost commented Dec 22, 2023

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@Markz878
Copy link
Author

Markz878 commented Jan 2, 2024

link or script should be loaded before blazor component. so use blazor component like Link or Script I don't think it's a good idea. we need find a new way resolve this issue.

In Blazor SSR mode the entire page is rendered first before sending anything to the client, so the link tag doesn't have to "loaded before blazor". I have used my implementation of the Link component in production for a while and it works well. What is this argument based on @ArgoZhang ?

@ArgoZhang
Copy link

ArgoZhang commented Jan 2, 2024

Yes, you are right. My viewpoint is incorrect.

@mkArtakMSFT
Copy link
Contributor

Closing as a dupe of #52824

@mkArtakMSFT mkArtakMSFT closed this as not planned Won't fix, can't repro, duplicate, stale Jan 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-static-web-assets Pillar: Complete Blazor Web
Projects
None yet
Development

No branches or pull requests

6 participants