
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
reactnorreact-domshould 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
reactandreact-dompackages from being included into my distributable file, using browserify’sexternaloption. This option will tell browserify to not try and includereact/react-domwhenever it encounters animport/require()for one of those packages, but to trust us to them being available. - Transform all
import/require()calls forreact/react-domto use the external (global) copies of React, using thebrowserify-global-shimtransform for Browserify. - Define a (global) namespace into which all of my classes will become available, using browserify’s
standaloneoption.
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.externalpreventsreact/react-domfrom being included locally into the dist file itself,- The entry
browserify-global-shim(along with its own options) inoptions.transformwires theimport/require()calls forreact/react-domto the global versions as the local versions don’t exist, options.browserifyOptions.standalonedefines 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!