Extend Your Trellis WordPress Site with React – Part 2: Adding React (Node.js) to Our Local Server

Now that we have successfully got a new sub-site up and running on our trellis server (see Part One) its time for part two; adding React.

I am very new to Node.js, React and the world of dynamic web applications, so bear with me if I talk about this from a beginner view. After getting our sub-site up and running alongside our original WordPress site, the challenge now is to get a full node server running locally for development and on our production server. The following steps are relatively “hacky” and will require some revision further down the line (see future work) to work better Ansible (playbooks is still something I haven’t spent time really trying to learn, so if anyone has some modifications which will improve this, please leave your thoughts in the comments below).

A lot of the content in this section was adapted from a fantastic blog on Hackenoon, check it out.

Create a React Application

First, let us build a react app, we will need to install React locally on our machine

npm install -g create-react-app

This will install React globally. Next, let’s create a new folderblockchain in our website’s directory. You can build your React app at this level, however, I prefer to add an additional subdirectory to help with file organisation. In the terminal write:

create-react-app my-app
cd my-app
nom run build

Replacing my-app with whatever your project will be called, in my case this was block; which creates a bunch of files in the directory. By running npm start or yarn start, we should be able to run this application locally (even without the Virtual Machine running). Yes, that’s all you need to have a full React development environment in place. Take a look at CodeBurst for a blog on extending this primary application further.

Setup the Local Server

Next, let’s add React to our virtual machine. You will need to access the machine via ssh by either going to the Trellis folder and vagrant ssh or ssh vagrant@elvinos.uk. We are then going to install some applications on this server to host our React app.

From root you will need to install:

curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install -y build-essential
sudo npm i -g pm2
npm i -g serve

nodejs -c # to check if installed

This will add Node.js 9 and NPM to our local server; a process manager and an application which allows us to serve up a single page application.

Next, we want to host the site on our test domain.

#this is where our react app was built 
cd /srv/www/block.elvinos.uk/current/block 

pm2 serve build

This will create an output which looks like:

[PM2] Applying action restartProcessId on app [static-page-server-8080](ids: 0)
[PM2] [static-page-server-8080](0) ✓
[PM2] Process successfully started
[PM2] Serving /srv/www/block.elvinos.uk/current/block/build on port 8080
┌─────────────────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬─────────┬──────────┐
│ App name                │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user    │ watching │
├─────────────────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼─────────┼──────────┤
│ static-page-server-8080 │ 0  │ fork │ 2247 │ online │ 0       │ 0s     │ 0%  │ 26.5 MB   │ vagrant │ disabled │
└─────────────────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴─────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Take note of the number added to static-page-server as this is the port of our react application. You can check if the site is working by going to http://block.elvinos.uk:8080 as my port is 8080; hopefully, you should see your site running.

Reverse Proxy the Local Domain

Next, we want to make our app run on the actual domain and not on its port number; this is where we will use reverse-proxying, which maps our ported Node.js application to the domain address.

cd #go to root directory
cd /etc/nginx/sites-availablels/
sudo nano block.elvinos.uk.conf # We need to configure this file

For our local site we are not concerned with HTTPS, so we can clear the contents of this file ( ctrl-k is a quick way to delete lines). I recommend taking a copy of this file in case there are any issues. We will replace the contents of this file with:

