remix
remix copied to clipboard
Uncaught Error: Dynamic require of "fs/promises" is not supported - when importing json from @remix-run/node
What version of Remix are you using?
1.7.1
Steps to Reproduce
import { json } from "@remix-run/node";
export default function SomePage(props) {
return <div>
Page
</div>
}
Then yarn dev.
Expected Behavior
No errors in developer console.
Actual Behavior
Error in developer console:

package.json
{
"private": true,
"sideEffects": false,
"scripts": {
"build": "remix build",
"dev": "remix dev",
"start": "remix-serve build"
},
"dependencies": {
"@remix-run/node": "^1.7.1",
"@remix-run/react": "^1.7.1",
"@remix-run/serve": "^1.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "^1.7.1",
"@remix-run/eslint-config": "^1.7.1",
"eslint": "^8.20.0"
},
"engines": {
"node": ">=14"
},
"packageManager": "[email protected]"
}
Yarn and Node
- node version: 18.9.0
- Yarn: 3.x
NB. I tried creating the project with using Yarn 1.x and it worked fine. The problem appears after migrating to yarn 3.x
Might be related:
https://github.com/yarnpkg/berry/issues/638#issuecomment-1124629341
Looks like Yarn 3.x supports ESM module loading. So I tried the following in my .yarnrc.yml file, following the recommendations from the link above:
yarnPath: .yarn/releases/yarn-3.2.3.cjs
pnpEnableEsmLoader: true
nodeLinker: "pnp"
But this did not help.
So, the thread above makes me think that yarn 3.x should work with Remix. But it does not. I'm wondering if this is Remix or Yarn issue?
The only workaround that works for me is to rollback to using nodeLinker: node-modules.
Just hit this. You need to import things from @remix-run/cloudflare instead
@mwood23 I am not using cloudflare.
@meglio I hit this too... A temp workaround is just change how "fs/promises" imports...
You need to change this row in file
node_modules/@remix-run/node/dist/upload/fileUploadHandler.js:
var fs = require('fs');
-var promises = require('fs/promises');
+var promises = require('fs').promises;
var os = require('os');
it is at the top of the file... but still annoys...
Explanation is on Stackoverflow So... a fix for devs must be just updating a node version... or change how they import promises from fs...
So... a fix for devs must be just updating a node version... or change how they import promises from fs...
Could you explain this part, please, @mkikets99 ? What devs do you mean - the Remix devs? If so, what node version do you mean? I am the package user and my Node version is 18.9, but it does not prevent the error from happening.
So... a fix for devs must be just updating a node version... or change how they import promises from fs...
Could you explain this part, please, @mkikets99 ? What devs do you mean - the Remix devs? If so, what node version do you mean? I am the package user and my Node version is 18.9, but it does not prevent the error from happening.
Yes, i meant the Remix Devs. But... i think on TS it will be better to use something like
import { promises as fspromises } from "fs";
rather than
import fspromises from "fs/promises"
because that is causing the error...
Node changed the way how "sub-modules" are imported...
And fs/promises are now a part of fs... maybe from Node v12...
and Node trying to not use the "path-requirement" for integrated values...
But TypeScript skipped this part... and allowing to use path import while Node doesn't like it
I may rewrite that file on TS... a bit later...
Now i just added a script in postinstall section of scripts...
cat ./node_modules/@remix-run/node/dist/upload/fileUploadHandler.js | sed -e \"s/var promises = require('fs\\/promises');/var promises = require('fs').promises;/g\" | tee ./node_modules/@remix-run/node/dist/upload/fileUploadHandler.js >/dev/null
you can try run this command in your project root folder and this must solve it... Maybe in 2-3 days ill make a PR with fix...
In my case, working with sessions, I had not specifically scoped my module to the server, e.g.: session.server.ts -- so the module had leaked to the client producing the titled error.
So, at the end of the day, is it something that Remix can/going to fix/improve?
Also running into this problem, any status updates?
also hit this problem
This problem happened to me because server-only code was in the client.
I had to re-name the server-only files with .server extension and it worked!
I though Remix would do a better job at distinguishing the server/client JS bundles.
Remix requires Node v14 or newer, so changing internal code should not be necessary since importing from fs/promises was added in Node v14(click on "history" dropdown to see it).
As @ErlanBelekov points out, this is likely due to server code being incorrectly included in your browser/client bundle.
In the example from @meglio :
import { json } from "@remix-run/node";
export default function SomePage(props) {
return <div>
Page
</div>
}
The @remix-run/node import should be treeshaken from the browser bundle.
I was facing the same issue.
Solution that worked for me : moved createCookie helper to .server file
also facing it
@alexpunct like the others, move the import into a .server file and re-export it. I think esbuild has issues tree-shaking node internal packages. I typically have a node.server file that I re-export from.
@kiliman We have been struggling with this for a while. Could you provide a brief example of how to import and re-export this?
// app/libs/node.server.ts
import path from 'node:path';
export * as fs from 'node:fs';
export * as fsp from 'node:fs/promises';
export { path };
// route.tsx
import { fs } from '~/libs/node.server'