Fixing "Module not found: Can't resolve 'fs'" in Next.js
The "Module not found: Can't resolve 'fs'" error is a common issue that occurs when Node.js-specific modules like fs
(file system) are incorrectly used in browser/client-side code in Next.js applications.
Understanding the Problem
Next.js uses a hybrid rendering approach that allows both server-side and client-side execution. Node.js modules like fs
, path
, and crypto
are only available in server-side environments and cannot run in browsers.
WARNING
Attempting to use Node.js modules directly in client components will always fail, as browsers don't have access to the Node.js runtime environment.
Root Causes
This error typically occurs when:
- Server-side code is mistakenly used in client components
- Mixed server/client modules are imported in client code
- Third-party libraries depend on Node.js modules
- Incorrect Webpack configuration
Best Solution: Proper Code Separation
The most maintainable approach is to properly separate server and client code according to Next.js conventions.
Use Data Fetching Methods
Only use Node.js modules within Next.js data fetching methods:
// pages/my-page.js (or app directory equivalent)
export async function getServerSideProps() {
const fs = require('fs');
const fileContent = fs.readFileSync('/path/to/file', 'utf8');
return {
props: {
content: fileContent
}
};
}
export default function MyPage({ content }) {
// Client-side component
return <div>{content}</div>;
}
Server Components (Next.js 13+)
With the App Router, use Server Components for server-side operations:
// app/my-page/page.js
import { promises as fs } from 'fs';
export default async function MyPage() {
// This runs on the server only
const file = await fs.readFile(process.cwd() + '/data/file.txt', 'utf8');
return (
<div>
<h1>File Content</h1>
<pre>{file}</pre>
</div>
);
}
Isolate Server-Only Code
Create separate modules for server-only code:
// lib/server-utils.js (server-only)
import { promises as fs } from 'fs';
export async function readDataFile() {
return fs.readFile('./data.json', 'utf8');
}
// lib/client-utils.js (client-safe)
export function formatData(data) {
return JSON.parse(data);
}
Use server-only
Package
For better code organization, mark server-only files explicitly:
npm install server-only
// lib/server-data.js
import "server-only";
import { promises as fs } from 'fs';
export async function getServerData() {
const data = await fs.readFile('./data.json', 'utf8');
return JSON.parse(data);
}
Webpack Configuration Solutions
If you must use Node.js modules in specific edge cases, modify your next.config.js
:
Webpack 5 Configuration
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
fs: false,
path: false,
os: false,
// Add other Node.js modules as needed
};
}
return config;
},
};
Handling Specific Node.js Modules
// next.config.js
module.exports = {
webpack: (config, { nextRuntime }) => {
if (nextRuntime !== "nodejs") {
const { IgnorePlugin } = require("webpack");
const ignoreNode = new IgnorePlugin({ resourceRegExp: /node:.*/ });
config.plugins.push(ignoreNode);
}
return config;
},
};
Common Scenarios and Fixes
Third-Party Libraries
Some libraries may have Node.js dependencies. For example, if using bcrypt
, switch to bcryptjs
:
npm uninstall bcrypt
npm install bcryptjs
import bcrypt from "bcryptjs"; // Instead of 'bcrypt'
Lingui Library Issue
If using Lingui macros, configure SWC plugin:
// next.config.js
module.exports = {
experimental: {
swcPlugins: [["@lingui/swc-plugin", {}]],
},
};
Edge Runtime Configuration
Ensure you're not accidentally using Edge Runtime with Node.js modules:
// Remove this if you need Node.js modules
export const runtime = 'edge'; // Change to 'nodejs' or remove
Debugging Tips
- Check for unused imports - Remove any unused Node.js module imports
- Verify module usage - Ensure Node.js modules are only used in server contexts
- Review third-party dependencies - Check if any dependencies require Node.js modules
- Inspect bundle - Use
npm run build
to see where the error occurs
DANGER
Avoid the browser
field hack in package.json as it only suppresses errors without fixing the underlying issue:
{
"browser": {
"fs": false,
"path": false
}
}
Conclusion
The "Module not found: Can't resolve 'fs'" error is fundamentally a code organization issue. The best solution is to:
- Separate server and client code appropriately
- Use Next.js data fetching methods for server-side operations
- Leverage Server Components in Next.js 13+
- Mark server-only files with the
server-only
package - Only use Webpack configuration as a last resort
By following these patterns, you'll create more maintainable Next.js applications that properly leverage both server and client capabilities.