/Node-how-to

The basic how to do's for Node.js

Primary LanguageJavaScript

How to Node.js

Errors

Support for the experimental syntax 'jsx' isn't currently enabled

View Content

๐Ÿ”— Reference


This is an error that you will see if you're jest to test react applications. This solution can also fix several other errors like

  • Unexpected token โ€œ<โ€
  • โ€œCannot use import statement outside a moduleโ€

Basically the way to resolve this issue is to add react presets within a babel.config.js. If you have set up jest yet, then go here

  1. If you have not installed these babel packages then you should right now.
 npm i -D @babel/preset-env @babel/preset-react
  1. Next, create a babel.config.js file and insert this code
module.exports = {presets: ['@babel/preset-env','@babel/preset-react']}
  1. What I found out is that when you added these presets you don't receive this error message, when you run jest that might a jsx component within the file.

go back ๐Ÿ 

how to setup jest with react

View Content

๐Ÿ”— Reference


I'm going to assume that you already installed react and got a react app up and running

  1. So first install jest
npm i -D jest
  1. Now in the package.json, add this in the scripts section. This will allow you to run jest with any cofigurations that you are going to put in the jest.config.js
{
  ...
  "scripts": {
    "start": "webpack serve --config ./webpack.config.js --mode development",
    "test": "jest --config jest.config.js",
    "test:watch": "npm run test -- --watch",
  },
  ...
}
  1. Now let's vim jest.config.js and add this necessary code to look for any js files that might have the spec extension
module.exports = {
  "testRegex": "((\\.|/*.)(spec))\\.js?$"
}
  1. If you have not installed babel libraries that are needed for jest, here is the time to do so
 npm i -D @babel/preset-env @babel/preset-react
  1. Next, let's create a babel.config.js file in order to make sure jest does not throw any errors when you add JSX in your testing files. Add code like so
module.exports = {presets: ['@babel/preset-env','@babel/preset-react']}
  1. Now if you already have an App.js file, create a App.spec.js file and add code like so. This will be a general assertion to just to see if jest is running.
import React from "react";


describe('My Test Suite', () => {
  it('should show my first test', () => {
    expect(true).toEqual(true);
  });
});
  1. Now run npm run test, jest should start running and the result should pass.

go back ๐Ÿ 

nodemon: port 3000 is already in use app crashed

View Content

๐Ÿ”— Reference


Basically this error message would happen when nodemon tries to set the application to certain port ( in this case it's 3000), and the node application is still running on that port. Many times, the node application is still running even when you restart nodemon. So, the best thing to do is to install kill-port package that will allow you destroy the process based on the port number when you tell nodemon to restart or if nodemon crashes. This works sometimes but it don't work all the time

  1. First install kill-port package
 npm i -D kill-port
  1. Now create a nodemon.json, that will allow the options to kill/destroy the process with the specific port number. Add this code
{
  "events": {
    "restart": "kill-port 3000",
    "crash": "kill-port 3000"
  },
  "delay": "1500"
}
  1. Now you can run nodemon index.js or whatever command you run and it should be able to run and kill processes when nodemon restarts or crashes

go back ๐Ÿ 

how to setup react with webpack

View Content

๐Ÿ”— Reference


  1. First install react & webpack libraries
npm i react react-dom ; npm i -D webpack webpack-cli
  1. Next create a directory that will hold the react files. So in the terminal type mkdir src or whatever you want your folder to be named. Then create the App.js file, and add the basic code like so.
import React from "react";

export default function App() {
  return <h1>Hello World</h1>;
}
  1. Now, create the index.js file that will render the react file like so.
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("app"));
  1. Next install the babel loaders that will compile your react code so that can be used in the browser
npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader
  1. Now it's time to create the webpack file. So you can vim webpack.config.js, and add this code like so to your config file
const path = require("path");
module.exports = {
  entry: "/src/index.js",
  output: { path: path.resolve(__dirname, "public/js/") },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env", "@babel/preset-react"],
          },
        },
      },
    ],
  },
  mode: "development",
  watch:true,
};
  1. Now in your package.json, add a webpack script that you can call when you do npm run ... like so
  "scripts": {
    "build": "webpack" // in the scripts property add this code
  },

  1. So now you if put in the the terminal npm run build, webpack would be in watch mode and will compile your code to the designated output property. So in this example it would be public/js/main.js. If you want to change the name of the output file you have to add the filename property inside the output object of the webpack object..

go back ๐Ÿ 

how to set up a basic node.js application

View Content

๐Ÿ”— Reference


  1. first create a new folder and type npm init
  2. now install express npm i express --save
  3. now install dependencies that's needed
 npm i  body-parser cookie-parser cors debug crypto dotenv
  1. create the index js file that is supposed to initialize the express app
