The following ST3 plugins are need for React development:
- babel - for jsx syntax highlighting
- sublime-jshint - for linting your js code
- sublime-jsxhint - for linting your jsx code
Install babel
This one is very straight forward, just find babel in package control and install it. To use the Babel's JSX syntax highlight whenever a .jsx file is opened:
- open up a .jsx file in ST3
- Goto 'View -> Syntax -> Open all current extention as ... > Babel > Javascript (Babel)'
Linting JSX
I have written a blog about Linting react code here. Follow the instructions in that blog, it will give you real time linting as you code in sublime.
Install React Chrome plugin
Install this plugin if you use Chrome for development, go to this link and install.
Once installed, open up Extensions find the React plugin and check the Allow access to file URLS. This is important if you want to test React files locally.
If you have a webpage using React opened, such as this page, an extra tab named React should appear in your Developer Tools
Convert JSX files to JS files
React uses a syntax called JSX. To use it in your webpage, you have to convert it to regular JS format first. There are two ways to do it:
- Use the 'JSXTransformer.js' (which comes with React.js download) to do the conversion
- Use the 'react-tools' npm package to perform the conversion
Which one should you choose?
If you want to write your JSX code inside the HTML page, then use JSXTransformer.js like this:
<html>
<body>
<script src="js/vendor/react.min.js"></script>
<script src="js/vendor/JSXTransformer.js"></script>
<script type="text/jsx">
...React code inside...
</script>
</body>
</html>
This is good for debugging but not good for production. Because compiling from .jsx to .js takes time, you want to precompile the .jsx files to regular .js files before serving them to your customers.
So, how to compile .jsx files?
Install the 'react-tools' package via npm:
npm install -g react-tools
Once finished, go into your dev directory and use this command:
Assuming this is the structure of your dev directory
dev_dir/
js/
src/
build/
cd dev_dir/js
jsx -w src/ build/
This command means watching all .js files inside the src folder and compile them if modified to regular .js files and save them to the build folder.
WARNING: This command works only if you saved the JSX files with .js extension, if you saved your JSX files with the .jsx extension, then you need to use this command:
jsx -x jsx -w src/ build/
If the command has been executed successfully, you should see a message like this:
built Module("your_js_or_jsx_filename")
["your_js_or_jsx_filename"]
You can import the compiled js files like this (without the need of JSXTransformer.js):
<html>
<body>
<script src="js/vendor/react.min.js"></script>
<script type="text/javascript" scr="js/build/precompiled.js"></script>
</body>
</html>
XMLHttpRequest cannot load
Just when you thought you can import a .jsx file like regular .js file locally like this:
<html>
<body>
<script src="js/react.min.js"></script>
<script src="js/JSXTransformer.js"></script>
<script type="text/jsx" src="react_module.jsx"></script>
</body>
</html>
You will see an error in Chrome's console: XMLHttpRequest cannot load, this is because the JSXTransformer.js loads jsx files via XHR which is prohibited for local files.
There are a few ways to overcome this problem which is explained in the StackOverflow link above, but the easiest way to deal with it is to precompile your .jsx files into regular .js files and import them. (which has been explained in the previous section)
A very good React tutorial link
Reactjs Introduction for People Who Know Just Enough JQuery to Get by
This is about it to kickstart your React project using ST3.
Use Jquery to get DOM elements
React.js injects code into HTML block like this:
React.render(
<EditorForm />,
document.getElementById('content)
);
To use Jquery to accomplish the samething:
React.render(
<EditorForm />,
$("#content")[0]
);
$("#content") along is not enough, because it returns a jquery object instead of a DOM object.
Why does React.js render function's return statement is surrounded by a parenthese?
This is because JavaScript does automatic semicolon insertion
When the following line is entered:
var test = 'str1'
'str2'
'str3';
The output is not an error, but instead str1 is assigned to variable test. This is because a semicolon has been inserted by js automatically like this:
var test = 'str1';
When working with React.js, this is what a typical render() looks like:
return (
<div className="form-group hovering-textarea-container">
<input className="form-control input-lg" type="text" />
</div>
);
To make sure the entire div block is returned as a whole instead of just the first line, the parenthese are needed.
Julien Phalip gave a great talk at DjangoCon 2015, he introduced three ways to hydrate (i.e. load initial data into React component on first page load) React app with data, I am going to quote him directly from the slides and add my own comments.
-
Conventional Method: Client fetches data via Ajax after initial page load.
-
Less conventional method: Server serializes data as global Javascript variable in the inital HTML payload (see Instagram).
Let the server load the data first, then put it into a global Javascript variable which is embed inside the returned HTML page.
In the linked Github project (which is a Django project), the server fetches from the database to get all of the data. Then, it converts the data from Python object to json format and embed the data in the returned HTML page.
-
Server side rendering: Let the server render the output HTML with data and send it to the client.
This one is a little bit involved. Django would pass the data from DB along with the React component to python-react for rendering.
python-react is a piece of code that runs on a simple Node HTTP server and what it does is receiving the react component along with data via a POST request and returns the rendered HTML back. (The pyton-react server runs on the same server as your Django project.)
So which method to use then?
We can use the number of round trips and the rendering speed as metrics for the judgement.
Method 1
Round trips: The inital page request is one round trip, and the following ajax request is another one. So two round trips.
Rendering time: Server rendering is usually faster then client rendering, but if the amount of data gets rendered is not a lot then this time can be considered negligible. In this case, the rednering happens on the client side. Let's assume the amount of data need to be rendered is small and doesn't impact the user experience, then it is negligible.
Method 2
Round trips: Only one round trip
Rendering time: Negligible as aforementioned.
Method 3
Round trips: Only one round trip
Rendering time: If it is negligible on the client side then it is probably negligible on the server side.
It seems that Method 2 & 3 are equally fast. The differences between them are:
- Method 2 renders on the client side and Method 3 renders on the server side.
- Method 3 requires extra setup during development and deployment. Also, the more moving pieces there are, the more likely it breaks and takes longer to debug.
Conclusion
Without hard data to prove, here is just my speculation: Use Method 2 most of the time and only Method 3 if you think rendering on the client side is going to be slow and impact the user experience.
While learning react, many tutorials have recommend to use webpack for building react apps. I created a very simple react app on Github to demonstrate the concept of webpack.
What does Webpack do? Why do I need it when using React?
React encourages you to write reusable UI components. Let's say you write a date picker. It comes with its own CSS style sheet and a background image. To reuse this component elsewhere, you need to pack the source code along with all the resources into one package for others to download.
Webpack does just that:
fonts + images + CSS + source code => bundle.js
How does it work?
Download this example I wrote and take a look at the index.js file. On the third line of index.js you will see:
var Style = require('./style.css'); // the './' in front of style.css is important, if missing, require will go into node_modules to look for it which is not what we want
You might think this line is broken because how can you import a .css into a .js file. While, it works because of Webpack. Open up webpack.config.js and take a look at this part (starting at line 18):
{
test: /\.css$/, // a regex to match all .css files
loader: 'style-loader!css-loader' //css-loader acts first to interpret require('.css') and read the content of the css file. Then, it passes the content to style-loader which insert the css as <style>content</style> into the header section of a HTML file. The ! mark is used to chain loaders. The order of the loader execution is from right to left.
}
Webpack uses loaders to deal with different file formats during the packing stage. In this case, css-loader and style loader are used to deal with .css file type. If you write in LESS or SASS, there are corresponding loaders to deal with those.
There are two ways to enable loaders, the most common way is to specify them in the webpack.config.js file:
{
test: /\.png$/, // use regex to match all the png files
loader: 'url-loader?limit=300&name=[name].[ext]' // use url-loader to deal with png files. You can pass parameters to a any loader using 'whatever-loader'?param=value' format
}
All .png files will be dealt with the url-loader. What the url-loader does is to turn a file into data URI. In this case, the file small_img.png is turned into:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAGCAYAAADOic7aAAAAH0lEQVQY02M4cODAfyhmgGKy+AzUNIgqmKoGDa4wAgBEaBrozyRdGQAAAABJRU5ErkJggg==
The limit=300
part means if the file is less than 300 bytes, then turn it into data URI.
Another way to enable loader is shown on line 11 in index.js:
<img src={require('file-loader?name=[name].[ext]!./large_img.jpg')}></img>
If you specify the loader this way, then it would only affect this particular jpg file rather than all the jpg files in your project.
The file-loader reads a file and return the file in the following format:
MD5_hash_of_the_file_content.extension
We don't want to reference a file with a hash name, instead we would like to reference it using the file's original name and extension. name=[name].[ext]
does just that.
Once all the loaders are being configured, run the webpack
command to transform the assets into data URIs or plain file names. Then, you can open up index.html
in the browser to see the result.
Conclusion
I hope this post provides a general overview of what Webpack does and how it fits into the big picture of react development.