Server Actions make server-side imports leak into client-side code and cause bundler errors
Answered
Asian black bear posted this in #help-forum
Asian black bearOP
Error encountered in Next.js 15.0.3 and 15.0.4, with Discord.js package.
Link to the code that reproduces this issue
https://github.com/vitallygolovanov/next-15_discord-js-sa-bug
To Reproduce
1. Install dependencies with npm i
2. Run the app in development mode (next dev)
3. Go to https://localhost:3000
4. See console error saying:
5. Comment out the two marked lines in
Current vs. Expected behavior
Server-side imports seem to be included in the client-side bundle and causing the error. They shouldn't.
Provide environment information
Additional context
I tried passing the server action to the client component as a property from the parent server component to avoid importing the module with the server actions into the client component directly, same result.
Link to the code that reproduces this issue
https://github.com/vitallygolovanov/next-15_discord-js-sa-bug
To Reproduce
1. Install dependencies with npm i
2. Run the app in development mode (next dev)
3. Go to https://localhost:3000
4. See console error saying:
./node_modules/.pnpm/@discordjs+ws@1.1.1/node_modules/@discordjs/ws/dist/index.js:571:54
Module not found: Can't resolve 'zlib-sync'
569 |
570 | // src/ws/WebSocketShard.ts
> 571 | var getZlibSync = (0, import_util2.lazy)(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
| ^^^^^^^^^^^^^^^^^^^
572 | var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
573 | WebSocketShardEvents2["Closed"] = "closed";
574 | WebSocketShardEvents2["Debug"] = "debug";
https://nextjs.org/docs/messages/module-not-found
5. Comment out the two marked lines in
src/lib/discord/discord.actions.ts
, and the error goes away.Current vs. Expected behavior
Server-side imports seem to be included in the client-side bundle and causing the error. They shouldn't.
Provide environment information
Operating System:
Platform: win32
Arch: x64
Version: Windows 10 Home Single Language
Available memory (MB): 24512
Available CPU cores: 8
Binaries:
Node: 20.17.0
npm: 10.8.2
Yarn: N/A
pnpm: 9.11.0
Relevant Packages:
next: 15.0.3 // Latest available version is detected (15.0.3).
eslint-config-next: N/A
react: 19.0.0-rc-66855b96-20241106
react-dom: 19.0.0-rc-66855b96-20241106
typescript: 5.7.2
discord.js: 14.16.3,
Next.js Config:
output: N/A
Additional context
I tried passing the server action to the client component as a property from the parent server component to avoid importing the module with the server actions into the client component directly, same result.
56 Replies
u cant call a server function on client
u can call a server action on client, which will require u to either use a form or invoke it manually
this is wrong
this is the way, read this and u good
@gin your use of "server actions" is wrong
Asian black bearOP
Where can I read up on that? Because the docs (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#event-handlers) say I should be able to.
While it's common to use Server Actions within <form> elements, they can also be invoked with event handlers such as onClick. For example, to increment a like count.
'use client'
import { incrementLike } from './actions'
import { useState } from 'react'
export default function LikeButton({ initialLikes }: { initialLikes: number }) {
const [likes, setLikes] = useState(initialLikes)
return (
<>
<p>Total Likes: {likes}</p>
<button
onClick={async () => {
const updatedLikes = await incrementLike()
setLikes(updatedLikes)
}}
>
Like
</button>
</>
)
}
then do what the documenation says
u have to await the function in your onclick handler
Asian black bearOP
Yeah, I noticed that.
Updated my code to wrap in the async function, still the same error:
My original code had it implemented that way, just made a mistake when making the minimal example.
Updated my code to wrap in the async function, still the same error:
"use client";
import { testDiscord_action } from "@/lib/discord/discord.actions";
export default function DiscordButton() {
return (
<button
className="discord-button"
onClick={async () => {
await testDiscord_action();
}}
>
<span>Test Discord Action</span>
</button>
);
}
My original code had it implemented that way, just made a mistake when making the minimal example.
hnm
let me clone and check
this is new for me aswell
for next v14 this was not the way to trigger actions
@gin for next v14 this was not the way to trigger actions
Asian black bearOP
Thank you. It totally was in next 14, I used to use it in an older project without any issues. It didn't use discord.js though.
It's just harder to find at the bottom of the docs page. And might have appeared in the later subversions of 14.
i might have found the solution
Answer
import {REST} from "@discordjs/rest";
import {Routes} from "discord-api-types/v10";
npm install @discordjs/rest discord-api-types
use this package
this eliminates the installation of zlib-sync
and configuration of webpack
@gin https://www.armannotes.com/2024/02/12/zlib-error-nextjs-server-actions/
Asian black bearOP
I did try this. It works, but feels liek sweeping the issue under the rug. Doesn't this solution just make the bundler successfully bundle the imports it shouldn't in the first place? I've got some sensitive code in there in the full project, so I wanted to avoid it bundling.
Should've mentioned it earlier. Sorry, spent too much time on this, started forgetting everything I tried.
Should've mentioned it earlier. Sorry, spent too much time on this, started forgetting everything I tried.
it doesnt address your issue
just ignore that and do the thing i told u above
and remove zlib-sync, node-loader and webpack config
Asian black bearOP
Tried it just now to confirm it works. It does. But I have two issues with this approach:
1. According to the most recent Discord.js docs I could find, since September 7 this year they're including
I might be getting it wrong, but this language implies they're moving away from separate packages and combining everything together in
2. It still just avoids causing the error, but not bundling the code. I think I at least should report this as an issue to the Next.js team to verify with them if it's just me, or there's something here.
1. According to the most recent Discord.js docs I could find, since September 7 this year they're including
@discord/rest
in the main discord.js
package. (https://discordjs.guide/additional-info/changes-in-v14.html#before-you-start)If you previously had @discordjs/builders, @discordjs/formatters, @discordjs/rest, or discord-api-types manually installed, it's highly recommended that you uninstall the packages to avoid package version conflicts.
I might be getting it wrong, but this language implies they're moving away from separate packages and combining everything together in
discord.js
. Which doesn't sound right. What do you think on this?2. It still just avoids causing the error, but not bundling the code. I think I at least should report this as an issue to the Next.js team to verify with them if it's just me, or there's something here.
discord.js is a big package
the internal logic is probably conflicting with the compilation system from next
server components arent really pure node
Asian black bearOP
I see the benefits from not using the whole
discord.js
in the next app. I'll probably stick to this solution for now.Thank you.
no problem :)
Asian black bearOP
Could you advise on where should I post this issue to notify the next.js team?
uhm
if u really think its a issue, u should open a issue on github
btw, addressing your concerns of code leaking into clientside
this log is only executed on the server
this log is only executed on the server
its 100% on the server
if u are still not sure, u can manually check the static files bundled after next build 😂 (put a comment or a console.log in your code and check for that in the bundle)
@Asian black bear I see the benefits from not using the whole `discord.js` in the next app. I'll probably stick to this solution for now.
u can mark my answer as solution :)
Asian black bearOP
I'm not sure how to do that from discord. There are multiple messages here. Do I need to make the public profile?
@gin its 100% on the server
Asian black bearOP
Got it
@gin as u see in the stack
Asian black bearOP
AWESOME. Thanks!