preface

As front-end engineers, we often want to break the dimensional wall of the front-end (not just to write pages and make interfaces hot), want to learn a back-end language, build our own services, and rush towards the full stack direction. So in my opinion, there is no better choice for us than Node.js. Node.js does not require us to learn a new language, but its ideas if learners do not have some OS, network, database related knowledge, is also a little understanding.

Interest as a driver, let’s first build our own services, write our own Restful interface to find confidence, and then go to further study it!

The official website describes Express as follows:

Based on node. js platform, fast, open, minimalist Web development framework

Although the sparrow is small and has all the five organs, it retains the flexible Node.js development framework of the smallest scale. So let’s play it together today and build our own service.

PS: The first and second sections will not describe too much of the original things, all the principles we put in the third section to realize their ownExpressMore on that

The installation

If you want to do a good job, you must first sharpen your tools. Let’s install what we have before we develop it. The builder tool is available on the website to quickly build the project, and the generated project already contains all the necessary dependencies.

npm install -g express-generator
Copy the code

Once installed, you can initialize an Express application.

express express-app
Copy the code

Project Catalog

Express - app │ app. Js │ package. The json │ ├ ─ bin │ WWW │ ├ ─ public │ ├ ─ images │ ├ ─ javascripts │ └ ─ stylesheets │ style.css. CSS │ ├─routes │ ├.js │ users.js │ ├─ exercises errorCopy the code
  • app.jsApplication initialization files include importing all application dependencies, setting the view template engine, static resource paths, importing routes, and configuring middleware
  • bin/wwwStart file, set listening port, starthttpService etc.
  • publicStatic file directory
  • routesRouting file that responds to the userhttpRequest and return the result
  • viewsView files

Interface development

Before we start development, let’s run through the code that comes with the project.

Hello Express

Start the program

cd bin
node www
Copy the code

PS: in the WWW inside the definition of the following, default does not change the program at 3000 port

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
Copy the code

After starting localhost:3000, you can see the welcome page.

Start the process

  • First of all,Node.jsLaunched thehttpThe server
  • ExpressRoute distribution is implemented internally, and is distributed to specific routes according to routing methods and pathscontrollerIn theactionlogic
  • The inputlocalhost:3000So the route is ‘/’ atapp.jsThere are two lines of code in
    app.use('/', indexRouter);
    app.use('/users', usersRouter);
    Copy the code

    This corresponds to the registration of the routing group, and the final match isroutes/index.jsThe method inside

    router.get('/'.function(req, res, next) {
        res.render('index', { title: 'Express' });
    });
    Copy the code
  • A static page is rendered inside the routeindex“And passed in the template variable
    extends layout
    
    block content
    h1= title
    p Welcome to #{title}
    Copy the code

    This corresponds to the welcome page you see.

Connecting to a Database

Before development, you still have to create a new database, and MySQL is used in this article. Install the MySQL driver.

npm install mysql --save
Copy the code

Create a DB folder under the root directory. The directory structure is as follows

Db │ dbconfig. js │ index.jsCopy the code

Index.js is our own ORM class. The following MySQL operations will be based on it, so if you are interested, you can add a DB class to Node.js

Write MySQL configuration to dbconfig.js

module.exports = {
    mysql: {
        host: 'localhost'.user: 'root'.password: '* * * * * *'.database: 'express_test'.port: 3306}};Copy the code

Next, create a database

CREATE DATABASE IF NOT EXISTS express_test;
Copy the code

Let’s create a user table

USE express_test;
CREATE TABLE IF NOT EXISTS user (
    u_id INT PRIMARY KEY AUTO_INCREMENT,
    u_account VARCHAR(100) NOT NULL,
    u_password VARCHAR(100) NOT NULL
);
Copy the code

Add the following code to app.js

const Db = require('./db/index')
global.Db = new Db.Orm();
Copy the code

Restful API development

With the above preparations in place, we are ready for our interface development. We developed two interfaces, login interface and registration interface. The parameters of the login interface and registration interface are as follows

parameter Will choose type instructions
account true string The user name
password true string password

Registered interface

Add the following code to routes/user.js:

  • To obtainaccountpasswordparameter
  • Do some validation on the parameters
  • Whether the user already exists
  • Check whether data is successfully inserted
function validate(account, password) {
  if(! account) {return {
      status: false.msg: 'User name cannot be empty'}}if(! password) {return {
      status: false.msg: 'Password cannot be empty'}}if (account.length > 24) {
    return {
      status: false.msg: 'Username cannot be larger than 24 characters'}}if (password.length > 24) {
    return {
      status: false.msg: 'Password must be no more than 24 characters'}}return {
    status: true.msg: null
  }
}

router.post('/register'.async (req, res, next) => {
  const {
    account,
    password
  } = req.body
  let userValidate = validate(account, password),
    result, user
  if(! userValidate.status) { res.end(userValidate.msg)return
  }
  let result
  try {
    result = await Db.table('user').where('u_account', account).count()
  } catch (error) {
    throw new Error(error)
  }
  if (result > 0) {
    res.end('The username already exists')
    return
  } else {
    let data = {
      u_account: account,
      u_password: md5(password)
    }
    let user
    try {
      user = await Db.table('user').insert(data)
    } catch (error) {
      throw new Error(error)
    }
    if (user.affectedRows > 0) {
      res.json({
        msg: 'Registration successful'.status: true})}else {
      res.end('error'); }}})Copy the code

