Problem
After a deploy, a subset of users can’t load the app. For them, a specific old chunk URL (e.g. chunk-B3EQFA6E.js) returns index.html with Content-Type: text/html instead of JavaScript. That triggers a MIME error and the app fails to boot.
For me (and most users) the same URL correctly serves application/javascript, and the app works.
Actual error (from console):
Error: Unsupported Content-Type "text/html" loading https://domain.app/chunk-B3EQFA6E.js imported from https://domain.app/_angular_material_expansion.6sH6WbSzQn.js. Modules must be served with a valid MIME type like application/javascript.
at On (polyfills-0X0I2Qx.js:15:314)
at async polyfills-0X0I2Qx.js:15:695
Environment:
- Angular app with micro-frontends (@angular-architects/native-federation)
- Nginx serving the SPA
- We previously had a service worker, but we unregistered it on all clients (and verified there’s no SW registered in DevTools for affected users).
Nginx config (relevant parts):
server {
listen 80;
root /usr/share/nginx/html;
# index.html - no cache
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate, proxy-revalidate, max-age=0";
add_header Pragma "no-cache";
expires -1;
try_files $uri =404; # <-- important
}
# SPA fallback (all routes go to index.html)
location / {
try_files $uri $uri/ /index.html =404;
}
# Remote entry (no cache)
location ~ ^/remoteEntry.json$ {
add_header Cache-Control "no-cache, no-store, must-revalidate, proxy-revalidate, max-age=0";
add_header Pragma "no-cache";
expires -1;
try_files $uri =404;
}
}
Here’s what the DevTools Network → Headers screenshot shows for the failing request:
• Request URL: https://<domain>/chunk-B3EQFA6E.js
• Request Method: GET
• Status Code: 200 OK (from disk cache)
• Remote Address: <server-ip>:443
• Referrer Policy: strict-origin-when-cross-origin
Response Headers
• Content-Type: text/html
• Date: Thu, 16 Oct 2025 08:54:20 GMT
• ETag: W/"68eff171-c64e"
• Last-Modified: Wed, 15 Oct 2025 19:09:37 GMT
• Server: nginx/1.29.2
• Vary: Accept-Encoding
• X-Content-Encoding-Over-Network: gzip
Request Headers (partial; banner shows provisional headers)
• Referrer: https://<domain>/dashboard
• User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
• Sec-CH-UA: "Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"
• Sec-CH-UA-Platform: "Windows"
• Sec-CH-UA-Mobile: ?0
Key takeaway from the image: the JavaScript chunk is being served as text/html from disk cache, which explains the MIME-type error and why the app breaks for those users.
Questions:
Is the SPA fallback (
try_files $uri $uri/ /index.html) the reason an old missing *.js gets served asindex.htmlfor some users?
Should I disable SPA fallback for static assets and return 404 instead, e.g.:location ~* \.(js|mjs|css|map|json|png|jpg|gif|svg|ico|woff2?)$ { try_files $uri =404; }so missing hashed assets never return HTML?
Any other headers or Nginx rules I should add to make this robust (e.g.,
Cache-Control: no-storeonindex.html, long-cache & immutable on static assets, ensuring correct types for .js/.mjs`)?Recommended way to reproduce this on any other stage so I can test the fix?