Is it possible to lazy load a set of components/modules in React from a url?

87
January 10, 2020, at 6:20 PM

I have a React application that I'm building that will support 3rd party developers writing their own components that we will test and then host on our company CDN. I have dynamic loading of modules working using @loadable/component, but I can't figure out how to get this to work for something that lives at a web address.

Here's what I have so far for lazy loading components. The components to be fetched are outlined in a .json file. This .json file is parsed and a component I wrote fetches the index.js at that location and loads that component into the application.

import moduleMetaData from "../thirdparty_modules"; //the json file outlining which modules to load
import loadable from "@loadable/component";
import React from "react";
const Module = (props) => {
    let id = props.id;
    let LoadedModule = null;
    if (!!moduleMetaData[id]) {
        let moduleLocation = moduleMetaData[id].location;
        LoadedModule = loadable(() => import(`${moduleLocation}`), {
            fallback: <div>Loading Module...</div>
        });
    }    
    return <LoadedModule/>;
}
export default Module;

Here's the .json file this is using:

{
  "module1": {
    "name": "ModuleTest1",
    "location": "./main/module1/index"
  }
}

I then use this <Module /> component inside of my App.js to load the modules into my application:

const App = () => {
    const GetModules = () => {
        let loadedModules = [];
        for(let key in moduleMetaData){
            loadedModules.push(<Module key={key} id={key}/>);
        }
        return loadedModules;
    }
    return (
        <AppContext.Provider
            value={{
                routes
            }}
        >
            <StylesProvider jss={jss} generateClassName={generateClassName}>
                <Provider store={store}>
                    <MuiPickersUtilsProvider utils={MomentUtils}>
                        <Auth>
                            <Router history={history}>
                                <FuseAuthorization>
                                    <FuseTheme>
                                        <FuseLayout/>
                                    </FuseTheme>
                                </FuseAuthorization>
                            </Router>
                        </Auth>
                    </MuiPickersUtilsProvider>
                    {/*LOAD MODULES*/}
                    {GetModules()}
                </Provider>
            </StylesProvider>
        </AppContext.Provider>
    );
};
export default App;

This code is allowing me to lazy load components and modules from within my /src directory, provided that the path to the index file of each module is added to thirdparty_modules.json.

The issue I'm having is that I cannot get this to work for modules that are being stored on an external web server. If I move the module1 directory from ./src/main/module1 to our CDN with an example address being https://our.cdn.net/module1, and then update my .json location to be https://our.cdn.net/module1/index, I get the error:

Unhandled Rejection (Error): Cannot find module 'https://our.cdn.net/module1/index'

How can I get my lazy loading of components to load from an external url, rather than having to load from my local /src directory?

Answer 1

While you cannot use it with import, you can still retrieve the data with, for example, the Fetch API and return it.

Something like

        LoadedModule = loadable(() => fetch(moduleLocation).then(res => res.text())

should work just fine.

READ ALSO
Heroku error module not found &#39;json-server&#39;

Heroku error module not found 'json-server'

I want to deploy my server on Heroku, but on Heroku build it says this:

107
Node.js Multer &ldquo;.array is not a function&rdquo;

Node.js Multer “.array is not a function”

I've been looking and trying to figure this out for two days now, and the only real mention of it that I can find is an old issue report on version 11

85
Sending multiple files in nodejs through TCP sockets

Sending multiple files in nodejs through TCP sockets

Here is the logical that im using:

79
store dispatch actions is not a Constructor in Angular

store dispatch actions is not a Constructor in Angular

I am using ngrx for storing dataI am getting below error while calling action?

116