Search code examples
reactjswebpack

Self-contained React webpack library


React is already bundled in the lib, so im trying to figure out how to use it instead of having to also download it in the consumer app.

webpack.config.js

const path = require('path');

module.exports = {
    mode: 'production',
    entry: './src/Components',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'webpack.bundle.js',
        library: {
            name: 'webpackLib',
            type: 'umd'
        }
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js'],
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                exclude: /node_modules/,
                use: 'ts-loader',
            },
        ],
    }
};

consumer app index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>HTML 5 Boilerplate</title>
    <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
    <script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js" crossorigin></script>
    <script src="../lib/dist/webpack.bundle.js"></script>
  </head>
  <body>
    <div id="container"></div>
    <div id="another-container"></div>
      <script src="index.js"></script>
  </body>
</html>

index.js

function injectComponentFromLib(containerName, componentName) {
    const root = ReactDOM.createRoot(document.getElementById(containerName));
    var component = webpackLib[componentName];
    var element = React.createElement(component);
    root.render(element);
}

injectComponentFromLib('container', 'TestComponent');
injectComponentFromLib('another-container', 'AnotherTestComponent');

Any idea how to go about it?


Solution

  • I figured out i could make the method part of the lib as

    import React from "react";
    import { createRoot } from 'react-dom/client';
    import Components from "./Components/ComponentMap";
    
    function InjectComponentFromLib(containerName: string, componentName: string): void {
        const root = createRoot(document.getElementById(containerName));
        const component = Components[componentName];
        if (!component) {
            console.error(`Component "${componentName}" not found.`);
            return;
        }
        var element = React.createElement(component);
        root.render(element);
    }
    
    export { InjectComponentFromLib };
    

    with creating ComponentMap

    import TestComponent from "./TestComponent";
    import AnotherTestComponent from "./AnotherTestComponent";
    
    type ComponentMap = Record<string, React.ComponentType<any>>;
    
    const componentMap: ComponentMap = {
        TestComponent,
        AnotherTestComponent
    };
    
    export default componentMap;