You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure托管Angular应用静态资源加载失败报Unexpected token '<'错误

问题根因

你遇到的问题由三个核心配置错误共同导致:

  • 中间件执行顺序错误,重写路径逻辑不严谨
  • 构建参数与Angular配置冲突,静态资源无哈希后缀引发缓存问题
  • 无判断的强制路径重写导致响应已发送后仍修改请求,触发服务端报错

修复步骤

1. 修正Startup.cs中间件配置

首先调整中间件顺序,UseStaticFiles必须放在路径重写逻辑之前,同时仅当请求返回404、且为前端路由请求时才重写路径到index.html,修复后的代码如下:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // 先处理静态资源请求
        app.UseStaticFiles();

        // 仅对404的非静态资源请求做前端路由回退
        app.Use(async (context, next) =>
        {
            await next();
            // 只处理响应状态码为404、且不是API/带后缀的静态资源类的请求
            if (context.Response.StatusCode == 404 
                && !context.Request.Path.StartsWithSegments("/api")
                && !Path.HasExtension(context.Request.Path.Value))
            {
                context.Request.Path = "/index.html";
                // 清空之前的响应内容避免报错
                context.Response.Clear();
                await next();
            }
        });
    }
}

该修改同时解决了服务端StatusCode cannot be set报错,以及静态资源请求错误返回index.html的问题。

2. 修正构建命令参数

你package.json中的构建命令加了--output-hashing none,优先级高于angular.json中production配置的outputHashing: all,导致编译出的静态资源无哈希后缀,新版本部署后用户浏览器缓存的旧资源请求404触发回退逻辑。
修改package.json的build命令,删除--output-hashing none即可:

"build": "ng build --aot --prod"

后续构建出的js、css文件都会自带哈希后缀,部署新版本后不会出现旧缓存资源请求问题。

3. 可选优化:配置静态资源缓存规则

可以在UseStaticFiles中添加缓存配置,给带哈希后缀的静态资源设置长期缓存,给index.html设置不缓存,进一步避免缓存问题:

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        // index.html不缓存
        if (ctx.File.Name.Equals("index.html", StringComparison.OrdinalIgnoreCase))
        {
            ctx.Context.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
            ctx.Context.Response.Headers["Pragma"] = "no-cache";
            ctx.Context.Response.Headers["Expires"] = "0";
        }
        // 带哈希的静态资源缓存1年
        else if (Regex.IsMatch(ctx.File.Name, @"\.[a-f0-9]{8}\.(js|css|png|jpg|svg)$"))
        {
            ctx.Context.Response.Headers["Cache-Control"] = "public, max-age=31536000, immutable";
        }
    }
});

内容的提问来源于stack exchange,提问作者Sharon Watinsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:24:02