reactjs Nextjs urql订阅交换导入问题

icnyk63a  于 2023-01-25  发布在  React
关注(0)|答案(2)|浏览(133)

由于导入问题,我无法使urql subscriptionsNextJS一起工作。
基本上我使用的是在urql文档推荐的graphql-ws库,需要ws实现库(例如:'ws')。当i import WebSocket from 'ws'时,我得到以下错误:Module not found: Can't resolve 'net'

import { createClient, defaultExchanges, subscriptionExchange, Client } from 'urql';
import { createClient as createWSClient } from 'graphql-ws';
import WebSocket from 'ws'; // <-- This causes the error

export const createUrqlClient = (): Client => {
  const wsClient = createWSClient({
    url: 'ws://xxx/graphql',
    webSocketImpl: WebSocket,
  });

  const client = createClient({
    url: 'http://xxx/graphql',
    exchanges: [
      ...defaultExchanges,
      subscriptionExchange({
        forwardSubscription: operation => ({
          subscribe: sink => ({
            unsubscribe: wsClient.subscribe(operation, sink),
          }),
        }),
      }),
    ],
  });

  return client;
};

我尝试了nextjs动态导入,这两个都不工作,以及:

const WebSocket = dynamic(() => import('ws'), { ssr: false });
const WebSocket = dynamic(() => import('ws').then(module => module.default), { ssr: false });

我还尝试修改next.config.js中的webpack配置,使其完全不捆绑这些库:

webpack: (config, { isServer }) => {
  if (!isServer) {
    config.resolve.fallback = {
      child_process: false,
      process: false,
      fs: false,
      util: false,
      http: false,
      https: false,
      tls: false,
      net: false,
      crypto: false,
      path: false,
      os: false,
      stream: false,
      zlib: false,
      querystring: false,
      events: false,
      'utf-8-validate': false,
      bufferutil: false,
    };
  }
  return config;
},

但是我得到了这些错误:

./node_modules/ws/lib/validation.js
Module not found: Can't resolve 'utf-8-validate' in '/home/danko/app/node_modules/ws/lib'
warn  - ./node_modules/ws/lib/buffer-util.js
Module not found: Can't resolve 'bufferutil' in '/home/danko/app/node_modules/ws/lib'

如果我也将'utf-8-validate': falsebufferutil: false添加到cfg,我会得到此错误:

TypeError: Class extends value undefined is not a constructor or null

所以基本上没有什么工作正常,然后你可以看到...
这有多难,我不可能是唯一一个使用urql订阅nextjs的人,希望有人能帮我这个忙。谢谢!

h6my8fg2

h6my8fg21#

基本上正如我所想,impl是不需要的,因为原生html5 WebSocket可以使用,问题是垃圾的nextjs与它的服务器端的东西。
typeof window !== 'undefined'是工作代码时,我基本上不使用这种交换:

import { createClient, dedupExchange, cacheExchange, subscriptionExchange, Client, Exchange } from 'urql';
import { multipartFetchExchange } from '@urql/exchange-multipart-fetch';
import { createClient as createWSClient } from 'graphql-ws';

export const createUrqlClient = (): Client => {
  const graphqlEndpoint = process.env!.NEXT_PUBLIC_GRAPHQL_ENDPOINT as string;
  const graphqlWebsocketEndpoint = process.env!.NEXT_PUBLIC_GRAPHQL_WS_ENDPOINT as string;

  let exchanges: Exchange[] | undefined = [dedupExchange, cacheExchange, multipartFetchExchange];

  if (typeof window !== 'undefined') {
    const wsClient = createWSClient({
      url: graphqlWebsocketEndpoint,
    });

    const subExchange = subscriptionExchange({
      forwardSubscription: operation => ({
        subscribe: sink => ({
          unsubscribe: wsClient.subscribe(operation, sink),
        }),
      }),
    });

    exchanges.push(subExchange);
  }

  const client = createClient({
    url: graphqlEndpoint,
    requestPolicy: 'cache-and-network',
    exchanges,
    fetchOptions: () => ({
      credentials: 'include',
    }),
  });

  return client;
};
tgabmvqs

tgabmvqs2#

@dankobgd
我也有同样的问题,你的回答帮了我。我简化了一点,效果很好

export const client = (): Client => {
  let exchanges: Exchange[] = [...defaultExchanges]

  if (typeof window !== 'undefined') {
    const wsClient = createWSClient({
      url: wsUrl,
    })

    const subExchange = subscriptionExchange({
      forwardSubscription: (operation) => ({
        subscribe: (sink) => ({
          unsubscribe: wsClient.subscribe(operation, sink),
        }),
      }),
    })
    exchanges.push(subExchange)
  }

  return createClient({
    url,
    exchanges,
  })
}

相关问题