[Notes on the practice of Node middle layer (1)]----Building a project framework

Foreword: This article is related to learning the practice of Node middle layer. It is recommended that you read the original text of Node middle layer practice
    by Keyon Y. Before starting this article, you can also read the following, Node middle layer practice (1) - full-stack development based on NodeJS , which is helpful for understanding the content of this article. (PS: Node Xiaobai who continues to repay debts ╮(╯▽╰)╭)

1. Scaffolding?

    Every time we start a new project, we may need to build a new scaffold according to the project requirements, and install the official recommendation according to the selected front-end framework. For example, for students who use angular2 and vue2, the official recommended installation method is to quickly build a webpack compiled and packaged project framework through dedicated angular-cli and vue-cli.
    Then, inspired by the tool, we can also develop a webpack-based project framework at the beginning of the project:

  • Use express to carry webpack-dev-middleware and webpack-hot-middleware for hot loading ;
  • Built-in dev (development environment) and production (production environment) two startup methods .

2. Technology selection

2.1 Node development framework

Choose one of express and koa

  • Express is closer to the concept of Web Framework;
  • Express has minimal functions and is a web development framework composed of routing and middleware: in essence, an Express application is calling various middleware;
  • Koa uses co as the underlying running framework, using it to completely forget when the callback function or callbackshell;
  • express has a longer history, a large installed capacity, complete documentation, and a lot of third-party middleware;
    this time, express is chosen as the node development framework.

2.2 Template engine

Directly select pug as the server-side template engine. Pug is a more flexible server-side template, and express is also very simple to configure, which is configured in the app.js file in the root directory.

// Set the type of template engine app.set('view engine','pug'); //Set the template file path app.set('views',path.resolve(_dirname,'src/Views'));

  In this way, use res.render('Home/index',{}) during express rendering to specify the corresponding page template path. The second parameter is the data content to be used in the pug page, in json format.

2.3 Asynchronous communication between the middle layer and the backend

  In fact, it is an ajax library, so I chose axios, the ajax library officially recommended by vue2, and the built-in axios.all() can proxy multiple back-end requests in the middle layer and return them together, easily implementing Bigpipe.

2.4 Modularity

  Because it is the front page of the website, SEO needs to be considered, and the front-end framework cannot be used, so another way of thinking is to use webpack+es6/AMD to achieve modularization. Therefore, using webpack as the modularization of the packer + View layer realizes modularization and componentization from the front-end level . es6 is used in the modularization of the Contorl layer, and realizes the modularization in the node middle layer .

3. Environment configuration (startup file)

  app.js, as the startup file of the project, is the configuration file of express, and also the configuration file of running the development environment/production environment.
  Through the command parameters configured when the file node is started, app.js receives the parameters, and then runs the corresponding environment.
  We need to install the cross-env plug-in

npm i --save-dev cross-env

  Configure in the script of package.json:

"scripts": {
    
    
    "start": "cross-env NODE_ENV=production node app.js",
    "dev": "cross-env NODE_ENV=dev supervisor -w app.js app",
    "build": "webpack --config build/webpack.prod.config.js"
}

  In this way, the environment parameters for node startup can be obtained by using process.env.NODE_ENV .
  Here, the development environment (dev) and the production environment (production) are configured

  • Development environment: do not compress code, open devtool to generate source-map, easy to debug code;
  • Production environment: use webpack for packaging, compression, and obfuscation operations, output the final complete code (application) to the dist directory, and then start the node server to run the application; the above code also uses the supervisor plug-in, which is to monitor
    node Configuration file (app.js) changes and automatically restarts node.
npm i --save-dev supervisor

The front-end level uses webpack-dev-middleware and webpack-hot-middleware to realize hot loading.
In this way, hot loading is realized from the middle layer to the front end.

3.1 node middle layer configuration

Under the root directory, a new config folder is created, and some commonly used configurations/parameters and methods are extracted and written in config/config.js and config/common.js.
For example, parameters such as the startup port number of the middle layer, the root directory of the application (path.resolve(_dirname,'.../')), the IP of the backend server, the description and keywords of the frontend SEO are all placed in config.js, It is uniformly introduced in all used files through the AMD specification, and it is convenient to modify.
app.js

var express = require('express');
var cookieParser = require('cookie-parser');
var path = require('path');
var localOptions = require('./build/localOptions');
var config = require('./config/config');
var bodyParser = require('body-parser');
var auth = require('./middleware/auth');
var log4js = require('./config/log4js');

process.env.NODE_ENV = process.env.NODE_ENV ? process.env.NODE_ENV : 'production';
var isDev = process.env.NODE_ENV === 'dev';
var app = express();
var port = config.port;


app.set('view engine', 'pug');
// 设置模板文件路径
if (isDev){
    
    
	app.set('views', path.resolve(__dirname, 'src/Views'));
}else {
    
    
	app.set('views', path.resolve(__dirname, 'dist/Views'));
}

