preface

Nodejs is a basic framework for building network applications. Developers can build servers, clients, command line tools and other applications based on NodeJS. Nodejs is now a necessary technology in the front end, so I’ll take you through the basics and build server applications using Express.

The characteristics of nodejs

Asynchronous I/O

In NodeJS, most operations are done asynchronously in an event loop. This allows each I/O call to be executed without waiting for the previous I/O to complete, making NodeJS ideal for I/O intensive scenarios. Personally, I understand that synchronous blocking should be used less to write business logic in spite of synchronous programming such as async/await. Specific can use another article to say. (holes)

Events and callback functions

In JS, functions are the first citizens, and it is common to see functions passed in as arguments, which we call callback functions. Using the callback function makes it possible to decouple events from each other (each event is a separate function) in multiple asynchronous task scenarios, allowing loose coupling of our code.

But there are drawbacks to writing code in this mode. Writing code using event callbacks is bound to result in a mismatch between the order in which the code is written and the order in which it is executed, making it harder to read. On the other hand, increasing the number of nested callback functions creates the problem of callback hell (which can be solved with promises).

Single thread

Node retains the single-threaded nature of JS in the browser. This means that node.js does not have the performance overhead of thread locking (deadlocks), sharing state, and exchanging contexts that multithreaded languages do. But at the same time, single threading also has the following disadvantages

  • Cannot compute with multi-core CPUS.
  • Errors can cause the entire application to exit.
  • A large number of calculations occupy the CPU, causing asynchronous I/O calls to fail.

Node uses child threads to solve the cpu-hogging problem by distributing a large number of computations to multiple child processes, and then passing on the results via event messages when the computations are complete.

cross-platform

To enable event drivers to be used across platforms, nodeJS has a platform-layer architecture called Libuv between its upper modules and the operating system. See the image below (from Node.js) :

Libuv is a library written to enable NodeJS to use asynchronous I/O across multiple platforms. The event loop algorithm in Libuv has different implementations for different platforms, as shown in the following table:

system Event loop algorithm
linux epoll
OSX Kqueue or BSD
SunOS event ports
Windows IOCP

Application scenarios

I/O intensive

Node uses the event loop processing capability to perform I/O processing with minimal resource usage. Such as Web applications, chat applications and so on.

CPU intensive application scenarios

Using child threads, you can use a portion of Node processes as resident server processes for computation, and then take advantage of inter-process messaging results to separate computation from I/O, allowing you to take advantage of multiple cpus. Therefore, Node can also be competent for CPU-intensive services. The key is how to arrange scheduling reasonably.

Nodejs in B/S

In B/S architecture, NodeJS can be used where I/O is frequent, such as receiving requests → sending requests → asynchronously retrieving data for assembly → returning it to the front end. Roughly as shown in the figure below.

Module mechanism in NodeJS

Nodejs prior to 13.2.0 only supports a set of module reference standards implemented by referring to the CommonJS specification. The ES specification supports import after 13.2.0.

In NodeJS, there are three main steps to introduce modules:

  1. Path analysis.
  2. File location.
  3. Compile execution.

Nodejs modules are divided into core modules and file modules.

The core module

The core module is divided into JS core module and C/C++ core module.

  • The js core module is compiled to generate C/C++ code using V8’s js2. Py.
  • Core modules written in C/C++ are compiled into binaries and loaded directly into memory once NodeJS starts executing. Buffer, Crypto, EVals, FS, OS and other modules are partly written by C/C++.

Setting up the Express Server

After talking about the basic concepts and features of NodeJS, we started to build a simple Express service step by step.

Initialize the project

Install typescript first.

npm install -g typescript
Copy the code

