“require is not defined” means require() isn’t available here; use a bundler, switch to import, or run the code in Node.
You’ll usually see this error the moment you open DevTools, refresh a page, or run a build that used to work. It feels unfair because the code can look fine. The good news is that the fix is almost always about where the code is running and how your files get loaded.
This guide keeps it practical. You’ll learn what triggers the message, how to pinpoint the exact source in minutes, and which fix fits your setup. You’ll also get a small checklist you can paste into your own notes.
What “Require Is Not Defined” Really Means
In plain terms, require() is a loader function used by CommonJS modules. CommonJS is the module style that Node.js popularized, and lots of older build setups and packages still use it.
A browser page does not ship with CommonJS built in. When your script runs in the browser and hits require(), the browser tries to find a variable named require. It can’t, so it throws a reference error.
That’s why the same file can run fine on the server and fail in the browser. The file did not “break.” It just landed in a place where require() is not part of the runtime.
If you’re loading scripts with a plain tag, you’re in the most common failure zone. If you’re using a bundler, the error often means a dependency slipped through without being converted to browser-ready module code.
Taking “Require Is Not Defined” In JavaScript With A Simple Triage
Before you change code, identify the context. Two quick checks save a lot of guessing.
- Read The Stack Trace — Click the first line that points to your code, not a minified vendor chunk, and note the file name and line.
- Confirm Where It Runs — Ask if the failing code executes in a browser tab, a Node process, a test runner, or a bundler build step.
- Check How The File Is Loaded — Look for a plain
, an app entry file, or a tool command likevite,webpack, ornode.
Once you know the context, the fix becomes a choice, not a hunt.
Pick The Right Fix For Your Setup
Most people solve this error by switching to native modules in the browser or by letting a bundler translate CommonJS. Use the option that matches your project’s shape and your deadlines.
Browser Code With No Build Step
If your page loads JavaScript directly, treat the browser as the source of truth. The clean move is to use ES modules.
Modules also change how the browser resolves paths. Imports act like URLs, so bare names like 'lodash' won’t load unless a tool rewrites them or you use an import map. When testing, don’t open the page with file://. Use a simple local server so module requests return proper headers and errors point to the true file. You’ll see it in DevTools quickly.
- Switch To Type Module — Change your script tag to
so the browser parses it as a module. MDN notes that modules run when the server sends a JavaScript MIME type. Source - Replace Require With Import — Turn
const x = require('x')intoimport x from 'x'orimport {y} from 'x', matching what the package exports. - Export What You Use — Use
exportin files you want to import, and keep names consistent. MDN explains thattype="module"is what makesimportandexportvalid in the browser. Source - Add The Loader Script — Include the loader on the page before the code that calls
require(). - Match The Loader Syntax — AMD uses patterns like
require(['dep'], function (dep) {}), not Node’srequire('dep'). - Keep The Scope Small — Use this route for legacy pages, then plan a gradual shift to ES modules as files get touched.
- Prefer ESM Packages — If a library offers an ESM entry, use it. Many libraries publish both styles.
- Enable CommonJS Conversion — With Rollup, a CommonJS plugin can translate
require()calls into imports during the build. Reference - Move Requires Behind The Build — Keep
require()out of browser-facing code paths. If you must keep it, isolate it in a server file or a build-only script. - Use Import In ES Module Files — Swap
require()forimportwhen the file is an ES module. - Switch The File Back To CommonJS — Rename it to
.cjsor set the package type to CommonJS if that matches your codebase. - Use CreateRequire When Needed — Node can create a CommonJS-style loader inside an ES module with
module.createRequire()when you need a legacy package.
When A Loader Makes Require Work In A Page
There is one case where require() can run in a browser tab: when you add a loader library that defines it. RequireJS is the classic example. It uses the AMD module style, not CommonJS, so the syntax and behavior differ from Node’s require.
This can be a quick fix for older codebases that already use AMD. For new work, ES modules are usually easier to maintain because they are built into browsers and align with modern tooling.
Browser App With A Bundler
If you use Vite, Webpack, Rollup, or similar tools, your code can keep modern import syntax while the tool handles packaging. The error often points to a CommonJS-only dependency that didn’t get converted.
Node Code Or A Tool Running In Node
If the code runs under Node and you still see this error, you’re likely inside an ES module file. Node treats files as ES modules when you use .mjs or set "type": "module" in package.json. In that mode, require is not a global.
Quick Comparison Table
| Where The Code Runs | Why Require Fails | Most Reliable Fix |
|---|---|---|
| Browser script tag | No CommonJS loader exists | Use type="module" + import |
| Bundler dev server | Dependency stayed CommonJS | Convert CommonJS or swap package |
| Node ES module | ES modules lack global require | Use import or createRequire |
Common Triggers That Keep Bringing The Error Back
Fixing this once is easy. Keeping it from returning takes a small mental model: browsers load modules differently, and modern tools try to keep that model intact.
Copying Server Examples Into Front-End Files
Tutorials often show Node-style snippets with require(). If you paste them into a file that ships to the browser, the error is expected. Convert the snippet to ESM, or run it as a server script.
Mixing Module Systems Inside One Folder
If some files are ES modules and others are CommonJS, it’s easy to call require() from a file that no longer has access to it. Pick one system per package when you can, and be clear with file extensions.
Asset Imports That Used To Work In Webpack
In some Webpack setups, people used require('./image.png') as a shortcut. Tools like Vite expect import for assets or a static URL reference. When you migrate, that old pattern can surface as “require is not defined.”
Libraries That Ship Node-Only Entry Points
Some packages are meant for Node only. They may depend on built-in modules like fs or path. If such a package gets pulled into browser code, you might see “require is not defined” or a related error. In that case, swapping the package is often faster than trying to patch it.
Test Runners And Build Scripts
Some test setups run your code in a browser-like sandbox. Others run it in Node. If a test file is treated as an ES module, a plain require() will fail the same way it does in a browser. If a test runs in Node, importing a browser-only package can create its own chain of errors.
- Check The Runner Mode — Look for a setting that says the tests run in Node or in a browser simulator.
- Match The Module Style — Keep test files consistent with the rest of the package: ESM files use
import, CommonJS files userequire(). - Mock Browser-Only APIs — If a package expects
windowordocument, mock it in Node tests instead of forcing the package into the wrong place.
Step-By-Step Debugging When The Fix Isn’t Obvious
Sometimes the stack trace points into a vendor bundle and you can’t tell what triggered it. Use this routine to narrow it down without guesswork.
- Reproduce With A Clean Reload — Hard refresh the page and confirm the error appears from the same action each time.
- Search The Built Output — In your compiled files, search for
require(. If you find it, you’ve found the section that escaped conversion. - Trace The Import Chain — Start from your entry file and follow imports until you reach the file that contains
require(). - Check Package Entry Fields — Look at a dependency’s
package.jsonfor fields likemodule,main, orexports. A browser build should pick an ESM entry when available. - Run The Same File In Node — If it works in Node but fails in the browser, you’ve confirmed it’s a browser packaging issue, not broken logic.
That process is dull, yet it ends the confusion fast. You end up with one file or one package to change, not a fog of possibilities.
Small Habits That Prevent “Require Is Not Defined”
Once you’ve fixed the immediate error, a few habits keep your codebase steady across tools and runtimes.
- Default To ES Modules In New Files — Use
importandexportfor browser-facing code, since browsers run modules directly when loaded withtype="module". Source - Keep Server Code In A Separate Folder — A clear boundary reduces accidental bundling of Node-only files into the browser build.
- Scan Dependencies Before Shipping — When adding a library, check if it mentions browser use and offers an ESM build. If not, plan a fallback.
- Lock Down Lint Rules — A simple lint rule that flags
require()in client folders can catch the issue before it hits production. - Test A Production Build Locally — Dev servers can mask packaging quirks. A local build run catches “works on my machine” surprises.
Copy-Paste Checklist For Your Notes
When the message pops up again, run this list in order. It’s short on purpose.
- Locate The First Relevant Stack Line — Find the first stack frame that points to your source or your dependency list.
- Confirm Browser Or Node — Decide if the failing code executes in a tab or in a Node process.
- Pick The Matching Fix — Browser with no build step: use
type="module"and imports. Bundler: convert CommonJS or swap the package. Node ES module: use imports or createRequire. - Remove Require From Client Paths — Keep
require()out of files that ship to the browser. - Rebuild And Reload — Re-run the build, refresh, and confirm the console stays clean.
If you follow that flow, you’ll stop treating this error like a mystery. It becomes a quick signal that a module boundary got crossed.
