8

I'm using React JS + webpack. General case that I need to resolve is to dynamically load React components that were not bundled with main application. Kind of pluggable components that can be developed independently from main app and then loaded by application dynamically, without rebuilding whole app.

Particular case is below.

I have two completely separated modules (i.e. built using different package.json and webpack.config.js):

  • The MainApp
  • Some Component

I need to implement following behaviour:

  1. Page with MainApp loaded and initialized.
  2. MainApp dynamicaly lookup for url of .js file that contains Component (e.g. by making GET request to web-server).
  3. MainApp loads .js file with Component and include it to page as <script>
  4. MainApp uses loaded Component while rendering.

Is such use-case possible in react js + webpack?

4
  • The GET request returns a compiled component? Commented Nov 15, 2016 at 18:16
  • It returns valid .js file, not .jsx (if you are talking about it). Commented Nov 15, 2016 at 22:10
  • Did you ever find a solution for this? Commented Jan 9, 2017 at 22:19
  • Nope. I found another solution for my particular task, but it doesn't solve general problem. I creating components dynamically from json description (like github.com/mozilla-services/react-jsonschema-form). It makes dynamic components quite limited in appearance and behaviour, but it's ok for me Commented Oct 12, 2018 at 8:26

2 Answers 2

2

With webpack 5 you can now do this via module federation.

The basic idea is that you "expose" exports from one project to be used in another:

App 1 (uses Button from app2)

<!-- public/index.html -->
<html>

<head>
  <!-- remote reference to app 2 -->
  <script src="http://localhost:3002/remoteEntry.js"></script>
</head>

<body>
  <div id="root"></div>
</body>

</html>

//app.ts
import * as React from "react";

const RemoteButton = React.lazy(() => import("app2/Button"));

const App = () => (
  <div>
    <h1>Typescript</h1>
    <h2>App 1</h2>
    <React.Suspense fallback="Loading Button">
      <RemoteButton />
    </React.Suspense>
  </div>
);

export default App;

//... webpack.config.js
plugins: [
    new ModuleFederationPlugin({
      name: "app1",
      library: { type: "var", name: "app1" },
      remotes: {
        app2: "app2",
      },
      shared: ["react", "react-dom"],
    }),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
  ]

App 2 (exposes Button)

// src/Button.ts
import * as React from "react";

const Button = () => <button>App 2 Button</button>;

export default Button;

//... webpack.config.js
 plugins: [
    new ModuleFederationPlugin({
      name: "app2",
      library: { type: "var", name: "app2" },
      filename: "remoteEntry.js",
      exposes: {
        Button: "./src/Button",
      },
      shared: ["react", "react-dom"],
    })
  ]

Here is a repo containing various examples.

Sign up to request clarification or add additional context in comments.

1 Comment

I have the same needs. I need to use an external .js file which itself include a react component to be used in a main react application. External .js file is loaded dynamically at runtime when neede. I configured webpack to have externals react and react-dom. But each time the external .js is loaded I get the folowing error: "[ReferenceError: react is not defined]". How can I allow external .js file to refer the react libraries in the main application? Thanks
-1

It sounds like you are asking how to externalize React. If so, you can list libraries as "externals" in your webpack.config.js file:

webpackConfig.externals = {
  "react": "React",
  "react-dom": "ReactDOM",
  ...
}

1 Comment

I need to load component that wasn't exists at "compile time" (well, bundling time). I think you're talking about lazy-loading so all components are already known when app is bundled. It's not the same

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.