Create file rack Node-server, go to folder and use NPM init to initialize the project. Then use tsc-init to generate tsconfig.json. Detailed configuration can be seen here, the following is the author’s configuration.

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es6"./* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs"./* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    // "lib": [], /* Specify library files to be included in the compilation. */
    "allowJs": true./* Allow javascript files to be compiled. */
    "outDir": "dist"./* Redirect output structure to the directory. */
    /* Strict Type-Checking Options */
    "strict": true./* Enable all strict type-checking options. */
    "noImplicitAny": true./* Raise error on expressions and declarations with an implied 'any' type. */
    "noImplicitThis": true./* Raise error on 'this' expressions with an implied 'any' type. */
    /* Module Resolution Options */
    "moduleResolution": "node"./* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "baseUrl": ". /"./* Base directory to resolve non-absolute module names. */
    "paths": {
      "*": ["node_modules/*"."src/types/*"]."@ / *": ["src/*"]},/* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    "esModuleInterop": true./* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    "skipLibCheck": true./* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true        /* Disallow inconsistently-cased references to the same file. */
  },
  "include": ["src"].// The ts files to compile, set this to all files in the SRC directory
  "exclude": ["node_modules"].// Compile the directory of files to exclude
}
Copy the code

Install dependencies

Start by installing Express, Body-Parser, Compression, and typescript

npm install --save-dev typescript
npm install --save body-parser
npm install --save-dev @types/body-parser
npm install --save compression
npm install --save-dev @types/compression
npm install --save express
npm install --save-dev @types/express
Copy the code
  • Body-parser: Parses JSON data and form data from requests sent by the client.
  • Compression: Compresses the request and response.

Next we create some new files and folders to build the entire application.

Configuration eslint

Using ESLint to constrain code styles, install dependencies first

npm install --save-dev @types/eslint eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
Copy the code

Write.eslintrc files

{
  "parser": "@typescript-eslint/parser"."extends": ["plugin:@typescript-eslint/recommended"]."parserOptions": {
    "ecmaVersion": 2018."sourceType": "module"
  },
  "rules": {
    "semi": ["error"."always"]."quotes": ["error"."single"]."@typescript-eslint/explicit-function-return-type": "off"."@typescript-eslint/explicit-module-boundary-types": "off"."@typescript-eslint/no-explicit-any": 1."@typescript-eslint/no-inferrable-types": [
      "warn", {
        "ignoreParameters": true}]."@typescript-eslint/no-unused-vars": "warn"}}Copy the code

Write eslintignore.

# /node_modules/* in the project root is ignored by default
# build artefacts
dist/*
coverage/*
# data definition files
**/*.d.ts
# 3rd party libs
/src/public/
# custom definition files
/src/types/
Copy the code

Write the app.ts file

The app.ts file is mainly used to register routes and middleware.

import bodyParse from 'body-parser';
import express from 'express';
import { NextFunction, Request, Response } from 'express';
import compression from 'compression';

const app = express();

/* Middleware */

/ / compression
app.use(compression());

// Request parsing json
app.use(bodyParse.json({ limit: '20mb' }));
// Request formData parse
app.use(
  bodyParse.urlencoded(
    {
      limit: '20mb'.extended: false}));Routing / * * /
app.get('/test'.function (req: Request, res: Response) {
  res.json({
    hello: 'www'
  });
});

export default app;
Copy the code

Configure the server

Create index.ts in config folder to set the port for the service.

export type SystemConfig = {
  port: number
}
export const systemConfig: SystemConfig = {
  port: 8003
};
Copy the code

Introduced in server.ts.

import app from './app';

import { systemConfig } from './config';

const server = app.listen(systemConfig.port, function() {
  console.log(`server is listening at port ${systemConfig.port}`);
});

export default server;
Copy the code

Compile and hot update

Ts does not run directly, so ts-Node is used for compilation. However, it would be troublesome to compile ts-Node every time you change the code, so nodemon is used here to check and hot update. To load tsconfig.json in the directory at Runtime, you must use tsconfig-paths.

Install dependencies first.

npm install --save-dev tsconfig-paths ts-node nodemon cross-env
Copy the code

Write the command in script of package.json.

{
	"scripts": {
    "dev": "cross-env nodemon --watch 'src/' -e ts --exec 'ts-node' -r tsconfig-paths/register ./src/server.ts --files"}}Copy the code

run

Direct NPM run dev run, run after visit http://localhost:8003/test can appear the following result.

{ hello: 'www' }
Copy the code

Summary & reference source code

Express is a very simple project to build. If you want to write a real API and middleware folder, you can refer to my express project github.com/Lstmxx/easy… .

reference

  • Node.js
  • Docs.libuv.org/en/latest/d…