Dynamically import React component from external URL and use parent React environment

Viewed 2127

I have a Main UI into which I want to load a Sub UI in the form of a React Component, which is then integrated through a React.Suspense JSX Tag. The Main and the Sub UI will both be separately bundled with Webpack. The Sub UI is bundled as a Webpack 5 Module Library.

Now, the dynamic loading of the component from an URL seems to be no problem. I can use

var path = "<< some URL to a JS-File in a CDN >>";
var SubUiComponent = React.lazy(() => import(/* webpackIgnore: true */ path));

But because the component that I want to import is bundled with Webpack, another React instance is being used. I have already tried to use Webpack Externals, but there seems to be no way that it can be used in combination with dynamic imports.

When I'm not defining externals, I get the following error:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.

With externals defined in webpack.config.js, I get the expected error:

Uncaught ReferenceError: React is not defined

So, is there a way of bundling a React component "kind of" as a library and then import it into another React Environment and use it there?

1 Answers

With two of your different local react projects, you want to link/refer/import one from another? If this is what you're trying to do then yes, it is possible.

First Approach:

You need to research on npm link

Note that package-name is taken from package.json, not from the directory name.

npm link in a package folder will create a symlink in the global folder {prefix}/lib/node_modules/<package> that links to the package where the npm link command was executed.

It will also link any bins in the package to {prefix}/bin/{name}. Note that npm link uses the global prefix (see npm prefix -g for its value).

In some other location, npm link package-name will create a symbolic link from globally-installed package-name to node_modules/ of the current folder

    cd ~/projects/some-dep
    npm link                # Step 1.
    cd ~/projects/my-app
    npm link some-dep       # Step 2.

now, from your my-app folder, you can install some-dep

    ~/projects/my-app
     npm install some-dep@

Second Approach:

Bundle and publish your project to npm registry then install, import it into your other project. Refer this one that I'd published to try out

Third Approach:

Webpack ModuleFederation, when you import the project/module, it will look for it in node_modules, if not found then in the federated modules.

Ref: https://webpack.js.org/concepts/module-federation/

Related