Full-Stack Engine

Creating a new project with Sails.js, Webpack and React.js

Update May 17th, 2018: Added second part, added react-router, bootstrap 4 and reactstrap.
Update April 11th, 2018: Upgraded to use Webpack 4 and Sails v 1.0

In a previous post I wrote about the steps needed for creating a new full-stack project using Sails.js in the back-end side and Angular 4/5 in the front-end.

Sails.js is an excellent framework for handling web services, database migrations, real-time updates using web sockets and in the top of that, provides a straightforward and opinionated set of configurations to make our life more comfortable at the time we create a full-stack project.

However, we also have React.js, who seats in the crown of JS Front-end frameworks as far as it is in 2017 (and it's shown in Developer Survey Results
2018
, it's in excellent shape in 2018). It's a vast library that offers us the flexibility to work with any other JS tool, CSS framework and of course with any back-end platform.

See also on Tutorials/Guides

So, this time I decided to show you how to create a new full-stack project with react and sails.js. As you might know, react.js uses ES6 (also ES7/ES8 using Babeljs) as the primary language in development time, opposed to Typescript in Angular. However, they both transpile code commonly into ES5 for compatibility with most of the browsers. Then we need to set up a transpiler for our project; we'll be using one of the most popular javascript compilers: Babeljs.

To know more about ECMAScript 2017, also known as ES8, you can take a look at this article.

On the other hand, we need a module loader, to load our react components and a bundler to minify assets for the production environment. For this task, we'll be using Webpack which is a modern and robust framework to accomplish all of these tasks and additionally provides a dev-server to live reload changes in the code as we work on development stage.

Let's recap the agenda for this guide:

  1. (*)Part 1: Basic project setup with Sails.js v 1.0 (back-end), React 16 (front-end lib) and webpack 4 (as the module loader/bundler).
  2. Part 2: Project setup adding bootstrap (4) for UI styling along with the use of reactstrap, react-router for client-side routing/history and jest/enzyme for basic testing.

You can find the complete project's template source here (part-1).

Without more delays, let's begin,

Create a new Sails project; for that, we need to install Sails.js globally, to use the cli tool (making sure of using the latest version 1.0 of Sails),

npm install sails@^1.0.0 -g

Then, create a new sails project,

sails new new-project
cd new-project

Now, let's add react and react-dom libraries,

npm install --save react react-dom

Our index.js in react will just show a simple message. Let's add it inside assets/src folder,

import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
  return (
    <div>
      Simple Sails-React stater
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));

And also index.html,

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Sails React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

Next, add webpack package,

npm install --save-dev webpack webpack-cli

Moreover, some plugins we'll need and review in detail in a moment,

npm install --save-dev HTML-webpack-plugin

Now, configure webpack. We'll add a file webpack.config.js,

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    entry: './assets/src/index.js'
  },
  output: {
    path: __dirname + '/.tmp/public',
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        use: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/
      },
      {
        use: ['style-loader', 'css-loader'],
        test: /\.css$/
      }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'assets/src/index.html'
    })
  ]
};

Let's explain how the plugins and loaders work and their purpose in the webpack work-flow,

  • HtmlWebpackPlugin: Takes our index.html and injects the script tags for the generated bundle and vendor js files.
  • babel-loader: Allows the dynamic loading of modules using ES6 syntax and transpiling them into the specified preset (in our case ejs with react).
  • style-loader & css-loader: Used to load separate CSS files into our JavaScript files.

On the other hand, you might have noticed webpack outputs the results into .tmp/public. Sails by default copies its assets into this folder. However, we need to modify our layout and homepage view for this to work fine.

Modify view/layouts/layout.ejs,

<%- body %>

And views/pages/homepage.ejs,

<!DOCTYPE html>
<html>

<!-- webpack generate html -->
<%- partial('../../.tmp/public/index.html') %>

</html>

As you can see, homepage becomes an empty shell which task is just loading the partial view generated by webpack in the previous step. A convenient approach when working with Single Page Applications, where we only need the initial page load from the server.

Let's move on.

Install Babel and presets for react,

npm install babel-loader babel-core babel-preset-env babel-preset-react --save-dev

And add .babelrc to define a "preset" for react js. This step is needed to handle JSX for javascript compilation in React.

{
  "presets": ["babel-preset-env", "react"]
}

Finally, let's configure webpack dev-server and the scripts we're going to use to run the project.

First, install npm-run-all to run several commands in parallel,

npm install npm-run-all --save-dev

Install Webpack dev-server and rimraf,

npm install --save-dev webpack-dev-server
npm install --save-dev rimraf

Add the following commands in the package.json,

"scripts": {
    "start": "npm-run-all --parallel open:client lift",
    "start:debug": "npm-run-all --parallel open:client debug",
    "open:client": "webpack-dev-server --mode development --open",
    "build": "npm run build:prod",
    "build:dev": "webpack --mode development",
    "build:prod": "webpack --mode production",
    "clean": "rimraf .tmp && mkdirp .tmp/public",
    "lift": "sails lift",
    "debug": "node --inspect app.js"
  }

Disable Grunt in .sailsrc- We don't need it anymore, as we are using webpack to perform the same tasks,

"hooks": {
    "grunt": false
}

Now we are ready to run the project!.

For the Development environment, we just run,

npm run start

This command starts and opens webpack dev-server and sails in dev mode.

If you want to take a different approach, then you might compile the assets first and then start sails to serve assets as it usually does in production. You might proceed with:

  • npm run build: Builds the project's assets in the production environment. Add build:dev for development; it won't minify javascript or CSS.
  • npm run lift: Starts running sails, same as Sails lift, by default it runs at localhost:1337

That's all for now. Thank you for reading this post. Take care!.

Author image
Costa Rica
Passionate Software Developer with full-stack development experience.