Share
Explore

Bolt components


Component code

A component’s code is stored in 2 separate S3 files: Markup and Variables.
Markup file (Compiled JS)
Variables (JSON)

Fetching the component data

The data is fetched server side and then rendered in the RenderRemoteComponent which handles:
Saving the component data in state. (This is to prevent having to re-fetch if the component is present on other pages in the project.)
It gets the props from the HOC to render the actual component file with the correct props.

Serving from S3

Screenshot 2024-03-19 at 9.53.49 PM.png

GPT message

Yes, that's correct. This implementation, following the second solution, is designed to take already compiled JavaScript files from S3 and load them directly into your React application without needing further processing at runtime. Here’s a summary of how it works and the key benefits:
How It Works
Pre-compiled Components: Your components are pre-compiled from JSX to JavaScript. This compilation includes any necessary transformations (e.g., transpiling ES6+ code to ES5, if needed) to ensure browser compatibility. The result is a set of JavaScript files that define React components, which are then uploaded to S3.
S3 as a Host: The compiled JavaScript files are stored in an S3 bucket. This bucket is configured to serve these files over HTTP/S, acting as a static file host. Proper CORS configuration is necessary if the S3 bucket and your application are served from different domains.
Dynamic Import in React: The React application dynamically imports these compiled component files at runtime using the dynamic import() syntax. This import is triggered based on a component identifier (like componentId in the examples) which is mapped to the URL of the compiled JavaScript file on S3.
Rendering Components: Once the dynamic import resolves, the imported component (a React component definition) is set to state and subsequently rendered as part of your React component tree. The component can be passed props (like variables in the example), which are derived from a separate JSON configuration file or any other source.
Key Benefits
No Runtime Compilation Needed: Since the components are pre-compiled, there's no need for any JSX-to-JavaScript transformation or similar processing at runtime. The browser executes the JavaScript code directly.
Performance: Fetching and executing pre-compiled JavaScript files can be more performant compared to fetching and dynamically compiling code on the client side, especially for complex components or on devices with limited processing power.
Flexibility and Scalability: This approach allows for easy updates and additions to your component library by uploading new or updated files to S3, without needing to redeploy your entire application.
Security and Reliability: Using S3 and dynamic imports provides a secure and reliable way to load external components, as long as the components themselves are secure and the S3 bucket is properly configured.
This strategy, therefore, provides a clear and efficient way to manage and deploy React components in a scalable application architecture, leveraging the strengths of cloud storage and modern JavaScript capabilities.

Key Points

Dynamic Imports and Webpack: This approach assumes you are using a module bundler like Webpack that supports dynamic imports. Webpack handles the import() syntax by splitting your code into chunks loaded at runtime.
CORS and S3 Configuration: To serve JavaScript modules from S3, ensure your bucket is configured for CORS and can serve .js files with the correct MIME type. This setup allows your application to request and load these modules dynamically.
Security and Integrity: Using import() for dynamic module loading is inherently safer than eval() or new Function(), as it does not execute arbitrary code strings. However, ensure the integrity and security of your component modules on S3.
Caching and Versioning: Manage caching and versioning of your component modules on S3 to control how updates are propagated. This can involve cache-control headers, versioning file names, or using a service worker.

variables.json example

[
{
"name": "image_url",
"block_type": "input",
"data_type": "file",
"control_type": "image",
"default_value": "https://images.unsplash.com/photo-1708257106465-7e2b14997ab9?q=80&w=2244&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"icon": "",
"quick_view": false,
"description": "",
"friendly_name": "Image url 2",
"show_in_advanced": false,
"hidden": false,
"disabled": false,
"values": {},
"placeholder": "",
"parameters": []
},
{
"name": "image_alt",
"block_type": "input",
"data_type": "string",
"control_type": "text",
"default_value": "",
... Rest of parameters

Babel compiled JS file example

Example of how a component’s code would be stored in S3. (After being compiled by Babel)
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*#__PURE__*/_jsxs("div", {
className: "block relative border rounded-lg overflow-hidden",
children: [show_image && image_url && image_position === "top" && /*#__PURE__*/_jsx("div", {
className: clsx(fullWidthImageStyle, overlayStyle, "z-0"),
children: image_url
}), /*#__PURE__*/_jsxs("div", {
className: "p-5 z-50 w-full h-full ",
children: [/*#__PURE__*/_jsx("h5", {
className: "mb-2 text-xl font-medium leading-tight ",
children: title
}), /*#__PURE__*/_jsx("p", {
className: "mb-4 text-base",
children: text
}), /*#__PURE__*/_jsx("button", {
type: "button",
className: `${button_color} inline-flex items-center justify-center text-white whitespace-nowrap rounded-md text-sm font-medium h-10 px-4 py-2`,
children: button_text
})]
}), image_url && image_position === "bottom" && /*#__PURE__*/_jsx("div", {
className: clsx(fullWidthImageStyle, overlayStyle, "z-0"),
children: image_url
})]
});


RenderRemoteComponent example

import React, { useState, useEffect } from 'react';
const RenderRemoteComponent = ({ componentId, variables }) => {
const [Component, setComponent] = useState(null);
useEffect(() => {
// Dynamic import based on componentId
const loadComponent = async () => {
try {
// Assuming `componentId` can be mapped to a URL path for the compiled JS module
// For S3, you might need a server or build process to rewrite URLs to match S3 paths
const componentModule = await import(`path/to/components/${componentId}.js`);
setComponent(() => componentModule.default);
} catch (error) {
console.error("Failed to load component:", error);
setComponent(() => () => <div>Component failed to load</div>);
}
};
if (componentId) {
loadComponent();
}
}, [componentId]);
if (!Component) {
return <div>Loading component...</div>;
}
return <Component {...variables} />;
};
export default RenderRemoteComponent;

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.