// app.locals定义的键值对能在模板中直接访问
app.locals.env = process.env.NODE_ENV || 'dev';
app.locals.reload = true;

app.use(cookieParser());
app.use(bodyParser.urlencoded({
    
    extended: false}));


if (isDev) {
    
    
    // app.locals.pretty = true;
	// 开发环境,静态文件使用热插拔
	var webpack = require('webpack');
	var webpackDevMiddleware = require('webpack-dev-middleware');
	var webpackHotMiddleware = require('webpack-hot-middleware');
	var webpackDevConfig = require('./build/webpack.dev.config.js');

	var compiler = webpack(webpackDevConfig);
	// 热插拔
	app.use(webpackDevMiddleware(compiler, {
    
    
		publicPath: webpackDevConfig.output.publicPath,
		noInfo: true,
		stats: 'errors-only'
	}))
	app.use(webpackHotMiddleware(compiler, {
    
    
		heartbeat: 1000,
		noInfo: true,
	}));

	// 不能热插拔的往下执行
	var reload = require('reload');
	var http = require('http');
	var server = http.createServer(app);
	// reload(server, app);
	reload(app);
	server.listen(port, () => {
    
    
		console.log('App【dev】 is now running on port ' + port + '!');
	});

	// 静态目录设置必须有,开发环境读取的vendor.js不是内存文件;
    // 静态目录设置必须放在reload后面,避免页面引入reload.js报错
    app.use(express.static(path.join(config.root, 'src')));
    app.use('/', require(path.join(config.configRoot,'/routes')));
	
}else {
    
    
	// 线上环境不需要监听,只需开启node服务即可
	// 设置node的静态文件目录
	app.use(express.static(path.join(config.root, 'dist')));
    app.use('/',require(path.join(config.configRoot,'/routes')));
    // app.listen(process.env.PORT, () => {
    
    
    app.listen(port, () => {
    
    
		console.log('App【production】 is now running on port ' + port + '!');
    })
}

// 捕捉 404错误 传给 error路由
app.use('*', auth, (req, res, next) => {
    
    
	let err = new Error('Not Found');
	err.status = 404;
	next(err);
});

// 捕获 error,跳转至error页面
app.use((err, req, res, next) => {
    
    
	const sc = err.status || 500;
	if(err.status == 405){
    
    
		res.redirect(config.cndesignOrigin + '/Home/GuideAuthentication');
		return;
	}
	res.status(sc);
	// 此处需写入日志
	log4js.error('\r\n Status: '+ sc + "\r\n Message: " + err.message + "\r\n Href: " + localOptions.baseUrl + req.originalUrl + "\r\n User-agent: " + req.headers['user-agent']);

	res.render('Error/404', {
    
    
		error: err,
		status: sc,
		message: err.message,
		userInfo: req.userInfo_ || {
    
     hasLogin: false }
	});
});

Pay attention to the order in which the Error Handle is mounted. Generally, it is mounted under app.use() and placed at the end.
Because the Error Handle has 4 parameters, the first parameter err is thrown by next(err) in the route, so that all routes can throw an error at any time and let the Error Handle capture it.
Take a look at the directory structure:

App
├─ .babelrc                         // babel的配置
├─ ReadMe                           
├─ app.js                           // 启动文件
├─ build                            // webpack的配置文件
│    ├─ entrys.js                   // webpack打包js和css的入口文件
│    ├─ localOptions.js             // 前端开发者本地配置文件,本地ip等站点配置
│    ├─ postcss.config.js           // postcss的配置文件
│    ├─ webpack.dev.config.js       // 开发环境的webpack打包配置
│    ├─ webpack.dll.config.js       // webpack.DllReferencePlugin插件的配置文件
│    └─ webpack.prod.config.js      // 生产环境的webpack打包配置
├─ config                           // Model层文件:包括node服务器的配置、路由和代理接口
│    ├─ common.js                   // 中间层逻辑处理的公用方法
│    ├─ config.js                   // node服务器的配置
│    └─ routes                      // 路由和代理接口配置
│           ├─ default.js
│           ├─ designers.js
│           ├─ home.js
│           └─ index.js             // 路由和接口配置的入口文件
├─ package.json
└─ src                              // View层文件
       ├─ Components                // 公用组件
       │    ├─ base
       │    ├─ home
       │    ├─ index
       │    ├─ message
       │    ├─ modals
       │    ├─ page
       ├─ Views                     // 页面
       │    ├─ Default
       │    ├─ Error
       │    ├─ Home
       │    ├─ Include
       │    ├─ Messages
       │    └─ Shared
       └─ assets                    // 静态文件目录
              ├─ Jcrop
              ├─ es5-shim-master
              ├─ images
              ├─ jquery-1.10.2.min.js
              ├─ jquery-ui-1.8.24.min.js
              └─ layui

Reference blog:

Node middle layer practice (2) - build project framework https://juejin.cn/post/6844904191605866510

おすすめ

転載: blog.csdn.net/qq_26780317/article/details/125809741