What steps should I take to manually split code in preact?

In my project, I am looking to manually implement code-splitting with preact. While preact already handles code splitting for routes, I want to take control of it.

The scenario is that I am creating a tool where users can customize widgets on a dashboard. I only want to load the code for the widgets that the user has configured on the home page, not all available widgets.

Therefore, I prefer not to bundle the code for all widgets in a single bundle.js file but instead load it lazily when required, such as when rendering the list of widgets.

I tried using the async! syntax, which I found in older commits for the boilerplate, but it didn't work as expected.

Here is a simplified version of the code I am working with

Configuration data

[{ "type": "notes", "title": "Widget 1}, { "type": "todo", "title": "Widget 2"}]

The render function for the widget list

const Grid = ({ widgets }) => (
    <ul>
        {widgets.map((widget) => <li key={widget.title}><Widget widget={widget} /></li>)}
    </ul>
);

Widget component structure

Here I have defined a mapping from the widget type to its corresponding component:

import notes from widgets/notes;
import todo from widgets/todo;

class Widget extends Component {
    widgetMap(widget) {
      if (widget.type === 'notes') {
         return notes;
      }
      if (widget.type === 'todo') {
          return todo;
      }
    }

    render ({ widget }) {
        const widgetComponent = this.widgetMap(map);
        return (
            <div>
                <h1>{widget.title}</h1>
                <widgetComponent />
            </div>
        );
    } 
}

Answer №1

In case you are utilizing Preact X, it comes with <Suspense> and lazy which has the same API React uses. If you want to explore more about it, you can find detailed information here: https://reactjs.org/docs/concurrent-mode-suspense.html

To adjust your example, it would resemble this (code adapted from here):

import { Suspense, lazy } from `preact/compat`;

const notes = lazy(() => import('./widgets/notes'));
const todo = lazy(() => import('./widgets/todo'));

class Widget extends Component {
    widgetMap(widget) {
      if (widget.type === 'notes') {
         return notes;
      }
      if (widget.type === 'todo') {
          return todo;
      }
    }

    render ({ widget }) {
        const widgetComponent = this.widgetMap(map);
        return (
            <Suspense fallback={<div>loading...</div>}>
                <div>
                    <h1>{widget.title}</h1>
                    <widgetComponent />
                </div>
            </Suspense>
        );
    } 
}

If you are working with an older version of Preact, you have the option to create an async loading HOC manually as long as you have Babel or another transpiler configured to manage dynamic module loading

export default asyncComponent = (importComponent) => {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);
      this.state = { component: null };
    }

    async componentDidMount() {
      const { default: component } = await importComponent();
      this.setState({ component });
    }

    render() {
      const Component = this.state.component;
      return Component ? <Component {...this.props} /> : <div>loading...</div>;
    }
  }

  return AsyncComponent;
}

Answer №2

If you're looking for a code snippet to implement, check this out:

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from '../../pages/Home';
import Books from '../../pages/Books';
import NotFound from '../../pages/NotFound';
import Header from '../Header';
import './style.css';

export default function App() {
  return (
    <Router>
      <Header />
      <main>
        <Switch>
          <Route exact path='/' component={Home} />
          <Route path='/books' component={Books} />
          <Route component={NotFound} />
        </Switch>
      </main>
    </Router>
  );
}

Although the solution provided uses lazy and suspense from preact/compat, the snippet above opts for react-router-dom and regular imports for components.
It seems like the usage of preact-iso with lazy is gaining popularity based on recent project setups.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can we add styles to text entered into a form input field in a targeted way?

Is there a way to apply styling to the second word entered into a form input text field after the user hits "enter" and the data is output? In this scenario, the text always follows the format of 3 numbers, followed by a space, and then a name. For examp ...

Sending properties within components using #createElement in React-Router is a convenient way to pass data locally

Have you ever wondered where the parameters Component and props are coming from in the React-Router documentation? // Here is the default behavior function createElement(Component, props) { // ensure all props are passed in! return <Component {... ...

Can the minimum length be automatically filled between two elements?

I'm struggling to find a way to adjust the spacing of the "auto filling in" dots to ensure a minimum length. Sometimes, on smaller screens, there are only one or two dots visible between items. Is there a way to set a minimum length for the dots in th ...

What are the steps to gather user data and generate a roster of individuals currently online?

I am currently working on a way to gather information about the users who are currently logged into my website. Here's how it works: When a user enters my website, they have the option to choose a nickname using an input box. Then, there are five diff ...

