Chapter 2 ■ hello World
Node.js supports ES2015 to a large extent, so we will be using the ES2015 features and style of programming. We’ll be using ES2015 for the client-side code, so we might as well use the same on the server, so as to have a consistent style throughout.
...
const app = express();
app.use(express.static('static'));
...
This instantiates the application and then mounts a middleware. The middleware generator takes the parameter static to indicate that this is the directory where all the static files reside. Remember that we moved index.html into this directory.
The express.static generated middleware function is also smart enough to translate a request to “/” (the root of the website) and respond by looking for index.html in the directory. This is similar to what other static web servers such as Apache would have done. You could also have used http://localhost:3000/index.html to access the application and seen the familiar Hello World.
Chapter 2 ■ hello World
27
Separate Script File
First, we need to separate out the JSX script from your all-in-one index.html, and refer to it as an external script. This way, we can keep the HTML as pure HTML and all the scripts that need compilation in a separate file. Let’s call this external script App.jsx, and place it in the static directory, so that it can be referred to as /App.jsx from the browser. The new modified files are shown in Listings 2-3 and 2-4.
Listing 2-3. index.html: Separate HTML and JSX
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<title>Pro MERN Stack</title>
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react.js">
</script>
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/react/15.2.1/react-dom.js">
</script>
<script src=
"https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js">
</script>
</head>
<body>
<div id="contents"></div><!-- this is where our component will appear -->
<script type="text/babel" src="/App.jsx"></script>
</body>
</html>
Listing 2-4. App.jsx: JSX Part Separated Out from the HTML var contentNode = document.getElementById('contents');
var component = <h1>Hello World!</h1>; // A simple JSX component
ReactDOM.render(component, contentNode); // Render the component inside the content Node
At this point, the app should continue to work. Test it to make sure it does (point your browser to http://localhost:3000). Until now, we have only separated the files; we have not moved the transform to build-time. The JSX continues to get transformed by the babel library script. We’ll move the transform to build-time in the next step.
Chapter 2 ■ hello World
Transform
Create a directory to keep all the JSX files, which will be transformed into JavaScript and placed in the static folder. Let’s call this directory src. Let’s move App.jsx into this directory.
To transform the JSX, we need to install some babel tools. In this case, we need a couple of tools: babel-cli (the command line tool that invokes the transformation) and babel-preset-react (the plugin that handles React JSX transformation). Note that the babel tool handles not just JSX but many other transformations, which you can read about on the website. For now, we’ll only be installing the React transform, so execute the following command:
$ npm install --save-dev babel-cli babel-preset-react
Now we’re ready to transform App.jsx into pure JavaScript. Do this:
$ node_modules/.bin/babel src --presets react --out-dir static
Since we did not install babel-cli globally, you must type the path to the command, relative to the current directory, which is node_modules/.bin. We could have installed babel-cli globally using the --global (or –g) option of npm. That way, we would have access to the command in any directory, without having to prefix the path. But as discussed earlier, it’s a good practice to keep all installations local to a project. This is so that we don’t have to deal with version differences of a package across projects. An alternative is to add the .bin directory to the PATH environment variable, but you’ll see later that there is a better way to do all this, so let’s keep it like this for now.
We also need to change index.html to replace the reference to App.jsx to App.js and indicate the new type of this script; it is now JavaScript and not JSX. So, let’s just remove the type="text/babel" in the script specification. We no longer need the runtime transformer to be loaded in index.html, so we can get rid of the babel-core script library.
These changes are shown in Listing 2-5.
Listing 2-5. index.html: Changes in Script Name and Type ...
<script
src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.
min.js"></script>
...
<body>
<div id="contents"></div><!-- this is where our component will appear -->
<script src="/App.js" type="text/babel"></script>
</body>
...
It’s time to test this set of changes and ensure that things work as before. For good measure, use the browser’s developer console to ensure it is App.js that’s being fetched, and not App.jsx. The developer console can be found on most browsers; you may need to look at your browser’s documentation for instructions to get to it.
Chapter 2 ■ hello World
29