Fixing incorrect source map paths after CDN deployment
Diagnose and resolve HTTP 404s or malformed sourceMappingURL references when .map files are served from a CDN. This guide isolates the build-time path mismatch, provides a minimal reproduction, and delivers exact Webpack configuration patches to restore stack trace resolution. Baseline setup should align with Configuring Webpack for Production Source Maps before applying CDN overrides.
Key failure indicators include:
- Browser DevTools and error trackers fail to fetch
.mapassets, returning 404 or CORS errors. output.publicPathdefaults to/or relative paths, ignoring CDN base URLs during static asset promotion.- Explicitly defining absolute CDN paths in
devtoolModuleFilenameTemplateandsourceMapFilenameresolves the mismatch. - Cross-reference network traces with standard resolution flows documented in Source Map Generation & Stack Trace Debugging.
Symptom Identification & Network Trace Analysis
Isolate the exact failing request by opening your browser’s Network tab. Filter for .map extensions and observe 404 Not Found or 403 Forbidden status codes. Inspect the minified JavaScript bundle’s trailing comment.
If //# sourceMappingURL=main.js.map points to a relative path, the browser attempts to fetch it from the origin server. This fails when assets are promoted to a separate CDN origin.
Verify CORS headers on the CDN response. Missing Access-Control-Allow-Origin headers block cross-origin fetch attempts by DevTools and error tracking SDKs. Use curl -I to confirm the CDN serves the correct headers.
Root Cause: Build-Time Path Resolution vs. CDN Routing
Webpack resolves publicPath at compile time. CDN base URLs injected at deployment time create an immediate mismatch. Relative sourceMappingURL paths break when JavaScript bundles and .map files are hosted on different origins.
Edge caching compounds the routing failure. CDNs cache malformed paths aggressively. Without cache-busting or pre-deployment configuration correction, stale routing rules persist across multiple releases.
The build system must generate absolute URLs that match the final CDN routing structure. Assets must be validated before promotion to prevent broken symbolication pipelines.
Minimal Reproduction Setup
Trigger the path mismatch deterministically using a baseline Webpack 5 configuration. Set devtool: 'hidden-source-map' to generate external files without inline comments.
Configure output.publicPath: '/assets/' and deploy the dist/ directory to a CDN with the base URL https://cdn.production-domain.com/. After deployment, inspect the compiled bundle.
The trailing comment will read //# sourceMappingURL=/assets/main.js.map. The browser attempts to resolve this against https://app.production-domain.com/assets/main.js.map, resulting in a 404. The correct path must explicitly include the CDN origin.
Exact Configuration Fix (Webpack 5)
Apply production-safe overrides to force absolute CDN paths in generated maps. Override output.publicPath with the absolute CDN URL, or inject it dynamically via __webpack_public_path__.
Configure devtoolModuleFilenameTemplate to return absolute CDN paths for each module reference. Set sourceMapFilename to [file].map to prevent hash mismatches in CI/CD upload pipelines.
const path = require('path');
const CDN_BASE = process.env.CDN_BASE_URL || 'https://cdn.production-domain.com/';
module.exports = {
mode: 'production',
devtool: 'hidden-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
publicPath: CDN_BASE,
devtoolModuleFilenameTemplate: (info) => {
return `${CDN_BASE}src/${path.relative(process.cwd(), info.absoluteResourcePath)}`;
},
sourceMapFilename: '[file].map'
}
};
This configuration forces absolute CDN URLs in sourceMappingURL and module references. The hidden-source-map setting prevents inline exposure while preserving files for secure upload. Explicit sourceMapFilename ensures predictable naming for automated CI/CD upload scripts.
For dynamic CDN environments where URLs vary per deployment, inject the runtime override before the first chunk loads:
// Inject before first chunk loads
__webpack_public_path__ = window.__CDN_BASE__ || 'https://cdn.production-domain.com/';
This resolves path mismatches when CDN origins shift across environments. The assignment must execute before Webpack’s runtime initializes chunk loading logic.
Post-Deployment Verification & Cache Invalidation
Validate stack trace resolution by triggering an intentional error in production. Open DevTools Console and verify that the stack trace resolves to original .ts or .js source files with accurate line numbers.
Purge the CDN cache for .map extensions using Cache-Control: no-cache headers or the provider’s API invalidation endpoint. Confirm that error tracking platforms successfully download and symbolicate maps without fallback.
If the platform continues to report unresolved frames, verify that the .map files are publicly accessible at the exact URLs referenced in the compiled bundles. Cross-check the sourceMappingURL against the CDN’s actual routing table.
Common Mistakes
Using relative publicPath: '/' with CDN-hosted assets
Relative paths resolve against the current HTML document origin, not the CDN origin. This causes cross-origin 404s for .map files when the application and assets are served from different domains.
Omitting sourceMapFilename configuration
Webpack defaults to [file].map but may append hashes or alter paths when devtool is set to source-map. This breaks deterministic CI upload scripts that rely on predictable file naming conventions.
Uploading .map files to restricted CDN paths
CDN security rules frequently block .map extensions or require explicit Access-Control-Allow-Origin headers. Failing to configure bucket policies or CDN rules results in blocked fetches during symbolication.
Hardcoding CDN URLs in build config Hardcoded URLs prevent environment-specific deployments. Staging builds pointing to production CDNs corrupt error tracking data and expose unreleased source code to external origins.
FAQ
Why do source maps work locally but 404 after CDN deployment?
Local servers resolve relative paths against localhost, while CDNs require absolute URLs in sourceMappingURL. Webpack’s default publicPath does not auto-prepend CDN origins, causing the browser to request files from the wrong host.
Can I use devtool: 'eval-source-map' for production CDN builds?
No. eval-source-map embeds maps inline, significantly increasing bundle size and exposing raw source code. Use hidden-source-map or source-map with external CDN hosting to maintain performance and security.
How do I verify source maps are correctly mapped after CDN cache purge?
Trigger a controlled throw new Error('test') in production. Open DevTools Console and verify the stack trace resolves to original .ts/.js files with correct line numbers. Confirm your error tracking dashboard symbolicates the event without fallback warnings.