This project is a simple template for an embeddable React widget that can be inserted into a host website using a single <script> tag. It supports JSX, CSS styles, and is compiled using Webpack into a single .js file which can be static-hosted.
Both synchronous and asynchronous loading is supported.
- The widget is instantiated when the .js package is loaded
- The host page supplies a name and a targetElementId
- The widget registers a global object with the name supplied by the host page
- The widget renders the React component at the element specified by the host page
- The host page can communicate with the widget via the global object
You can view a live demo of both synchronous and asynchronous loading here:
https://bjgrosse.github.io/simple-embeddable-react-widget/dist/
This method uses simple <script> tag reference as shown below:
<div id="root"></div>
<script src="http://somehost/widget.js"
id="Simple-Widget-Script"
data-config="{'name': 'w1', 'config': {'targetElementId': 'root'}}" ></script>
The data-config attribute passes in the name w1 for the widget's global object as well as the target element id root where the widget should be rendered.
The host page can then communicate with the widget via the global object like this:
<div><button onclick="w1('message', 'Hello world!');">Send Message</button></div>
In this code, we send the message call to the widget and pass a string as the parameter.
We can load the widget asynchronously. Using this method we create a temporary object that holds any calls to the widget in a queue and when the widget loads, it will then process those calls.
<div id="root">Loading...</div>
<script>
(function (w, d, s, o, f, js, fjs) {
w['Simple-Widget'] = o; w[o] = w[o] || function () { (w[o].q = w[o].q || []).push(arguments) };
js = d.createElement(s), fjs = d.getElementsByTagName(s)[0];
js.id = o; js.src = f; js.async = 1; fjs.parentNode.insertBefore(js, fjs);
}(window, document, 'script', 'w1', 'http://somehost/widget.js'));
w1('init', { targetElementId: 'root' });
</script>
This code follows the pattern used by Google Analytics. The function is called with the desired name of the global object (w1) and the url to the script. The function then records the desired name and, using that name, creates a placeholder global object that receives and queues any calls made to the widget before the asynchronous loading finishes.
Then it creates a script tag and injects it into the DOM.
The host then issues the 'init' call to the widget passing in any initialization values:
w1('init', { targetElementId: 'root' });
$ npm install
$ ./node_modules/.bin/webpack-dev-server --open
$ ./node_modules/.bin/webpack --config webpack.config.js
$ Jest
I found helpful guidance in this project from the following sites: