Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

apollo-link-ws loads backend modules when using it in the browser #1274

Open
markpradhan opened this issue May 19, 2020 · 1 comment
Open

Comments

@markpradhan
Copy link

markpradhan commented May 19, 2020

Expected Behavior
apollo-link-ws package does not crash whole web app.

Actual Behavior
apollo-link-ws crashes app due to backed packages being required.

A simple reproduction
Use the mentioned package's export "WebSocketLink" in frontend code.

Monkey patch for front end, will break backend ofcourse
In node_modules/apollo-link-ws/lib/webSocketLink.js change:
var subscriptions_transport_ws_1 = require("subscriptions-transport-ws");
to:
var subscriptions_transport_ws_1 = require("subscriptions-transport-ws/browser/client.js");

Version
apollo-link-ws 1.0.19

How i eventually fixed it

I just created a file with this content (fetched from the apollo-link-ws repo and removed some types and updated the import path for 'subscriptions-transport-ws', https://raw.githubusercontent.com/apollographql/apollo-link/master/packages/apollo-link-ws/src/webSocketLink.ts)

import { ApolloLink, Operation, FetchResult, Observable } from 'apollo-link'

import { SubscriptionClient } from 'subscriptions-transport-ws/dist/client'

export class WebSocketLink extends ApolloLink {
  private subscriptionClient

  constructor(paramsOrClient) {
    super()

    if (paramsOrClient instanceof SubscriptionClient) {
      this.subscriptionClient = paramsOrClient
    } else {
      this.subscriptionClient = new SubscriptionClient(
        paramsOrClient.uri,
        paramsOrClient.options,
        paramsOrClient.webSocketImpl,
      )
    }
  }

  public request(operation: Operation): Observable<FetchResult> | null {
    return this.subscriptionClient.request(operation) as Observable<FetchResult>
  }
}
@michaelyuen
Copy link

Encountered this as well. I can provide another potential solution and more context.

(Potential) Alternate Solution - Webpack
Check your webpack config's resolve.mainFields. Reference

When the target property is set to webworker, web, or left unspecified:

module.exports = {
  resolve: {
    mainFields: ['browser', 'module', 'main']
  }
};

When referenced against subscriptions-transport-ws, webpack should use dist/client.js.
In my case, the webpack config defined a different order in which main was preferred. Changing that resolved the issue.

Background

Tracked down this line causing errors: import { WebSocketLink } from 'apollo-link-ws'.
My terminal has a bunch of different errors in the format of:

ERROR in ./node_modules/graphql/index.mjs 42:0-48:205
    Can't reexport the named export 'visitInParallel' from non EcmaScript module (only default export is available)

and then in the browser:

Error: Cannot find module 'tls' at webpackMissingModule

I tried the above solution, rewriting the class and importing from 'subscriptions-transport-ws/dist/client' directly, and it works. But I was unsatisfied.

The reason I was unsatisfied is because I have other implementations on top of both create react app and nextjs that import apollo-link-ws the same way without issue. I spent a while debugging before noticing the package.json's browser property and checking my webpack config.

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

No branches or pull requests

2 participants