Waking Up Hapi
First, I’m going to initialize the app and install the Node.js dependencies. If you don’t have Node.js installed, head over here to get that done.
# Initialize a new Node.js app
npm init# Install Hapi, React, Flux, and dependencies
npm install --save hapi react react-dom flux hapi-react-views vision inert object-assign dateformat superagent babel-register babel-preset-es2015 babel-preset-react
*Update: Added babel to the list of dependencies since hapi-react-views no longer uses node-jsx but requires you to register Babel in the server.js file. The upside to this is you can start using ES6 and ES7 features anywhere in the server-side code. For the client side, check out Migrating to ES6 with Babel and ESLint.
Also, Babel 6 requires a .babelrc file to be placed at the root of the project declaring the configuration:
Next, I’ll add a basic Hapi.js server file. This will provide a few things:
- An HTTP server accessible at http://localhost:8000 to serve the web app;
- A view engine using the Hapi plugin vision and the hapi-react-views package to render the React/JSX components to a string before sending it to the client;
- A static directory route using the Hapi plugin inert to serve client-side assets like CSS, JS, and IMG; and
- A main app route that will serve a Default.jsx view template.
Here’s the completed server.js file that I’ll put in my project’s root directory:
To start it up, I’ll simply run:
Adding a Default Template
Building the Client Assets
After setting up the server and template, it’s time to automate the bundling of the client-side assets. Webpack provides a holistic approach by automatically following an entry file to every dependency that it needs. It then bundles all of the dependencies into one file. In addition, I noticed Webpack bundles about twice as fast as Browserify (based only on my testing in this project).
Another item of interest is that Webpack is often used in conjunction with a “hot-loading” development environment which automatically updates your code without refreshing the browser. In order to add hot-loading to this Hapi implementation, I’d need to take Kevin Old’s approach of attaching the webpack-dev-server to the public assets path that I’m serving. For now, I’ll resign to the fact that I’ll be refreshing my browser after changes like other web projects. Update: I recently added Webpack’s BrowserSync plugin which can help boost productivity.
First, I’m going to move all my client-side assets into a new assets directory off the root. Second, I’ll install the development dependencies I’ll be using:
npm install --save-dev nodemon webpack babel-core babel-loader
I’ve added nodemon to the mix because it’s a simple way to watch files and restart the server with minimal configuration. By default, nodemon watches all files in the current directory and runs npm start. Since Webpack will be bundling and watching my client assets, I don’t need nodemon to restart the server when those change. Consequently, here’s the nodemon.json file I’ll place in the root directory to configure all this:
The restartable option allows me to enter “rs” after nodemon is running to quickly have it restart (versus [Ctrl]+[C], [up], [enter]). The ignore array will have nodemon ignore the .git, node_modules, and assets folders.
Next, I’ll create the following webpack.config.js Webpack configuration file in the root directory:
The main parts of this file are the following:
- The entry — Webpack looks at the Index.jsx file to start bundling and tracing dependencies,
- The output — defines the location of the bundled file, and
- The loaders — it needs to process JSX file transformations with babel-loader.
I also edited my package.json file to add the following script:
"start": "node server.js",
"build": "webpack -p --progress",
"dev": "webpack --progress --color --watch & nodemon"
This allows me to quickly build the bundle and start the server during development with the following command:
npm run dev
I can also kick of a bundle of a production version of my assets and start the server with these commands:
npm run build
Note that I won’t be able to simply run the webpack command directly since I opted to install it locally. However, using an NPM script automatically sources the ./node_modules/.bin folder which makes the webpack command available in NPM scripts.
With Webpack and Hapi.js setup to bundle and serve, the Todo app can now be plugged into a deployment pipeline. By standardizing the app with a published port and providing build and run scripts, it’s even easier for an ops team or the continuous integration/delivery system to manage subsequent testing, packaging, and releasing. The next step might be configuring and packaging the app in a docker container for local development, remote testing, and deployment.
The full code of this example of serving React and Flux with Hapi and Webpack can be found here on GitHub.
If you found this post helpful, please let me know by selecting the heart below to recommend it.