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

unable to use server on node.js #20

Closed
saknarak opened this issue Apr 5, 2023 · 12 comments
Closed

unable to use server on node.js #20

saknarak opened this issue Apr 5, 2023 · 12 comments

Comments

@saknarak
Copy link
Contributor

saknarak commented Apr 5, 2023

When use in browser there is no problem to use client
But when I try to use in node.js, client was not found

What should I do to skip import client that I never use

both node.js 18 and 19
step to reproduce

  1. npm init -y
  2. npm install @passwordless-id/webauthn
  3. change package.json add type: 'module'
  4. create index.js
import { server } from '@passwordless-id/webauthn'
console.log(server)
  1. run node index.js
  2. error occurs
node:internal/errors:490
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.\node_modules\@passwordless-id\webauthn\dist\esm\client' imported from .\node_modules\@passwordless-id\webauthn\dist\esm\index.js
    at new NodeError (node:internal/errors:399:5)
    at finalizeResolution (node:internal/modules/esm/resolve:231:11)
    at moduleResolve (node:internal/modules/esm/resolve:850:10)
    at defaultResolve (node:internal/modules/esm/resolve:1058:11)
    at nextResolve (node:internal/modules/esm/hooks:654:28)
    at Hooks.resolve (node:internal/modules/esm/hooks:309:30)
    at ESMLoader.resolve (node:internal/modules/esm/loader:312:26)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:172:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v19.8.1
@dagnelies
Copy link
Collaborator

dagnelies commented Apr 5, 2023

Good point...

I used full/partial imports in other projects, both server and client side, and since it worked out of the box I assumed it would work for other vanilla projects too ...but apparently not, thanks for noticing/reporting it with the clear minimal example.

I guess it has something to do with how it is bundled and how module resolution works. It's more difficult than I though to make make it compatible with browser/typescript/node/ all at once ...somehow they all import slightly differently. Dammit.

@dagnelies
Copy link
Collaborator

I fear I have to split it into different builts :/

@saknarak
Copy link
Contributor Author

saknarak commented Apr 5, 2023

Now I can find the root cause and work around

In node.js, javascript type=module,
import file need to have .js extension

from

export * as client from './client';
export * as server from './server';
export * as parsers from './parsers';
export * as utils from './utils';

change to

export * as client from './client.js';
export * as server from './server.js';
export * as parsers from './parsers.js';
export * as utils from './utils.js';

and many other files in dist/esm too
now is working

@dagnelies
Copy link
Collaborator

I noticed that too... I'd have to change the sources though and verify it doesn't break for typescript/vite/cloudflare workers since I use these "in production" for https://passwordless.id

@niktek
Copy link

niktek commented Apr 6, 2023

Can confirm with change of exports to .js that importing client now works with Vite/Svelte Kit using TS.

@dagnelies
Copy link
Collaborator

dagnelies commented Apr 7, 2023

I already have the problem that the jest tests fail when importing with ".js" extensions:

Cannot find module './client.js' from 'src/index.ts'
...
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js

@dagnelies
Copy link
Collaborator

dagnelies commented Apr 7, 2023

To sum it up...

  • half of the tools/environments prefer imports without file extension
  • the other half with file extensions
  • from a stackoverflow answer, I read typescript is strongly against "import rewriting" so a double build seems not an option.

It's funny how the js ecosystem is "destandardized", or I'm missing something. Every lib I look at seems to do things slightly differently so I don't know the "right way" to do it.

As far as I could see, imports without file extension seem more widespread... And feels more natural to me. It feels weird to write "import ...js" to actually import a "ts" file.

Checklist for a successful change, it should at least work with:

  • browser
  • node
  • cloudflare workers
  • vite
  • jest tests

Perhaps instead of changing file extensions, it may make sense to split it into separate client and server builts, each minified and bundled... But I think it might negatively affect the size of imported code for partial imports.

@niktek
Copy link

niktek commented Apr 7, 2023

Yeah, it's quite a bit to work through. Also keep in mind that some frameworks will be importing client on the server as part of SSR'ing content out, which means that you will also need checks like if (typeof window === 'undefined') return false; at Line 8 of src/clients.ts as it can't be assumed that window exists either.

@niktek
Copy link

niktek commented Apr 7, 2023

Also, you could run the tests on the emitted JS (as mentioned here https://learn.microsoft.com/en-us/visualstudio/javascript/unit-testing-javascript-with-visual-studio?view=vs-2022&tabs=mocha or use something like ts-jest as covered here https://www.testim.io/blog/typescript-unit-testing-101/

@dagnelies
Copy link
Collaborator

Regarding the window thing, it's in a method to detect the browser's capabilities at runtime, so it doesn't make sense to use it for SSR, as stated in #19. The ts-jest lib is already used in this project, and targeting the emitted js wouldn't solve the issue AFAIK.

I digged a bit and it seems an issue that many people faced. Among others evanw/esbuild#622 ...and the workarounds are like the wild west to insert the extension in emitted files.

@dagnelies
Copy link
Collaborator

microsoft/TypeScript#16577 would rather be the curlpit.

@dagnelies
Copy link
Collaborator

I'll try with https://github.com/AyogoHealth/jest-ts-webcompat-resolver later on...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants