/web-example

Primary LanguageJavaScript

Example application

This document details the steps by which this example was made.

To begin with this example, copy this code into your terminal:

curl https://raw.githubusercontent.com/lawrancej/web-example/master/main.sh | bash

Preliminaries

Download and install:

  1. Node.js, a server-side JavaScript network application framework.

  2. Git, a version control system.

    Windows

    Stick with the default options and click Next until finished.

    Mac OS X

    Got an error? Try:

    • Apple menu → System Preferences…​ → Security & Privacy → Open Anyway.

    • Otherwise, try: Spotlight Search (press F4 or Command-Space) → Terminal. Then, type git and follow instructions to install git.

    Linux

    Use sudo with your package manager.

  3. The Heroku toolbelt, to deploy to Heroku.

  4. PostgreSQL, a database server.

    Windows

    Use the Postgres Installer.

    Then, Windows key → Type "Environment" → Add the bin directory of Postgres to your PATH (like this: C:\Program Files\PostgreSQL\<VERSION>\bin).

    Mac

    Install Postgres.app.

    Move to Applications and Double-click to run.

    Then, from the command-line:

    echo "export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/latest/bin" >> ~/.bash_profile

Initial project setup

  1. Open the command-line.

    Windows

    Windows Key → Type "Git Bash"

    Mac

    Spotlight Search (Command-Space) → Type "Terminal"

  2. From the command line, install express-generator globally. Express is the web framework for Node.js.

    npm install express-generator -g
    Note

    Did you get an EACCES error? If so, do this:

    sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
  3. Use express-generator to generate boilerplate code.

    express --hbs project
  4. Go into your project folder. Assume all subsequent steps occur in this folder.

    cd project
  5. Examine the files placed in this folder:

    .
    ├── app.js
    ├── bin
    │   └── www
    ├── package.json
    ├── public
    │   ├── images
    │   ├── javascripts
    │   └── stylesheets
    │       └── style.css
    ├── routes
    │   ├── index.js
    │   └── users.js
    └── views
        ├── error.hbs
        ├── index.hbs
        └── layout.hbs
    app.js

    The entry point into this project.

    bin/www

    A wrapper script for app.js

    package.json

    Configures project name, scripts, and dependencies.

    public

    Anything placed in this folder is served statically.

    routes

    Where to place server-side code.

    views

    Handlebars templates

  6. Examine the package.json file. Notice the following dependencies:

Run the project locally

  1. From the command line, install dependencies listed in package.json. This command may take a while to run.

    npm install
  2. Run the server to see the example project.

    npm start
  3. Open http://localhost:3000/ in your browser. You should see Welcome to Express.

  4. In the command line, Ctrl-C stops the server.

Setup Heroku

Heroku is one of many modern web hosting services, and it uses git for deployment.

  1. Sign up to create your free account on Heroku. Don’t forget to validate your email!

  2. Log in to Heroku from the command-line.

    heroku login
  3. Initialize git.

    git init
  4. Create an application on Heroku. This command creates a git remote called heroku (a place to deploy to).

    heroku create
  5. To verify things worked properly, check the git remotes. You should see heroku listed.

    git remote -v
  6. Node installs dependencies in node_modules. Since we don’t want dependencies in git, let’s ignore them.

    echo "node_modules" >> .gitignore

Deploy to Heroku

Now that setup is out of the way, let’s deploy to Heroku. You do not need to repeat the Heroku setup steps for subsequent deploys.

  1. Add everything to version control.

    git add .
    git commit -m "Initial commit"
  2. Push to Heroku:

    git push heroku master
  3. Open the web application in your browser.

    heroku open
  4. At this point, you should see Welcome to Express on Heroku.

Run locally as Heroku would

  1. Heroku wants a Procfile to ensure everything’s configured right.

    echo "web: npm start" > Procfile
  2. To run as Heroku would, but locally, do:

    heroku local web
  3. Go to your server: http://localhost:5000/

Database setup

  1. Install Node.js bindings to PostgreSQL. Note that native Postgres bindings are required to test locally.

    npm install pg --save
    npm install pg-native --save
  2. Provision a database on Heroku.

    heroku addons:create heroku-postgresql:hobby-dev
  3. Read more about Heroku and databases.

  4. Write the Heroku database URL into .env, otherwise you cannot test locally.

    heroku config:get DATABASE_URL -s  >> .env
    echo .env >> .gitignore
  5. To read the .env file into process.env, install dotenv:

    npm install dotenv --save
  6. Then, in app.js, be sure to add this line to append process.env with anything listed in .env:

    require('dotenv').config();

Authentication

  1. Install bcryptjs

    npm install bcryptjs --save
  2. Install passport.js

    npm install passport --save
    npm install passport-local --save
  3. Install express-session

    npm install express-session --save
  4. Connect to the database.

    heroku pg:psql
  5. Once connected, create a login table with fields for the username, password, salt, and email. Remember: NEVER store the password directly in the database.

    CREATE TABLE users ("id" serial primary key, username text, password text);
  6. Add a user (admin) with password hello (for testing purposes only):

    INSERT INTO users (username,password) VALUES('admin','$2a$10$tXMKF036p0ZYIxF/cJEHauw/TFrcho4DXy41Kt12D3Lbnzr221hmK');
  7. The code that must change is rather intricate. Study the authentication commit in this repo carefully.

    gitk --all &

Books

  1. Connect to the database:

    heroku pg:psql
  2. Create table book (nope, it’s not normalized by any stretch):

    create table book (id serial primary key, author text, title text, published date, pages integer, language char(2));
  3. Insert a row into book:

    insert into book(author,title,published,pages,language) values('Stephen King', 'Misery', '1988-01-01', 300, 'en');
  4. Create routes/books.js and save:

    var express = require('express');
    var router = express.Router();
    var pg = require('pg').native;
    
    /* GET home page. */
    router.get('/', function(req, response, next) {
      pg.connect(process.env.DATABASE_URL + "?ssl=true", function(err, client, done) {
        client.query('SELECT * FROM book', function(err, result) {
          done();
          if (err) {
            response.json(err);
          } else {
            response.json(result.rows);
          }
        });
      });
    });
    
    module.exports = router;
  5. Add these lines to app.js and save:

    var books = require('./routes/books');
    app.use('/books', books);
  6. Re-run the example:

    heroku local web
  7. Go to http://localhost:5000/books

Debugging

The time will come when you’ll need to debug.

# Debug code deployed to Heroku
heroku run node debug ./bin/www
# Debug local code
heroku local:run node debug ./bin/www
# debug
node debug ./bin/www

Using the debugger consists of setting breakpoints, stepping through the code, and printing information.

setBreakpoint("routes/users.js",51);
next
cont

Next steps