using System.Collections.Concurrent;
using System.Text.Json;

namespace Dpz.Core.Web.Library;

public class AssetService
{
    private readonly IWebHostEnvironment _environment;
    private static readonly ConcurrentDictionary<string, string> Manifest = new(
        StringComparer.OrdinalIgnoreCase
    );

    public AssetService(IWebHostEnvironment environment, ILogger<AssetService> logger)
    {
        _environment = environment;
        if (!Manifest.IsEmpty)
        {
            return;
        }
        var manifestPath = Path.Combine(_environment.WebRootPath, "assets-manifest.json");
        if (File.Exists(manifestPath))
        {
            try
            {
                var json = File.ReadAllText(manifestPath);
                var manifest =
                    JsonSerializer.Deserialize<Dictionary<string, string>>(json)
                    ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                InitManifest(manifest);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "加载资源清单失败");
            }
        }
    }

    private static void InitManifest(Dictionary<string, string> manifest)
    {
        foreach (var (key, value) in manifest)
        {
            Manifest.TryAdd(key, value);
        }
    }

    public string GetPath(string path)
    {
        // 在开发环境中,返回原始路径
        if (_environment.IsDevelopment())
        {
            return path;
        }

        // 规范化路径键:移除 ~ 和开头的 /
        var key = path.TrimStart('~').TrimStart('/');

        if (Manifest.TryGetValue(key, out var hashedPath))
        {
            return "/" + hashedPath;
        }

        // 如果在清单中未找到,返回原始路径
        return path;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

AssetService 代码解释

这个 AssetService 类是一个用于管理Web应用程序中静态资源(assets)的服务,主要功能是根据环境(开发/生产)返回正确的资源路径。

主要功能

  1. 资源清单加载

    • 在构造函数中,从 wwwroot 目录加载 assets-manifest.json 文件
    • 这个清单文件应该包含原始资源路径到带哈希版本路径的映射
    • 如果加载失败或文件不存在,会初始化一个空字典
  2. 路径解析

    • GetPath 方法根据当前环境返回适当的资源路径
    • 在开发环境(IsDevelopment())直接返回原始路径
    • 在生产环境使用清单文件中的哈希版本路径

工作原理

  • 开发环境:直接使用原始路径,方便调试和热重载
  • 生产环境:使用带哈希的文件名,实现缓存控制和版本管理
  • 路径规范化:处理以 ~/ 开头的路径,确保能正确匹配清单中的键

典型使用场景

这种服务通常与前端构建工具(如Webpack、Vite等)配合使用,这些工具会生成带哈希的文件名和对应的清单文件,用于解决浏览器缓存问题,同时确保用户能获取到最新的资源版本。

错误处理

  • 如果清单文件不存在或解析失败,会记录错误并回退到原始路径
  • 如果请求的资源在清单中找不到,同样回退到原始路径
评论加载中...