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

Conditional Import depending on Environment #1829

Closed
sinclairzx81 opened this issue Dec 7, 2021 · 4 comments
Closed

Conditional Import depending on Environment #1829

sinclairzx81 opened this issue Dec 7, 2021 · 4 comments

Comments

@sinclairzx81
Copy link

Hi, I'm just looking for bit of guidance on how to conditionally import node npm packages based on the JavaScript environment (either Node or the Browser). The package I'm trying to conditionally import is the ws WebSocket package.

When running as --platform node, things are fine. However when running --platform browser with --external ws specified, esbuild still seems to try resolve the ws package (albeit externally), even if the require('ws') call is wrapped in conditional block.

const IsomorphicWebSocket: typeof WebSocket = isBrowser() ? WebSocket : require('ws').WebSocket
//
//                       this should not execute in browser environments ^ 
       

Is there a way to have esbuild completely ignore the ws package when running --external ws? Any info on how to approach this in esbuild would be great.

@hyrious
Copy link

hyrious commented Dec 7, 2021

--external:ws, did you miss the : ?

@sinclairzx81
Copy link
Author

sinclairzx81 commented Dec 7, 2021

@hyrious Hi, I'm actually using the esbuild api directly as part of a build process. I think the issue may be that; while esbuild does exclude the external package from a bundle (which is ideal), it does still try to resolve the package, so in the ws case, I get the following error in the browser

Uncaught TypeError: Failed to resolve module specifier "ws". Relative references must start with either "/", "./", or "../".

This error is thrown before any of my code is run, suggesting it is part of the esbuild module resolver infrastructure. Ideally, id like to conditionally resolve ws (as per above example), such that no attempt to resolve ws is made at all.

Maybe there is a better way to handle this?

@hyrious
Copy link

hyrious commented Dec 7, 2021

It shouldn't happen. Does your isBrowser() return false?
Can you provide some reproduction steps?

@sinclairzx81
Copy link
Author

@hyrious Hi, false alarm 🤦‍♂️ Found the issue, but didn't turn out the be the isBrowser() function.

The package im currently trying to build includes both client and server implementations, so while the isBrowser() was working as expected on the client side, the call to resolve ws actually originated from the following import on the server end.

import { WebSocketServer } from 'ws' // nope

export class Service {
   ...
  public listen(port) {
     const wss = new WebSocketServer({ port })
  }
}

Which I've temporarily resolved with...

import type { WebSocketServer } from 'ws' // fix

export class Service {
   ...
  public listen(port) {
        const WsWebSocketServer = require('ws').WebSocketServer as typeof WebSocketServer
        const wss = new WsWebSocketServer({ port })
  }
}

I'm not sure I want the server implementation included in the client code, but this workaround does solve the issue in the interim.

Looks like esbuild is working as expected here, so will close off this issue. Thanks for your help!
S

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

2 participants