How do I insert a new item into the tree structure using Sapui5 CustomTreeItem?

Having an issue with the CustomTreeItem in SAPUI5. I can successfully display the tree structure from JSON, but struggling to manually add data on click of the Add button. https://i.sstatic.net/BpLOK.png In the image above, when I click the + Button, I n ...

What is the significance of declaring a variable outside of a JavaScript function? (Regarding jQuery and #anchor)

In my jQuery function, I needed to determine the current #anchor of the page. To achieve this, I utilized the jQuery URL Parser plugin. $.fn.vtabs = function() { alert("The current anchor is "+$.url.attr('anchor')); } Initially, the code c ...

Transforming the timezone of a date from the Backend to the timezone selected by the user in the User

I have an API that provides dates in the format: 12/23/2023 at 03:31 a.m. CST My goal is to convert this to a date with the user-selected timezone in the following format: 12/23/2023 at 7:31 p.m. The timezone part is not required for display in the UI. c ...

Is the fulfillment of AngularJS $q promises determined by the return value?

I'm currently working with angularjs 1.6.1 and $q. My task involves fetching a large amount of data from an API. I'm struggling to grasp when promises are actually fulfilled. Here's a snippet of what I'm doing: // controller this.dataO ...

Encountering an error in React Native: Unable to access property 'length' as it is

Currently, I am working on developing a registration application and I have encountered some issues in the final phases when attempting to submit the new data to the server. Below is the script I am using: import React from 'react'; import React ...

The pagination feature for array field type is malfunctioning on Mongoose, yet it functions properly on the Mongo

I am facing an issue with pagination on the rating field of my product collection. After executing a query in the mongo shell, db.products.find({_id: ObjectId('610bd9233fdc66100f703dd4')}, {ratings: {$slice: [1,1]}}).pretty(); I received the ...

Utilizing ID for Data Filtering

[ { "acronym": "VMF", "defaultValue": "Video & Audio Management Function", "description": "This is defined as the Video and/or Audio Management functionality that can be performed on a Digital Item. The Video & Audio M ...

Inquiries regarding the distinctive key and component framework of Ant Design

Currently, I am in the midst of a project utilizing react, next.js, and antd. However, an error message has popped up stating: Warning: Each child in a list should have a unique "key" prop. This issue precisely stems from the absence of a uniqu ...

Selecting a full table row activates a top-up popup

I have successfully implemented a script in Javascript to enable full table row selection as shown below. <script type="text/javascript"> $(function() { $('#link-table td:first-child').hide(); $('#link-table tr').hover(func ...

Determination of Vertical Position in a Displayed Table

I am trying to incorporate infinite scrolling with an AJAX-based loader in the body of an HTML table. Here is a snippet of my HTML code: <table> <thead> <tr><th>Column</th></tr> </thead> <tbody> ...

Setting URL parameters in a POST request: A guide

Currently, the data in question is structured as JSON within this code snippet. However, I've received feedback indicating that it should actually be implemented as URL parameters. I'm currently facing some difficulties with modifying this to fit ...

How do I avoid using an if statement in jQuery to eliminate errors caused by "undefined" values?

Whenever I incorporate third-party plugins, my usual practice is to initiate them in the main application.js file. For example: $('.scroll').jScrollPane(); However, a challenge arises when a page loads without the presence of the scroll class, ...

Click outside of this popup to dismiss it

I have been struggling to figure out how to make this popup close when clicking outside of it. Currently, it only closes when clicked directly on it. Your assistance in this matter is greatly appreciated. Here is the HTML code: <h2>Popup</h2> ...

The DOM assigned a new source to an image

Currently, I am working on a project that involves both jquery and PHP. In this project, users are able to upload images which are then displayed in blocks. The uploading functionality is already working, but I am facing an issue with setting the image sou ...

Return the outcome of an Axios POST request

Upon integrating JWT verifyToken into my non-JWT api call, my Axios POST request now returns an empty result set. Function 2 (/userget) is functioning correctly and displays results on HTML, whereas Function 7 (/api/userget) can retrieve data and token but ...

What is the process for transferring information from a Microsoft Teams personal tab to a Microsoft Teams bot?

Is it feasible to share data such as strings or JSON objects from custom tab browsers to a Teams bot's conversation without utilizing the Graph API by leveraging any SDK functionality? ...