Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🐞] Defining and calling $server() function inside onClick$ causes Error: Dynamic require of "_.js" is not supported #5495

Open
linkfang opened this issue Nov 28, 2023 · 13 comments
Assignees
Labels
COMP: optimizer TYPE: bug Something isn't working VERSION: after next major Features we'd want to add after the next version is done

Comments

@linkfang
Copy link
Contributor

Which component is affected?

Qwik Runtime

Describe the bug

Hi,

I am defining a server function inside an onClick event handler and call it below the definition.

import { component$ } from "@builder.io/qwik";
import { server$ } from "@builder.io/qwik-city";

export default component$(() => {
  return (
    <button
      onClick$={() => {
        const serverFn = server$(() => console.log('Hi from server'));
        serverFn();
      }}
    >
      Say Hi!
    </button>
  );
});

In dev mode, everything works perfectly.

But in prod mode, I will get a POST error POST http://localhost:4173/?qfunc=n4X1sOI0zW0 500 (Internal Server Error) with error message saying Error: Dynamic require of "_.js" is not supported.

I was expecting no error, because dev mode works fine and what I did aligns with what Miško did in this video

I found a solution to this issue that might help finding the root cause or a fix.
Basically add another $ to wrap the function assigned to onClick$. But I guess this is not needed as onClick$ should be sufficient already, right? Anyways, hope this helps on debugging, thanks!

    <button
      onClick$={$(() => {
        const serverFn = server$(() => console.log('Hi from server'));
        serverFn();
      })}
    >
      Say Hi!
    </button>

Thanks!

Reproduction

https://stackblitz.com/edit/qwik-starter-qmzrws?file=src%2Froutes%2Findex.tsx

Steps to reproduce

  1. After open the link, the app should be running in dev mode by default
  2. The two buttons work great. Click them and the messages will be shown in terminal
  3. Stop the app and run it in prod mode by npm run preview
  4. The 2nd button still works, but the 1st button doesn't. After click the 1st button, some error messages will be shown in inspect - console
    image

System Info

System:
    OS: Windows 11 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
    Memory: 2.63 GB / 15.60 GB
  Binaries:
    Node: 20.9.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (119.0.2151.72)
    Internet Explorer: 11.0.22621.1

Additional Information

No response

@linkfang linkfang added STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working labels Nov 28, 2023
@mhevery
Copy link
Contributor

mhevery commented Nov 29, 2023

OK, that is very bizarre. Thank you for a simple repro.

@sarat1669
Copy link

Any update on this?

@PatrickJS
Copy link
Member

PatrickJS commented May 5, 2024

the workaround is just to make sure the functions have $ wrap around them. looking at the build it looks like the server$ is not being output correctly in the server build. @mhevery this seems like an optimizer issue. will this be an issue in v2?

I made my own repro repo with latest qwik
https://github.com/PatrickJS/qwik-error-dynamic-js-server-jwerqd

@PatrickJS
Copy link
Member

image

@wmertens it looks like the server$ output is not working unless the handler is wrap in $

this is the output when the handler is wrap in $
image

@PatrickJS
Copy link
Member

PatrickJS commented May 5, 2024

we probably use eslint to require $ if server$ (or any other $ is being used) for now. This works correctly with one server$ but once you have more than one then it breaks

@PatrickJS
Copy link
Member

added this to the docs for now 48abd15

@PatrickJS PatrickJS closed this as not planned Won't fix, can't repro, duplicate, stale May 7, 2024
@PatrickJS PatrickJS reopened this May 7, 2024
@PatrickJS PatrickJS added COMP: optimizer and removed STATUS-1: needs triage New issue which needs to be triaged labels May 7, 2024
@wmertens
Copy link
Member

I missed this. This is still a problem in v2 I expect.
I'll take a look this week

@PatrickJS
Copy link
Member

yeah I'm fairly certain it's optimizer issue

@genki
Copy link
Contributor

genki commented Jun 22, 2024

I have faced this issue on the production env at the version 1.5.6-dev20240611011722
It doesn't occured in dev mode. It has been solved by wrapping by the $

@wmertens
Copy link
Member

Ok the reason is this: onClick$ will convert the handler to a noopQrl on the server because it can never be called.

However, this happens before the handler is scanned for any other qrls, and so it misses the server$.

The fix is therefore to still process noopQrls to check if there are any server$ calls in there.
However, this needs some care, it's like a double negative, we will now need a list of functions to keep vs a list to convert to noop. This is especially important to get right, to avoid importing DOM-related librairies.

So I'm wondering if we should even support this, and if the eslint rule shouldn't be done instead? @mhevery ?

@PatrickJS
Copy link
Member

@wmertens we should support this because calling server$ in onClick$ is used in all examples of server$ and it's the main use-case. Is there any way to process server$ before we convert to noopQrls or just have the optimizer convert everything to $ then it will work correctly? I think eslint is just a workaround until it's automated correctly

@linkfang
Copy link
Contributor Author

linkfang commented Jul 9, 2024

@wmertens we should support this because calling server$ in onClick$ is used in all examples of server$ and it's the main use-case. Is there any way to process server$ before we convert to noopQrls or just have the optimizer convert everything to $ then it will work correctly? I think eslint is just a workaround until it's automated correctly

Hi @PatrickJS , I just double checked the bug, it only happens when I define the server function inside onClick. So, if I define the server function outside of it, then it will work on both dev and prod. Please check the updated repro here: https://stackblitz.com/edit/qwik-starter-uqskwo?file=src%2Froutes%2Findex.tsx

When run npm run preview, only the 1st button will have the error (works in dev, has error in prod), both the 2nd one (defining the server function inside onClick with an extra $) and the 3rd one (defining the server function outside of the onClick and only call it inside) work fine on both dev and prod.

So, I think using eslint or something to force the user to define the server function outside of onClick is fine to me as a quick fix.

@maiieul maiieul added the VERSION: after next major Features we'd want to add after the next version is done label Aug 17, 2024
@wmertens
Copy link
Member

status: this would be solved by #6871 combined with adding if (false) {} around qrls that will be removed. This way they will be processed and other qrls will be discovered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
COMP: optimizer TYPE: bug Something isn't working VERSION: after next major Features we'd want to add after the next version is done
Projects
Status: Backlog
Development

No branches or pull requests

7 participants