transpilePackages

Compile dependencies that ship raw TypeScript or JSX instead of leaving them as-is.

Signature
transpilePackages?: string[] // default: []
  • Added in Next.js v13.0.0

Parameters

ParameterTypeDescription
$transpilePackagesoptionalstring[]= []Package names to compile and bundle rather than treat as untouched runtime code. Scoped names such as '@scope/pkg' are supported. Paths and glob patterns are not.

Errors

next build throws at start if a package appears in both transpilePackages and serverExternalPackages.

Changelog

  • PHP v13.0.0transpilePackages added, replacing the next-transpile-modules package.

Next.js does not compile code inside node_modules. A dependency that publishes raw .ts or .tsx therefore reaches the bundler as source it will not transform, and the build fails on the first interface or JSX tag. Listing the package opts it into compilation.

When to reach for it

  • A published dependency ships untranspiled TypeScript or JSX. The alternative fix is to build the package to plain JavaScript and point its main/exports at the output.
  • You use the Pages Router and want a node_modules dependency bundled into the route instead of loaded through Node's require at runtime.
  • You build the Pages Router with webpack and the dependency's source lives outside the app directory, as with apps/web importing packages/ui.

What trips people up

You often do not need it. Turbopack transpiles workspace packages in npm, pnpm and Yarn workspaces automatically under both routers, and webpack does the same for the App Router — so a monorepo package usually works untouched. Values are bare package names: packages/ui or @acme/* will not match. A package listed here cannot also appear in serverExternalPackages. Entries already in optimizePackageImports, and the packages in the shipped default list, are added for you.

Example

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  transpilePackages: ['package-name', '@scope/pkg'],
}

export default nextConfig

When to use it

  • Build a dependency that publishes raw .tsx instead of compiled JavaScript.
  • Bundle a node_modules dependency into a Pages Router route rather than requiring it at runtime.
  • Replace a legacy next-transpile-modules wrapper in an upgraded config.

Frequently asked questions

Why do I get Unexpected token 'export' or a JSX syntax error from node_modules?

The dependency ships untranspiled source and Next.js does not compile node_modules by default — add the package name to transpilePackages. The other fix is to have the package build to plain JavaScript and point its main/exports field at the compiled output.

Do monorepo workspace packages need transpilePackages?

Usually no. Turbopack transpiles workspace packages in npm, pnpm and Yarn workspaces automatically under both routers, and webpack does the same for the App Router; only webpack builds of the Pages Router with sources outside the app directory still need the entry.

Can a package be in both transpilePackages and serverExternalPackages?

No, Next.js throws at the start of the build if it is. The options are contradictory: one compiles and bundles the package, the other leaves it to be required at runtime.

More examples

A dependency that publishes its source

Without the entry the build stops on the package's first JSX element, because node_modules is not compiled. This is the case transpilePackages is really for — a monorepo workspace package normally needs no entry at all, since Turbopack already transpiles workspace sources.

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  // @acme/charts ships src/*.tsx with no build step
  transpilePackages: ['@acme/charts'],
}

export default nextConfig

Patterns that do not work

Only exact package names are matched, so a scope-wide glob silently transpiles nothing and the original syntax error stays. Every package in a scope must be listed individually.

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  transpilePackages: [
    '@acme/ui', // works: an exact package name
    // '@acme/*',        // no: globs are not supported
    // '../packages/ui', // no: paths are not supported
  ],
}

export default nextConfig

Migrating off next-transpile-modules

The built-in option replaces the community plugin entirely. Dropping the wrapper also removes a webpack-specific layer, which matters because Turbopack is the default bundler from Next.js 16 onward.

Example · typescript
// Before: next.config.js
// const withTM = require('next-transpile-modules')(['@acme/ui'])
// module.exports = withTM({})

// After: next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  transpilePackages: ['@acme/ui'],
}

export default nextConfig

Discussion

  • Be the first to comment on this lesson.