Comes with an MD5 implementation of Node.js

function md5(data) {
  var Buffer = require("buffer").Buffer;
  var buf = new Buffer.from(data);
  var str = buf.toString("binary");
  var crypto = require("crypto");
  return crypto.createHash("md5WithRSAEncryption").update(str).digest("hex");
}
Copy the code

Login interface

After implementing the registration interface, let’s implement the login interface. Add the following code to routes/users.js:

  • Get parameters and verify
  • According to the user incomingaccountGo to query
  • md5User password after comparison
  • The login state after login is discussed in section 2
router.post('/login'.async (req, res, next) => {
  const {
    account,
    password
  } = req.body
  let userValidate = validate(account, password),
    result, dbPassword
  if(! userValidate.status) { res.end(userValidate.msg)return
  }
  try {
    result = await Db.table('user').where('u_account', account).find();
  } catch (error) {
    throw new Error(error)
  }
  dbPassword = result.length > 0 ? result[0].u_password : null
  if (dbPassword === md5(password)) {
    res.json({
      msg: 'Successful landing'.status: true})}else {
    res.json({
      msg: 'Please check username or password'.status: false})}})Copy the code

Upload a file

Uploading files is also a common function in the development of the interface. Next, we use Node to implement a file uploading function. Here we use a middleware called Multer. Multer is a Node.js middleware that processes form data of type multipart/form-data. It is mainly used for uploading files. NPM install multer –save Add the following route to routes/users.js:

  • Using themulterAfter that, the file information is placedreq.filesinside
  • Based on thePromiseEncapsulates a method for uploading a single file
  • And then usePromise.allUnified Management
  • If an error occurs while reading or writing a file, the processing here isresolve(err)Rather thanreject(err)To ensurePromise.allCall successful, as for the upload failed error message, on the front show it ~
var multer = require('multer');
var fs = require('fs')
var upload = multer({
    dest: '.. /public/upload_tmp/'
});

router.post('/upload', upload.any(), (req, res) = > {
  let files = [...req.files],
    pros = []
  files.forEach(file= > pros.push(uploadSingleFile(file)))
  Promise.all(pros).then(uploadFiles= > {
    res.json(uploadFiles)
  }).catch(err= > {
    res.json(err)
  })
})

function uploadSingleFile(file) {
  return new Promise((resolve, reject) = > {
    fs.readFile(file.path, (err, data) = > {
      if (err) {
        resolve(err)
      } else {
        let timestamp = +new Date(a)let path = `.. /public/images/${timestamp}-${file.originalname}`
        fs.writeFile(path, data, err= > {
          if (err) {
            resolve(err)
          } else {
            resolve({
              originalname: file.originalname,
              filename: `${timestamp}-${file.originalname}`})}})})})})}Copy the code

Accessing a static file

Express also implements static file access logic. App. use(express.static(path.join(__dirname, ‘public’)));

All we need to know is the name of the file and enter the following browser address:

http://localhost:3000/images/xxx.png
Copy the code

To access the files we uploaded ~

PM2

PM2 is a node process management tool, which simplifies many node application management tasks, such as performance monitoring, automatic restart, and load balancing. Common commands are as follows:

$pm2 start app.js - I 4 # cluster mode to start 4 app.js application instances # 4 applications will automatically load balance $pm2 start app.js App.js --name=" API "# Start the application and name it" API "$pm2 start app.js --watch # Automatically restart the application when the file changes $pm2 start script.sh # Start bash script $ $pm2 show [app-name] # display the CPU usage of each application $pm2 logs # $pm2 logs [app-name] # Flush $pm2 stop all # flush $pm2 stop all # flush $pm2 stop 0 $pm2 reload all $pm2 gracefulReload all # Graceful reload all apps in Cluster mode Cluster mode $pm2 delete all # delete all applications $pm2 delete 0 # delete application ID 0 $pm2 scale API 10 # $pm2 save # Save the list of applications. $pm2 update # Reloads the list of saved applications Save processes, kill PM2 and restore processes $ pm2 generate # Generate a sample json configuration file pm2 start app.js --node-args="--max-old-space-size=1024"Copy the code

After the pm2 is installed, we can start with pm2 start WWW -i Max

nodemon

During development, the code needs to be restarted frequently, which is very tedious. We can use the tool Nodemon, which is used to monitor the changes of the code file and automatically restart the code when it changes.

npm install -g  nodemon
nodemon www
Copy the code

The last

Personally, the leap from front end to back end is not only a linguistic difference, but also a grammatical difference that can be quickly made up for. The lack of more is the design of the database, the processing of background logic, the processing of resources and other thinking. Only with this article, throw out a brick to attract jade, the road ahead is long, I will search up and down.

Thank you for reading, if you like, you can help to click a “like” yo ~