upstream block.elvinos.uk{
 server 127.0.0.1:8080;
 keepalive 64;
}
server {
 listen 80;
 server_name block.elvinos.uk;
 root /srv/www/block.elvinos.uk/current/web/block;

 location / {
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header Host $http_host;
 proxy_set_header X-NginX-Proxy true;
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection “upgrade”;
 proxy_max_temp_file_size 0;
 proxy_pass http://block.elvinos.uk;
 proxy_redirect off;
 proxy_read_timeout 240s;
 }

Make sure you replace block.elvinos.uk with your own subset name, and the port number is set to the one earlier. Save the file with ctrl-x Y enter. We then need to restart our NGINX server with sudo service nginx restart. Hopefully, that should run successfully, and our new react app should be accessible at subset test domain (http://block.elvinos.uk).

At this point I have not managed to get pm2 startup to work correctly with pm2 serve build, this means when you restart the virtual machine you will need to run these steps:

 vagrant ssh
cd /srv/www/block.elvinos.uk/current/block/
pm2 serve build

This will start up the node server and allow the domain to work correctly

Understanding all this is an essential step to understanding how the react app will work on the real server. Having a locally ported subdomain is less critical as we can always access the react app even without the virtual machine running.

Putting Node.js on our Production Server

The final step is to take what we have learnt from building our local server and replicating this on the production server. The main difference is having root access to the server; use su followed by the root password. Remember you can access your remote server via ssh web@elvinos.uk provided you have set up the ssh keys correctly. We will then follow the same steps as before on the production server installing Node.js. At this point, it is a good idea to deploy your react app to the production server so the code can be run (git commit then ./bin/deploy.sh production block.elvinos.uk). After you run pm2 server build you should see the react app accessible at the actual domain on the designated port number.

Finally, we need to configure NGINX with HTTPS using Trellis’s SSL certificate.

cd #go to root directory
cd /etc/nginx/sites-availablels/
sudo nano block.elvinos.uk.conf # We need to configure this file

This time replace the code in the file with:

upstream block.elvinos.uk { #Change to your site
 server 127.0.0.1:8080; #change to your port 
 keepalive 64;
}

server {
  listen [::]:443 ssl http2;
  listen 443 ssl http2;
  server_name block.elvinos.uk; #Change to your site

  access_log   /srv/www/block.elvinos.uk/logs/access.log main; #Change to your site
  error_log    /srv/www/block.elvinos.uk/logs/error.log; #Change to your site

  root /srv/www/block.elvinos.uk/current/web/block; # Change to your site here
  add_header Fastcgi-Cache $upstream_cache_status;

  # Specify a charset
  charset utf-8;

  # Set the max body size equal to PHP's max POST size.
  client_max_body_size 25m;

  # SSL configuration
  include h5bp/directive-only/ssl.conf;
  include h5bp/directive-only/ssl-stapling.conf;
  ssl_dhparam /etc/nginx/ssl/dhparams.pem;
  ssl_buffer_size 1400; # 1400 bytes to fit in one MTU

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; ";

  ssl_certificate         /etc/nginx/ssl/letsencrypt/block.elvinos.uk-a728c93-bundled.cert; #Change to your site
  ssl_certificate_key     /etc/nginx/ssl/letsencrypt/block.elvinos.uk.key; #Change to your site

  include acme-challenge-location.conf;

  include includes.d/all/*.conf;
  include includes.d/block.elvinos.uk/*.conf;

  # Prevent PHP scripts from being executed inside the uploads folder.
  location ~* /app/uploads/.*\.php$ {
    deny all;
  }

  location / {
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_set_header X-NginX-Proxy true;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection “upgrade”;
  proxy_max_temp_file_size 0;
  proxy_pass http://block.elvinos.uk; # Change to your site
  proxy_redirect off;
  proxy_read_timeout 240s;
  }

  include h5bp/directive-only/cache-file-descriptors.conf;
  include h5bp/directive-only/extra-security.conf;
  include h5bp/directive-only/x-ua-compatible.conf;
  include h5bp/location/cross-domain-fonts.conf;
  include h5bp/location/protect-system-files.conf;

  location ~ \.php$ {
  try_files $uri /index.php;

  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
  fastcgi_param DOCUMENT_ROOT $realpath_root;
  fastcgi_pass unix:/var/run/php-fpm-wordpress.sock;
}
}

# Redirect to https
server {
listen [::]:80;
listen 80;
server_name block.elvinos.uk; #Change to your site

include acme-challenge-location.conf;

include includes.d/all/*.conf;
include includes.d/block.elvinos.uk/*.conf; #Change to your site

location / {
  return 301 https://$host$request_uri;
}
}

This file is kept very similar to the original where the root folder is modified, and an upstream section added. I recommend copying the original file and changing the code. Take note as your SSL file certificates will be different.

Finally, all we need to do is restart the server with sudo service nginx restart. And after a minute or so you should see your new sub-site react app fully operational!

Block.elvinos.uk React app up and operational

 Conclusions

A there you have it, you now have a blank new canvas to build your next react project ready to be deployed on your original WordPress server, keeping your work all in one place. This work was all done in preparation to build a prototype Smart Contract application over the next few months. So watch this space.

Further Work

Getting react to work on a Trellis configured Ubuntu server still has some work to be done. Re-provisioning the server will remove all the Node.js installations requiring the setup process to be rerun. If I have some time/ if anyone can help, it would be good to add the following improvements:

  • Make sure deploy_hooks.yml works correctly with the WordPress and Non-Wordpress sites. Currently, I have to comment out deploy_hooks.yml when I want to provision the react sub-site (less than ideal)
  • Get pm2 startup to work correctly, so I don’t have to manually start the node server when my production or development servers are rebooted
  • Automate the Node.js installation using Ansible’s playbooks
  • Automate the NGINX configuration file for the sub-site

Watch http://block.elvinos.uk for some new upcoming React projects.

Thanks for reading!

Join the Mailing List

Get the latest blog posts delivered straight to your inbox