How to Generate Source Maps in Create React App: Implicit Generation, Build Folder Location & No Eject/Webpack

When building a React application with Create React App (CRA), your code undergoes transformation: it’s transpiled, bundled, minified, and optimized for production. While this process improves performance, it obfuscates your original code, making debugging errors or inspecting components in the browser difficult. This is where source maps come to the rescue.

A source map is a file that maps your minified/bundled code back to your original source files (e.g., .jsx, .tsx). It acts as a bridge between the browser’s dev tools and your development code, letting you see line numbers, variable names, and component structures as you wrote them—even in production.

In this blog, we’ll demystify how source maps work in CRA, covering:

  • How CRA implicitly generates source maps (no manual setup required).
  • Where to find source maps in the build folder.
  • How to control or customize source maps without ejecting or editing Webpack config directly.

Table of Contents#

  1. What Are Source Maps?
  2. How Create React App Generates Source Maps Implicitly
  3. Where Are Source Maps Located in the Build Folder?
  4. Generating Source Maps Without Ejecting or Webpack Configuration
  5. Advanced: Customizing Source Maps (Without Ejecting)
  6. Troubleshooting Common Source Map Issues
  7. Conclusion
  8. References

What Are Source Maps?#

Source maps are JSON files with a .map extension that map code in your bundled files (e.g., main.8a3b2.js) to lines/columns in your original source files (e.g., App.jsx). They solve a critical problem: when an error occurs in production, the browser reports the error in the minified code (e.g., Uncaught TypeError: Cannot read property 'x' of undefined at main.8a3b2.js:1:1234), which is useless for debugging. With source maps, the browser translates this to Uncaught TypeError: ... at App.jsx:42:15, pointing directly to your original code.

Key Benefits:

  • Debug production errors with original file/line references.
  • Use browser devtools to inspect components and variables as written.
  • Integrate with error-tracking tools (e.g., Sentry, Datadog) for actionable reports.

How Create React App Generates Source Maps Implicitly#

CRA (v1+) abstracts complex Webpack configuration, including source map generation. You don’t need to write a single line of Webpack config—CRA handles it out of the box, with behavior tailored to your environment (development vs. production).

Development vs. Production Environments#

CRA uses different source map "types" (via Webpack’s devtool option) depending on whether you’re running npm start (development) or npm run build (production):

Development (npm start)#

In development, CRA prioritizes fast rebuilds and detailed debugging. It uses eval-cheap-module-source-map, which:

  • Is fast to generate (critical for hot reloading).
  • Maps bundled code to original source files (but not to exact columns, trading speed for detail).
  • Embeds source map data directly in the bundle (no separate .map files) using eval statements.

Result: When you debug with npm start, errors in the browser console point to your original .jsx/.tsx files, not the bundled code.

Production (npm run build)#

In production, CRA balances debugging detail with bundle size. By default, it uses source-map, which:

  • Generates high-quality source maps (full line/column mapping).
  • Creates separate .map files (e.g., main.8a3b2.js.map) instead of embedding data in bundles (reduces bundle size).
  • Is slower to generate (but only runs during build, not development).

Note: In CRA v5+, production source maps are enabled by default. To confirm, check your package.json—no extra setup is needed!

Where Are Source Maps Located in the Build Folder?#

After running npm run build, CRA generates a build directory at your project root. Source maps live here, alongside minified JS/CSS bundles.

Typical Build Folder Structure#

build/  
├── static/  
│   ├── js/  
│   │   ├── main.8a3b2.js        # Minified JS bundle  
│   │   ├── main.8a3b2.js.map    # Source map for main JS bundle  
│   │   ├── 789.cba45.js         # Chunked JS bundle (for code splitting)  
│   │   └── 789.cba45.js.map     # Source map for chunked JS  
│   ├── css/  
│   │   ├── main.d6e7f.css       # Minified CSS bundle  
│   │   └── main.d6e7f.css.map   # Source map for CSS  
│   └── media/                   # Images/fonts (no source maps)  
├── index.html  
└── ...  

How Source Maps Are Linked#

Bundled files explicitly reference their source maps via a comment at the end. For example, main.8a3b2.js ends with:

//# sourceMappingURL=main.8a3b2.js.map  

Browsers (and tools like Sentry) use this comment to load the .map file and map minified code to original sources.

Generating Source Maps Without Ejecting or Webpack Configuration#

CRA’s "no eject" promise means you never need to edit Webpack config directly. Source maps work out of the box, but you can control their generation using the GENERATE_SOURCEMAP environment variable.

Enabling/Disabling Source Maps with GENERATE_SOURCEMAP#

By default:

  • GENERATE_SOURCEMAP=true (source maps are generated in production).
  • In development, source maps are always enabled (no need to configure).

To disable production source maps (e.g., to reduce build size), set GENERATE_SOURCEMAP=false in your build script:

package.json

{  
  "scripts": {  
    "build": "GENERATE_SOURCEMAP=false react-scripts build"  
  }  
}  

Now, running npm run build will not generate .map files in the build folder.

Advanced: Customizing Source Maps (Without Ejecting)#

CRA’s default source map behavior works for most apps, but you may need customization (e.g., smaller .map files, hidden source maps for security). To do this without ejecting, use tools like craco (Create React App Configuration Override) to modify Webpack’s devtool setting.

Using craco to Override Webpack Config#

craco lets you override CRA’s Webpack, Babel, and ESLint configs with a craco.config.js file. Here’s how to use it to customize source maps:

Step 1: Install craco#

npm install @craco/craco --save-dev  

Step 2: Update package.json Scripts#

Replace react-scripts with craco in your start, build, and test scripts:

package.json

{  
  "scripts": {  
    "start": "craco start",  
    "build": "craco build",  
    "test": "craco test"  
  }  
}  

Step 3: Create craco.config.js#

Add a craco.config.js file in your project root to override Webpack’s devtool (source map type).

Example 1: Use hidden-source-map for Production
hidden-source-map generates .map files but does not add //# sourceMappingURL comments. This keeps source maps private (e.g., for internal debugging) while hiding them from public users.

craco.config.js

module.exports = {  
  webpack: {  
    configure: (webpackConfig, { env, paths }) => {  
      // Only override production config  
      if (env === 'production') {  
        // Use 'hidden-source-map' instead of default 'source-map'  
        webpackConfig.devtool = 'hidden-source-map';  
      }  
      return webpackConfig;  
    },  
  },  
};  

Example 2: Smaller Source Maps with cheap-source-map
cheap-source-map omits column mappings, reducing .map file size (useful for large apps):

craco.config.js

module.exports = {  
  webpack: {  
    configure: (webpackConfig, { env }) => {  
      if (env === 'production') {  
        webpackConfig.devtool = 'cheap-source-map';  
      }  
      return webpackConfig;  
    },  
  },  
};  

Step 4: Build and Verify#

Run npm run build and check the build/static/js folder. You’ll see .map files with your custom devtool behavior.

Troubleshooting Common Source Map Issues#

1. Source Maps Not Generating in Production#

  • Check GENERATE_SOURCEMAP: Ensure it’s not set to false in your build script (see Enabling/Disabling Source Maps).
  • Verify CRA Version: Older CRA versions (<=v4) had different defaults. Upgrade to CRA v5+ for consistent behavior.

2. Source Maps Not Working in DevTools#

  • Browser Settings: In Chrome DevTools, go to Settings > Experiments and check "Enable JavaScript source maps" and "Enable CSS source maps".
  • Missing .map Files: If using hidden-source-map, DevTools won’t auto-load maps. Manually upload .map files to DevTools (under "Sources" tab > "Filesystem" > "Add folder to workspace").

3. Large .map Files Slowing Down Builds#

  • Use cheap-* or hidden-source-map: These generate smaller maps than the default source-map.
  • Disable in Production: If debugging isn’t critical, set GENERATE_SOURCEMAP=false to skip map generation entirely.

4. CSS Source Maps Missing#

CRA generates CSS source maps by default. If missing:

  • Check build/static/css for .css.map files (e.g., main.d6e7f.css.map).
  • Ensure GENERATE_SOURCEMAP=true (CSS maps depend on this flag too).

Conclusion#

Source maps are indispensable for debugging React apps, and Create React App makes them effortless to use. Key takeaways:

  • Implicit Generation: CRA auto-generates source maps for development and production.
  • Build Folder Location: Find .map files in build/static/js and build/static/css.
  • No Eject Needed: Control generation with GENERATE_SOURCEMAP, or customize with craco.
  • Balance Detail vs. Size: Use devtool types like hidden-source-map or cheap-source-map to optimize for production.

By leveraging source maps, you can debug production issues with confidence—without sacrificing CRA’s simplicity.

References#