How to Fix: nextjs15 with .babelrc report $ is not a function

5 min read

Next.js 15 with .babelrc causing $ is not a function: root cause and fix

If a fresh Next.js 15 app starts throwing $ is not a function right after adding a .babelrc, the real problem is usually not jQuery, not your component code, and not random runtime corruption. The issue is typically caused by replacing Next.js’s expected compiler pipeline with a custom Babel setup that changes how application code is transformed.

Understanding the Root Cause

In Next.js 15, the default compilation flow is built around SWC, not traditional Babel-first transforms. When you add a .babelrc, Next.js can switch behavior and start using your Babel configuration for parts of the build pipeline. If that configuration is incomplete, outdated, or overrides the framework defaults incorrectly, the generated client bundle can become incompatible with what Next expects at runtime.

The most common pattern looks like this:

  • You create a new app with create-next-app.
  • You add a custom .babelrc using next/babel.
  • You also customize preset-env, module transforms, or plugin behavior.
  • The compiled output no longer matches what Next.js 15 expects.
  • A runtime failure surfaces as $ is not a function.

This happens because Next.js preset integration is sensitive to transformation order and compiler ownership. In older setups, custom Babel config was more common. In newer Next.js releases, forcing Babel into the pipeline can disable or alter SWC-based optimizations, React transforms, or bundler assumptions. That mismatch can produce cryptic runtime errors, including minified variable failures like $ being called as a function.

In short, the bug is usually caused by one of these technical reasons:

  • Overriding Next’s default transpilation behavior with a custom Babel preset config.
  • Adding unsupported preset-env options that transform modules or syntax in a way Next 15 does not expect.
  • Using Babel for a case that should be handled by SWC.
  • Carrying over an older .babelrc from a previous Next.js version.

If the issue starts immediately after introducing .babelrc, that file is the first thing to suspect.

Step-by-Step Solution

The safest fix is to remove the custom .babelrc unless you absolutely need Babel-only plugins that SWC cannot replace.

1. Confirm that .babelrc is the trigger

Temporarily rename or delete the file:

mv .babelrc .babelrc.backup

Then restart the dev server:

npm run dev

If the error disappears, the problem is your Babel configuration.

2. Preferred fix: remove .babelrc entirely

For most Next.js 15 projects, you do not need Babel at all. Let SWC handle compilation.

rm .babelrc

Then clear the build cache and reinstall if needed:

rm -rf .next node_modules package-lock.json
npm install
npm run dev

This restores the default compiler path and resolves the runtime mismatch in many cases.

3. If you must keep Babel, use the minimal safe config

If your project depends on a Babel-only plugin, start with the smallest possible config and avoid custom preset-env overrides unless they are truly required.

{
  "presets": ["next/babel"]
}

This is much safer than nesting custom options into next/babel right away.

4. Remove custom preset-env module transforms

If your current config looks like this conceptually:

{
  "presets": [
    [
      "next/babel",
      {
        "preset-env": {
          "modules": "commonjs"
        }
      }
    ]
  ]
}

remove that customization. In a modern Next.js app, forcing CommonJS or manually changing module output can break the bundler/runtime contract.

Replace it with:

{
  "presets": ["next/babel"]
}

5. Move Babel-only needs to supported Next.js alternatives when possible

Many older Babel use cases no longer require Babel in Next 15. Before keeping a custom config, check whether you can replace it with:

  • next.config.js options
  • TypeScript compiler settings
  • SWC-compatible transforms
  • built-in React and Next.js behavior documented in the Next.js documentation

6. Clean caches after changing compiler configuration

Compiler changes can leave stale output behind. Always clear the cache after removing or simplifying Babel:

rm -rf .next
npm run dev

7. Verify package versions

Make sure your Next, React, and React DOM versions align:

npm ls next react react-dom

A healthy setup should show matching supported versions for your app. If dependencies are inconsistent, update them:

npm install next@latest react@latest react-dom@latest

8. Example of a working approach

Recommended for most apps:

// No .babelrc file at all

If Babel is unavoidable:

{
  "presets": ["next/babel"],
  "plugins": []
}

Keep it minimal and add plugins one by one until you identify the exact incompatible transform.

Common Edge Cases

1. A Babel plugin is the real culprit, not the preset itself

Sometimes next/babel is fine, but a plugin such as a legacy class property transform, module resolver, or macro-related transform breaks the emitted code. If you need Babel, reintroduce plugins gradually.

2. Old project config copied into a new Next 15 app

A configuration that worked in Next 12, Next 13, or early React setups may be incompatible now. Legacy options for preset-env, decorators, or module transforms are common offenders.

3. Turbopack or bundler behavior differs between environments

If the issue appears only in dev or only in production, the custom Babel config may be interacting differently with the active bundler path. Test both:

npm run dev
npm run build
npm run start

4. Monorepo or shared config interference

A root-level Babel config such as babel.config.js can affect your Next app even if the app-local config looks harmless. Check parent directories for inherited Babel settings.

5. Third-party libraries expecting ESM behavior

If Babel rewrites modules unexpectedly, some packages may stop working correctly in the browser bundle. This can manifest as strange runtime invocation errors, including minified variables like $.

6. Cache makes the fix look ineffective

After changing compiler settings, stale artifacts in .next or package manager caches can keep the error around. Always clear build outputs before retesting.

FAQ

Should I use .babelrc in Next.js 15?

Only if you truly need a Babel-specific plugin that cannot be replaced by SWC or built-in Next.js features. For most projects, the best practice is to avoid custom Babel configuration entirely.

Why does the error say $ is not a function instead of mentioning Babel?

Because the failure usually appears in the generated runtime bundle, not at config parse time. The compiler mismatch produces broken emitted JavaScript, and the browser reports the symptom, not the original configuration mistake.

What is the safest Babel config if I cannot remove it?

Use the smallest possible setup:

{
  "presets": ["next/babel"]
}

Then add only the exact plugin you need, one at a time, while testing after each change.

The practical fix for this GitHub issue is simple: remove the custom .babelrc or reduce it to a minimal next/babel preset with no aggressive overrides. In Next.js 15, trying to customize Babel the old way often causes runtime breakage that surfaces as $ is not a function.

Leave a Reply

Your email address will not be published. Required fields are marked *