const express = require('express')
const app = express()
const port = 3005 // choose the port that is opened in your environment

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
  1. add this code to add the dependencies that you've installed to get the app up and running
var express = require('express');
var body = require('body-parser');
var cookie = require('cookie-parser');
var path = require('path');
var app = express();
var ip =  process.env.IP || 'localhost'; // change the IP address to get your 
var cors = require("cors");
var port = process.env.PORT || 3001;
require('dotenv').config();



app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(body.json());
app.use(body.urlencoded({extended:true}));
app.use(cookie());

app.get("/", function(req, res){
  res.send("Welcome Home")
})
app.use(function(req,res,next){
	if(res.status(404)){
	  res.render('error/400');
	}

    next();
});

app.use(function(err,req,res,next){
      if(res.status(500)){
    	  var title = err;
        res.render('error/500',{errTitle:title});
    }else if(res.status(502)){
        res.render('error/500',{errTitle:502});
    }else if(res.status(503)){
        res.render('error/500',{errTitle:503});
    }
})


app.listen(port, ip, function(){
    var n = process.env.APP_ENV;
    const code = require('crypto').randomBytes(64).toString('hex');
    console.log("node connected to "+port);
    console.log("node environment is in "+n)
})
  1. create an .env file to store your variables
 vim .env
DB_USERNAME="jermaine"
DB_PASSWORD=""
DB_PORT="1234"
PORT=1738
IP=123.123.123
DB_NAME="Test"
APP_ENV="development"
TOKEN_SECRET="9f0dc1da0366d17fa6902386c6475e75c71b0a8b09b2bae4cca27354ab304ef659b3baa212aed819a71abef7ff07e5d9ffb3be7e41004d4b9c9d33c809a535ec"
  1. create folders that are supposed to hold the mvc structure
 mkdir mvc mvc/routes mvc/models/ mvc/controllers mvc/views
  1. Create the router vim mvc/routes/router.js and add any route path that are supposed to serve information like so
var express = require('express');
var route = express.Router();

route.get("/", (req,res) => {
  res.send("this is the home page");
})

module.exports = route;
  1. Now in the app.js file require the path to the router that you created, and add it in the app.use method like so
var express = require('express');
var body = require('body-parser');
var cookie = require('cookie-parser');
var path = require('path');
var app = express();
var ip =  process.env.IP || '0.0.0.0'; 
var cors = require("cors");
var port = process.env.PORT || 3001;
var routes = require('./mvc/routes/router');// require the router so then you can serve your files
require('dotenv').config();



app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(body.json());
app.use(body.urlencoded({extended:true}));
app.use(cookie());

// app.get("/", function(req, res){
//   res.send("Welcome Home")
// })

app.use("/", routes); // this is how you can add the routes

app.use(function(req,res,next){
	if(res.status(404)){
	  res.render('error/400');
	}

    next();
});

app.use(function(err,req,res,next){
      if(res.status(500)){
    	  var title = err;
        res.render('error/500',{errTitle:title});
    }else if(res.status(502)){
        res.render('error/500',{errTitle:502});
    }else if(res.status(503)){
        res.render('error/500',{errTitle:503});
    }
})


app.listen(port, ip, function(){
    var n = process.env.APP_ENV;
    const code = require('crypto').randomBytes(64).toString('hex');
    console.log("node connected to "+port);
    console.log("node environment is in "+n)
})
  1. Install a template engine to set up your views like so
npm install handlebars express-handlebars --save
  1. Then, require the template engine and add it to the express.engine method, configuring the view path, and declaring the extension file express should look for when rendering a view
const hbs = require("express-handlebars");// requiring the handlebars

app.use(cors());
app.engine("hbs",hbs())//running the handlebars method to set up the template engine
app.set("views",path.join(__dirname,"mvc/views")); // setting the views path
app.set("view engine", "hbs" ); // setting the extension file
app.use(express.static(path.join(__dirname,'public')));
  1. Also, if you're using the handlebars method it is required to create a layouts file that is called main.handlebars, so first create directory called layouts in the views folder like so mkdir views/layouts . Then create the file add template a basic code template like this
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />  
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
    <link rel="stylesheet" type="text/css" href="./style.css" />
  </head>
  <body>
    {{{body}}}
  </body>
</html>
  1. Now in the views folder create a basic home file named home.hbs and add simple html like so . Also it is important to create a views/error/500.hbs, if you run node it will state that this file does not exist
<p> Hello, {{name}} </p>

<!-- Inside the 500.hbs -->
<p> Error 500</p>
  1. In the controller change the home method to res.render as opposed to res.send like so
// The old way
route.get("/", (req,res) => {
  res.send("this is the home page");
})

