Organizing a React JS project - building single JS file
-
21-12-2019 - |
Question
I just got started using React. I went through the CommentBox tutorial without any issues. But the framework does not give much/any guidance to organizing your JS files or compiling a single minified JS file for a SPA. I already know the framework is flexible and does not enforce a standard and I'm sure these questions are probably dead obvious for someone who develops in the Javascript ecosystem.
I would imagine the consensus is to use Browserify and in the docs there's a link to a git starter project:
https://github.com/petehunt/react-browserify-template
This is a good start, but still it only compiles a single JS file "index.js". I read through some of the browserify handbook and I thought I simply had to 'require' my other files (and those files need to export themselves).
So I modified index.js to look like this:
/** @jsx React.DOM */
var React = require('react');
var pkg = require('./package.json');
var commentBox = require('./comment-box.js');
comment-box.js is basically a hello world test:
/** @jsx React.DOM */
var React = require('react');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
module.exports = CommentBox;
If I run the react-browserify-template's start target it seems to generate browser-bundle.js fine:
npm start
But if I try the build target
npm build
...nothing happens. I changed the output of npm to verbose and I get the following:
npm info it worked if it ends with ok
npm verb cli [ 'node', '/usr/local/bin/npm', 'build' ]
npm info using npm@1.4.21
npm info using node@v0.10.24
npm verb exit [ 0, true ]
npm info ok
According to package.json it's supposed to generate a file "browser-bundle.min.js" but instead I get no output. I'm hoping someone can clear this up.
Solution
I figured out what the problem was. As I stated originally, it is probably obvious for someone who's been developing in the JS ecosystem :)
The package.json in the react-browserify-template has three scripts in the "scripts" section with the keys "start", "build", and "test".
As I said previously, start worked fine by running:
npm start
I wrongly assumbed that I could run the build script similarly:
npm build (this will never work and there will be no errors/output)
It turns out I needed to run the build script using:
npm run-script build
One extra line in the documentation might have saved me hours of trouble :D I'm now using this approach as it seems quite a bit simpler. Also, it sets NODE_ENV to production and uses envify which apparently is important: https://github.com/facebook/react/issues/1772
One other thing, some of the official examples such as todomvc-flux use the lowercase 'react' in the require function:
var React = require('react');
so I suppose that's the recommended syntax (?)
OTHER TIPS
Working solution using Felix's gist. Note: This is not 100% equivalent to the react-browserify-template which uses envify and the production flag to get rid of some React debugging (mainly "Download the React DevTools for a better development experience: http://fb.me/react-devtools" which is printed to the console on startup).
Perhaps a mod can give Felix credit for the solution?
App.js
/**
* @jsx React.DOM
*/
"use strict";
var React = require('React');
var CommentBox = require('./components/CommentBox.js');
React.renderComponent(
<CommentBox />,
document.getElementById('content')
);
components/CommentBox.js
/** @jsx React.DOM */
var React = require('React');
var CommentList = require('./CommentList.js');
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList />
</div>
);
}
});
module.exports = CommentBox;
components/CommentList.js
/** @jsx React.DOM */
var React = require('React');
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
Hello, world! I am a CommentList.
</div>
);
}
});
module.exports = CommentList;