web3-react icon indicating copy to clipboard operation
web3-react copied to clipboard

Dynamic importing providers might cause `@ethersproject/providers not available`

Open gordomium opened this issue 2 years ago • 7 comments

@ethersproject/providers not available seems like throws from https://github.com/NoahZinsmeister/web3-react/blob/main/packages/core/src/hooks.ts#L16.

Print the hidden error here, it's require is undefined. Here's the transformed code:

let DynamicProvider;
function importProvider() {
    return __awaiter(this, void 0, void 0, function* () {
        if (DynamicProvider === undefined) {
            try {
                const { Web3Provider } = yield Promise.resolve().then(() => __importStar(require('@ethersproject/providers')));
                DynamicProvider = Web3Provider;
            }
            catch (_a) {
                console.debug('@ethersproject/providers not available');
                DynamicProvider = null;
            }
        }
    });
}

It's an inline-require for lib users.
For some of frontend pack tools, inline-require is a trouble I think. Keep the dynamic import for shipped code might be better?

Or just leave the choose to lib user might be better.

Key Files

package.json

...
"dependencies": {
    "@ethersproject/providers": "^5.6.8",
    "@web3-react/core": "8.0.30-beta.0",
    "@web3-react/gnosis-safe": "8.0.3-beta.0",
    "@web3-react/metamask": "8.0.24-beta.0",
    "@web3-react/network": "8.0.23-beta.0",
    "@web3-react/walletconnect": "8.0.31-beta.0",
    ...
  },
...

src/index.ts

import { initializeConnector, Web3ReactProvider } from '@web3-react/core';
import { MetaMask } from '@web3-react/metamask';
import { Network } from '@web3-react/network';
import { GnosisSafe } from '@web3-react/gnosis-safe';
import React from 'react';
import ReactDOM from 'react-dom';


export const defaultNetwork: {
	chainId: number;
	chainName: string;
	rpcUrls: string[];
	nativeCurrency: {
		name: string;
		symbol: string;
		decimals: 18;
	};
	blockExplorerUrls: string[];
} = {
	chainId: 1,
	chainName: 'Ethereum Mainnet',
	rpcUrls: ['https://cloudflare-eth.com'],
	nativeCurrency: {
	  name: 'Ether',
	  symbol: 'ETH',
	  decimals: 18,
	},
	blockExplorerUrls: ['https://etherscan.io'],
} 


const App: React.FC = () => {
  const defaultChainId = defaultNetwork.chainId
  const allowedChainIds = [defaultChainId];
  const endpoints = { [defaultChainId]: defaultNetwork.rpcUrls };

  return (
    <Web3ReactProvider connectors={[
      initializeConnector<GnosisSafe>(
        actions => new GnosisSafe(actions, true),
      ),
      initializeConnector<MetaMask>(
        actions => new MetaMask(actions, true),
        allowedChainIds,
      ),
      initializeConnector<Network>(actions => new Network(actions, endpoints, true), allowedChainIds),
    ]}
    network={defaultChainId}
    >
      {null}
    </Web3ReactProvider>
  )
}


ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root'),
);

vite.config.ts

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  base: '/',
  plugins: [
    react(),
  ],
  server: {
    host: '0.0.0.0'
  },
});

Reproduce MVP

If you need reproduce by self: connect-mvp.zip

gordomium avatar May 25 '22 15:05 gordomium

@gordomium I also hit this issue.

Seems like vite and esbuild are not working well with inline-require in the production mode Did you found a way to solve this? At least some vite workaround?

benzsuankularb avatar Jun 11 '22 12:06 benzsuankularb

I can't even fix this using @originjs/vite-plugin-commonjs

following this suggestion https://github.com/vitejs/vite/issues/5308

benzsuankularb avatar Jun 11 '22 13:06 benzsuankularb

I ended up hacked it so hard by patching the code using vite-plugin-replace plugin.

import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import { replaceCodePlugin } from "vite-plugin-replace";

export default defineConfig({
  plugins: [
    replaceCodePlugin({
      replacements: [
        {
          from: 'const zustand_1 = __importDefault(require("zustand"));',
          to: 'const zustand_1 = __importDefault(require("zustand"));const providers_1 = __importStar(require("@ethersproject/providers"));',
        },
        {
          from: "const { Web3Provider } = yield Promise.resolve().then(() => __importStar(require('@ethersproject/providers')));",
          to: "const { Web3Provider } = yield Promise.resolve().then(() => providers_1);",
        },
      ],
    }),
    react(),
  ]
})

Waiting for web3-react to solve the issue.

benzsuankularb avatar Jun 11 '22 14:06 benzsuankularb

+1, having the exact same issue and not sure how to solve it.

teqieth avatar Jun 11 '22 14:06 teqieth

Thanks.I solved my problem

lxhyl avatar Jul 05 '22 09:07 lxhyl

@lxhyl How did you?

benzsuankularb avatar Jul 06 '22 12:07 benzsuankularb

How did you?

look up. https://github.com/NoahZinsmeister/web3-react/issues/557#issuecomment-1152941052

lxhyl avatar Jul 07 '22 02:07 lxhyl