At work we’ve been building quite some stuff on top of React the past few months. We use Grunt (and more recently Webpack) to run browserify with the babelify transform to transpile our ES6 code into ES5.
Earlier this week I came to the point where I wanted to distribute a built component as a standalone .js
file, for inclusion in the browser by 3rd party developers (in case they don’t know React themselves, or use ES5, or just don’t want to include the component’s source).
Building that standalone version comes with a few prerequisites:
- No copy of
react
norreact-dom
should be included in the component itself – just like a jQuery plugin does not include jQuery itself but relies on it being available instead. - The contained classes should be accessible on a single namespace to the 3rd party developer.
That way an implementer could include the component as follows:
<-- Include react and react-dom -->
<script type="text/javascript" src="/libs/react/15.2.1/react.js"></script>
<script type="text/javascript" src="/libs/react/15.2.1/react-dom.js"></script>
<-- Include the Component -->
<script type="text/javascript" src="/script/my-react-component.js"></script>
<-- Use the Component -->
<script type="text/javascript">
var c = new MyComponent.Player();
</script>
To get this working, I had to make a few adjustments into the build script:
- Prevent both the
react
andreact-dom
packages from being included into my distributable file, using browserify’sexternal
option. This option will tell browserify to not try and includereact
/react-dom
whenever it encounters animport
/require()
for one of those packages, but to trust us to them being available. - Transform all
import
/require()
calls forreact
/react-dom
to use the external (global) copies of React, using thebrowserify-global-shim
transform for Browserify. - Define a (global) namespace into which all of my classes will become available, using browserify’s
standalone
option.
Puzzling all pieces together, our browserify Grunt task to build the standalone/distrubutable version looks like this:
{
dist: {
src: ['src/index.js'],
dest: 'dist/my-react-component.js',
options: {
watch: false,
external: [
'react',
'react-dom',
],
transform: [['babelify', {
presets: ['react', 'es2015'],
compact: false,
plugins: ['transform-class-properties', 'transform-object-rest-spread', 'add-module-exports']
}], ['browserify-global-shim', {
"react": "React",
"react-dom": "ReactDOM"
}]],
browserifyOptions: {
extensions: ['.js'],
debug: false,
standalone: 'MyComponent'
}
}
}
}
In summary:
options.external
preventsreact
/react-dom
from being included locally into the dist file itself,- The entry
browserify-global-shim
(along with its own options) inoptions.transform
wires theimport
/require()
calls forreact
/react-dom
to the global versions as the local versions don’t exist, options.browserifyOptions.standalone
defines the namespace which gets exported globally.
Consider donating.
I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!