---
title: "Upload source maps with bundlers | Grafana Cloud documentation"
description: "Configure webpack, rollup, vite, or esbuild to upload source maps to Grafana Cloud using Faro bundler plugins."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Install source maps with bundlers

Configure Webpack, Rollup/Vite, or esbuild bundlers to automatically upload source maps to Grafana Cloud during builds.

> Note
> 
> The source map upload endpoint differs from the Faro Collector endpoint. Use the endpoint shown in **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**.

Faro bundler plugins support client-side rendered applications only. Server-side rendering isn’t supported. Next.js client-side apps may need `_next/` path adjustments using the `nextjs` option.

## Webpack plugin

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npm install --save-dev @grafana/faro-webpack-plugin
```

or

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
yarn add --dev @grafana/faro-webpack-plugin
```

## Rollup/Vite plugin

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npm install --save-dev @grafana/faro-rollup-plugin
```

or

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
yarn add --dev @grafana/faro-rollup-plugin
```

## Esbuild plugin

> Note
> 
> The esbuild plugin is currently **experimental**. While it provides feature parity with the rollup and webpack plugins, it may have issues or limitations. Report any problems you encounter.

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
npm install --save-dev @grafana/faro-esbuild-plugin
```

or

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
yarn add --dev @grafana/faro-esbuild-plugin
```

## Obtain an API key

To use the Faro JavaScript bundler plugins, you must generate a token for the API key value with the necessary permissions to upload source maps to Grafana Cloud. To generate a token, follow these steps:

1. Navigate to the [Grafana website](/).
2. Sign in to your account and then click **My Account** in the top right corner.
3. In the sidebar under **Security**, click **Access Policies** and then click **Create access policy**.
4. Select the `sourcemaps:read`, `sourcemaps:delete`, and `sourcemaps:write` scopes from the drop-down list.
5. After creating your access policy, click **Add token** in the card for your newly created policy.
6. **Create** the token and be sure to copy the token value, as you aren’t be able to see it again.

After you have generated a token with the API key value, you can use it in the Faro JavaScript bundler plugins to upload your source maps to Grafana Cloud. Use the generated token value as the `apiKey` value in the configuration options for the bundler plugins.

For best practices, store your token in a secure location and don’t expose it in your source code. Consider using environment variables or a secrets manager to securely store and access your API key.

## Webpack configuration

Add the plugin to your `webpack.config.js`:

JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```javascript
// other imports
import FaroSourceMapUploaderPlugin from '@grafana/faro-webpack-plugin';

module.exports = {
  // other configs
  plugins: [
    // other plugins
    new FaroSourceMapUploaderPlugin({
      appName: '$your-app-name',
      endpoint: '$your-faro-sourcemap-api-url',
      apiKey: '$your-api-key',
      appId: '$your-app-id',
      stackId: '$your-stack-id',
      gzipContents: true,
      // Set skipUpload: true to upload later with CLI
      // skipUpload: true,
    }),
  ],
};
```

## Rollup/Vite configuration

Add the plugin to your `rollup.config.js` or `vite.config.js`:

JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```javascript
// other imports
import faroUploader from '@grafana/faro-rollup-plugin';

export default defineConfig(({ mode }) => {
  return {
    // other configs
    plugins: [
      // other plugins
      faroUploader({
        appName: '$your-app-name',
        endpoint: '$your-faro-sourcemap-api-url',
        apiKey: '$your-api-key',
        appId: '$your-app-id',
        stackId: '$your-stack-id',
        gzipContents: true,
        // Set skipUpload: true to upload later with CLI
        // skipUpload: true,
      }),
    ],
  };
});
```

## Esbuild configuration

Add the plugin to your esbuild build script:

> Note
> 
> The esbuild plugin automatically injects a `file` property into each source map during the build, even when `skipUpload: true` is set. This is required for Grafana to correctly match source maps to JS chunks when de-obfuscating stack traces.
> 
> Angular applications are commonly affected by this because Angular’s default esbuild builder does not include the `file` field in generated source maps. If you upload source maps separately via the Faro CLI, use this plugin with `skipUpload: true` to ensure the `file` field is set before upload.

JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```javascript
import * as esbuild from 'esbuild';
import faroEsbuildPlugin from '@grafana/faro-esbuild-plugin';

await esbuild.build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  outdir: 'dist',
  plugins: [
    faroEsbuildPlugin({
      appName: '$your-app-name',
      endpoint: '$your-faro-sourcemap-api-url',
      apiKey: '$your-api-key',
      appId: '$your-app-id',
      stackId: '$your-stack-id',
      gzipContents: true,
      // Set skipUpload: true to upload later with CLI
      // skipUpload: true,
    }),
  ],
});
```

## Configuration options

Configure bundler plugins with these options:

**Required options:**

- `appName: string` - Application name that matches your Faro Web SDK configuration
- `endpoint: string` - Source map API endpoint from **Frontend Observability** &gt; **Settings** &gt; **Source Maps** &gt; **Configure source map uploads**
- `apiKey: string` - API key with `sourcemaps:read`, `sourcemaps:write`, and `sourcemaps:delete` scopes
- `appId: string` - Application ID that matches your Faro Web SDK configuration
- `stackId: string` - Grafana Cloud stack ID

**Optional options:**

- `outputPath: string` - Override output directory path for source maps. Uses bundler output path by default
- `outputFiles: string[] | RegExp` - List of source map files or regex pattern to match. Uploads all source maps by default
- `bundleId: string` - Bundle/build ID. Auto-generated by default
- `keepSourcemaps: boolean` - Keep source maps in generated bundle after uploading. Default: `false`
- `gzipContents: boolean` - Compress source maps before uploading. Default: `true`
- `verbose: boolean` - Enable detailed logging during upload. Default: `false`
- `skipUpload: boolean` - Skip uploading during build and export bundle ID to environment file. Default: `false`
- `maxUploadSize: number` - Maximum upload size in bytes for single batch. Default: 30MB
- `recursive: boolean` - Recursively search subdirectories for source maps. Default: `false`
- `nextjs: boolean` - Webpack only. Prepend `_next/` to file properties for Next.js compatibility. Only needed when your Next.js application has both client and server side code. If both `prefixPath` and `nextjs` are provided, they are combined as `${prefixPath}/_next/`. Default: `false`
- `proxy: string` - Proxy URL to route source map uploads through. Supports HTTP and HTTPS proxies. Include credentials in the URL if authentication is required: `http://username:password@proxy.example.com:8080`
- `prefixPath: string` - Prefix to prepend to the `file` property in source maps. Useful when files in the browser appear in a different path hierarchy than the bundler is aware of (for example, when using a CDN where stack traces show `cdn/index.js` but the source map only shows `index.js`)
- `prefixPathBasenameOnly: boolean` - When `true`, strips any directory path from the source map `file` property before prepending `prefixPath`, keeping only the filename. Useful when assets are deployed flat to a CDN with no subdirectory structure. For example, if the source map’s `file` is `assets/index.js` and `prefixPath` is `https://cdn.example.com/assets/`, this produces `https://cdn.example.com/assets/index.js` instead of `https://cdn.example.com/assets/assets/index.js`. Only applies when `prefixPath` is set. Default: `false`

## Verify source maps

After building your application, verify uploads in Frontend Observability by navigating to **your app** &gt; **Settings** &gt; **Source Maps**. If you set `skipUpload: true`, complete the upload using the CLI.

For troubleshooting common issues, refer to [Troubleshooting](/docs/grafana-cloud/monitor-applications/frontend-observability/sourcemap-uploads/troubleshooting/).