//The way to render files
route.get("/", (req,res) => {
  const data = {
    name: "Jermaine Forbes"
  }

  res.render("home",data); // The home file will render: Hello, Jermaine Forbes
})
  1. Now create a separate controller file called mvc/controllers/homeController.js and add the function that is in callback function that is in the router.js file to this new file like so.
// Inside homeController.js

module.exports.page = (req, res) => { 

  const data = {
    name: "Jermaine Forbes"
  }

  res.render("home",data); // The home file will render: Hello, Jermaine Forbes
}
  1. In the router.js file require the homeController and insert it into the second parameter of the get method like so
const express  = require('express');
const route = express.Router();
const home = require("../controllers/homeController");

// Doing this will make the code cleaner and easier to manage routes
// That are specific a page or controller
route.get("/",home.page)

module.exports = route;
  1. Next, we need to set up a model to CRUD any data. So first you need to setup mongodb on your server, here is a guide to do it in ubuntu. After your mongo has been set up, install mongoose like so.
npm i mongoose
  1. In your ./mvc/models directory create a schema.js and a db.js. The schema file is for you to define the models/documents fields that are required when you make any changes to them. And the db file is to connect to your mongodb so that when you make a CRUD change it will be saved into mongodb. Here is an example

In schema.js

const goose = require('mongoose');
const schema = goose.Schema;

// Defines a user schema
const user = new schema({
    username: String,
    password: String,
    
}, {
 timestamps:true
});


goose.model("Users", user);

In db.js

const goose = require('mongoose');
const db = goose.connection;
const dbURI = 'mongodb://localhost/test';
const settings = { useNewUrlParser: true,  useUnifiedTopology: true  };
goose.connect(dbURI, settings);

db.on('connected', function(){
    console.log("database connected");
});

db.on('error', function(err){
    console.log(err)
});

db.on('disconnected', function(){
    console.log("database disconnected");
});

// Make sure you put the schema file 
// at the bottom of the db file. I'm not sure why
// I assume after a connection has been made it will
// create the model and attach it to mongoose
require('./schema')
  1. Now, we want to create a simple form that can save user information. So in the ./mvc/views/home.hbs file we want to add in a form like so.

Note: this form is using classes from Bootstrap 4. So if you want it to look exactly like this you have to get the styles from there

<div class="container">
    <p>Hello {{name}}</p>

    <form action='/store/user' method='POST' >
    <div class="mb-3 col-4">
        <label for="exampleInputEmail1" class="form-label">Email address</label>
        <input type="email" class="form-control " name="username" id="exampleInputEmail1" aria-describedby="emailHelp">
        <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
    </div>
    <div class="mb-3 col-4">
        <label for="exampleInputPassword1" class="form-label">Password</label>
        <input type="password" class="form-control " name="password" id="exampleInputPassword1">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
    </form>

</div>
  1. Lastly, require the path to the db file in the app.js like so. This will allow the mongod database to connect on startup of the app
// In app.js require the file like so

require("./mvc/models/db");
const express = require('express');
const body = require('body-parser');
const cookie = require('cookie-parser');
const path = require('path');
const app = express();
...
  1. The last thing we need to do is to set up a route that will store the information that would be set in the form. The action at this moment has /store/user. So we need to create an endpoint that would catch the information the form is sending. So in the homeController file add this code in order to store the user's information
const goose = require("mongoose");
const User = goose.model('Users')

module.exports.home = (req, res) => {

    res.render("home", {name:'Jermaine Forbes'});
}

module.exports.storeUser = (req , res) => {
    User.create(req.body, (err, data) =>{

      //if there was any type of error, they will the error message
        if(err) return res.send(err)

      //if there is no error, then it output the data into the console, and send a message that the information has been saved
        console.log(data)
        res.send("Information has been saved")

    })

}
  1. Now, go back into the route.js file to create the end point of store/user.
const express  = require('express');
const route = express.Router();
const ctr = require("../controllers/homeController");


route.get("/",ctr.home)

// Now when the form is submitted it will store the new user information and send you a message
route.post("/store/user",ctr.storeUser)


module.exports = route;

go back ๐Ÿ 

how to use process.env

View Content

If you need to store environment variables like port numbers, passwords, or database connections then this is what you need to follow

๐Ÿ”— Reference


  1. first install dotenv
npm install dotenv --save
  1. create a .env file to add your environment variables like so
 vim .env
// inside .env

PORT=8000
PASSWORD="password"
USERNAME="username"
DATABASE="DB"
  1. in your node application make sure you require dotenv and then call the method config
// inside server or app.js
require("dotenv").config()
  1. after that you should be able to call the environment variables in any page
console.log(process.env.PORT) // should output 8000

go back ๐Ÿ 

how to upgrade nvm

View Content

๐Ÿ”— Reference


nvm install node --reinstall-packages-from=node

go back ๐Ÿ