infinum / eightshift-frontend-libs

Frontend library that exposes custom scripts and styles for modern WordPress projects
https://eightshift.com
MIT License
69 stars 12 forks source link

[FEATURE] - Blocks Lazy Loading #778

Open volfkarlo opened 6 months ago

volfkarlo commented 6 months ago

We might take a look at lazy loading of the blocks inside the boilerplate. It might lower the initial load size and reduce the main thread execution time.

This is the idea:

import React from 'react';
import { props } from '@eightshift/frontend-libs/scripts';
import { GridEditor as GridEditorComponent } from '../../../components/grid/components/grid-editor';

export const GridEditor = ({
    clientId,
    attributes,
    isSelected,
    setAttributes,
    showGridGuides
}) => {

    return (
        <GridEditorComponent
            {...props('grid', attributes, {
                setAttributes,
            })}
            showGridGuides={showGridGuides}
            clientId={clientId}
            isSelected={isSelected}
        />
    );
};

export default GridEditor;

Notice the default export at the end

import React, { useState, Suspense } from 'react';
import { InspectorControls } from '@wordpress/block-editor';

export const Grid = (props) => {
    const [showGridGuides, setShowGridGuides] = useState(true);

    const GridOptions = React.lazy(() => import('./components/grid-options'));
    const GridEditor = React.lazy(() => import('./components/grid-editor'));

    return (
        <>
            <InspectorControls>
                <Suspense fallback={<>Loading...</>}>
                    <GridOptions {...props} showGridGuides={showGridGuides} setShowGridGuides={setShowGridGuides} />
                </Suspense>
            </InspectorControls>
            <Suspense fallback={<>Loading...</>}>
                <GridEditor {...props} showGridGuides={showGridGuides} />
            </Suspense>
        </>
    );
};

Pontentially we can build up some kind of helper for solving this, something like:

const lazying = (url) => {
  const Component = React.lazy(() => import(url));
  return (
  <Suspense fallback={<div>loading...</div>}>
    <Component />
  </Suspense>
  );
};

But in a way that it works(this solution doesn't work).

What you are suppose to get is something like this inside the editor part Screenshot 2024-01-03 at 10 43 14 notice the additional file next to *Editor.js

@goranalkovic-infinum and I've tested it out, the savings for Grid block are measured in KBs but it might make a difference if everything is written in that way. I don't think this should be high on the priority list for testing, but potentially something to look into.

KR, Karlo

mbmjertan commented 2 months ago

I think this will make a noticeable impact on block editor performance on sites with a large number of blocks, given all blocks are imported by default.

I also considered something like this for the frontend with the intersection observer API, but I'm not sure whether the overhead of observers plus network requests will make it a net positive impact.