Home > Web Front-end > JS Tutorial > Detailed explanation of front-end framework ThinkJS framework

Detailed explanation of front-end framework ThinkJS framework

小云云
Release: 2018-02-08 16:25:39
Original
7430 people have browsed it

This article mainly shares with you a detailed explanation of the front-end framework ThinkJS framework. Thinkjs is a fast and simple lightweight Node.js development framework based on MVC and object-oriented. It is released under the MIT license. Adhering to the design principle of simplicity and ease of use, while maintaining excellent performance and minimal code, it focuses on development experience and ease of use, providing strong support for WEB application development.

Many features in Thinkjs come from ThinkPHP. At the same time, according to the characteristics of Node.js, Promise, WebSocket and other features are used to make the code more concise and elegant. The biggest feature is that it has excellent support for currently popular grammatical features, such as es6, es7, typescript, etc. With these, it also supports features such as aysnc/await, making the code more fashionable.

Installation

Install the command line tool:

$ npm install -g thinkjs
Copy after login

Then create a new project using thinkjs new demo. In order to ensure that existing files are overwritten due to user errors, the thinkjs new command only applies to folders that do not exist or are empty. Otherwise, the following error will be reported:

path `/data/www/demo` is already a thinkjs project.
Copy after login

The implementation of this feature actually relies on a hidden file .thinkjsrc in the root directory of the project. Use ls -a to view the hidden file. When you open this file, you can see the following content:

{  "createAt": "2017-02-12 19:08:38",  "mode": "module",  "es": true}
Copy after login

After using the command, the system starts to build the project:

$ thinkjs new demo
  create : demo
  create : demo/package.json
  create : demo/.babelrc
  create : demo/.thinkjsrc
  create : demo/nginx.conf
  create : demo/pm2.json
  create : demo/.gitignore
  create : demo/README.md
  create : demo/www
  create : demo/www/development.js
  create : demo/www/production.js
  create : demo/www/testing.js
  create : demo/www/README.md
  create : demo/www/static
  create : demo/www/static/js
  create : demo/www/static/css
  create : demo/www/static/img
  create : demo/src
  create : demo/src/common/bootstrap
  create : demo/src/common/bootstrap/middleware.js
  create : demo/src/common/bootstrap/global.js
  create : demo/src/common/config
  create : demo/src/common/config/config.js
  create : demo/src/common/config/view.js
  create : demo/src/common/config/db.js
  create : demo/src/common/config/hook.js
  create : demo/src/common/config/session.js
  create : demo/src/common/config/error.js
  create : demo/src/common/config/env
  create : demo/src/common/config/env/development.js
  create : demo/src/common/config/env/testing.js
  create : demo/src/common/config/env/production.js
  create : demo/src/common/config/locale
  create : demo/src/common/config/locale/en.js
  create : demo/src/common/controller
  create : demo/src/common/controller/error.js
  create : demo/view/common
  create : demo/view/common/error_400.html
  create : demo/view/common/error_403.html
  create : demo/view/common/error_404.html
  create : demo/view/common/error_500.html
  create : demo/view/common/error_503.html
  create : demo/src/home/config
  create : demo/src/home/config/config.js
  create : demo/src/home/controller
  create : demo/src/home/controller/base.js
  create : demo/src/home/controller/index.js
  create : demo/src/home/logic
  create : demo/src/home/logic/index.js
  create : demo/src/home/model
  create : demo/src/home/model/index.js
  create : demo/view/home
  create : demo/view/home/index_index.html

  enter path:
  $ cd demo

  install dependencies:
  $ npm install

  run the app:
  $ npm start
Copy after login

It should be noted that when creating a new project, a lot of babel is needed, so the project construction will be slower. The main dependent packages are: :

 "dependencies": {    "thinkjs": "2.2.x",    "babel-runtime": "6.x.x",    "source-map-support": "0.4.0"  },
Copy after login

Directory

.├── README.md
├── app
│   ├── common
│   │   ├── bootstrap
│   │   ├── config
│   │   └── controller
│   └── home
│       ├── config
│       ├── controller
│       ├── logic
│       └── model
├── nginx.conf
├── package.json
├── pm2.json
├── src
│   ├── common
│   │   ├── bootstrap
│   │   ├── config
│   │   └── controller
│   └── home
│       ├── config
│       ├── controller
│       ├── logic
│       └── model
├── tree.txt
├── view
│   ├── common
│   │   ├── error_400.html
│   │   ├── error_403.html
│   │   ├── error_404.html
│   │   ├── error_500.html
│   │   └── error_503.html
│   └── home
│       └── index_index.html
└── www
    ├── README.md
    ├── development.js
    ├── production.js
    ├── static
    │   ├── css
    │   ├── img
    │   └── js
    └── testing.js388 directories, 1381 files
Copy after login

Startup process analysis

1) Start command

npm start
Copy after login

What does the system do after using start?

 "scripts": {    "start": "node www/development.js",    "compile": "babel src/ --out-dir app/",    "watch-compile": "node -e \"console.log(&#39;<npm run watch-compile> no longer need, use <npm start> command direct.&#39;);console.log();\"",    "watch": "npm run watch-compile"  },
Copy after login

Use Node to execute www/development.js. This is env environment processing. Thinkjs uses 3 envs. The more common ones are:

  • development development mode

  • production online mode

  • testing test mode

thinkjs treats www as a node project directory, and static under www is the static resource file directory. The www/development.js directory is as follows:

var instance = new thinkjs({
  APP_PATH: rootPath + path.sep + &#39;app&#39;,
  RUNTIME_PATH: rootPath + path.sep + &#39;runtime&#39;,
  ROOT_PATH: rootPath,
  RESOURCE_PATH: __dirname,
  env: &#39;development&#39;});
Copy after login

Of course, you can use the "tree src -L 3" command to view the project directory:

$ tree src -L 3         src
├── common
│   ├── bootstrap
│   │   ├── global.js
│   │   └── middleware.js
│   ├── config
│   │   ├── config.js
│   │   ├── db.js
│   │   ├── env
│   │   ├── error.js
│   │   ├── hook.js
│   │   ├── locale
│   │   ├── session.js
│   │   └── view.js
│   └── controller
│       └── error.js
├── home
│   ├── config
│   │   └── config.js
│   ├── controller
│   │   ├── base.js
│   │   └── index.js
│   ├── logic
│   │   └── index.js
│   └── model
│       └── index.js16 directories, 19 files
Copy after login

Common module configuration (will be discussed in detail later) :

$ thinkjs module topic(能创建不能删除,略遗憾)

  create : src/topic/config
  create : src/topic/config/config.js
  create : src/topic/controller
  create : src/topic/controller/base.js
  create : src/topic/controller/index.js
  create : src/topic/logic
  create : src/topic/logic/index.js
  create : src/topic/model
  create : src/topic/model/index.js
  exist : /Users/sang/workspace/github/nodewebframework/demo/view/topic/index_index.html
Copy after login

The directory structure at this time is as follows:

src
├── common
├── home
└── topic
Copy after login

3) Business module directory

├── home
│   ├── config
│   │   └── config.js
│   ├── controller
│   │   ├── base.js
│   │   └── index.js
│   ├── logic
│   │   └── index.js
│   └── model
│       └── index.js
Copy after login

4) Routing and view identification Route identification, by default, is based on module/controller/operation/parameter 1/parameter 1 value/parameter 2/parameter 2 value, which is actually a convention.

For example/resolved as:

  • The default module is home

  • The control is index

  • The operation is indexAction

What if there is another one?

&#39;use strict&#39;;import Base from &#39;./base.js&#39;;export default class extends Base {  /**
   * index action
   * @return {Promise} []
   */  indexAction(){    //auto render template file index_index.html    return this.display();  }  myAction(){    //auto render template file index_index.html    return this.display();  }}
Copy after login

Add myAction and report an error [Error] Error: can't find template file /Users/sang/workspace/github/nodewebframework/demo/view/home/index_my.html

Change view /home/index_index.html is copied to view/home/index_my.html. The principle is that my should correspond to the index_my.html module. That is, index is controller, and my is action.

After understanding this, you will feel that naming index_index is not very weird. The rest is view writing and the like, which will not be described here.

Performance

As mentioned earlier, the development phase is written in Babel, so the efficiency will not be very high.

$ autocannon -c 100 -d 5 -p 10 localhost:8360Running 5s test @ http://localhost:8360100 connections with 10 pipelining factor

Stat         Avg       Stdev    Max       
Latency (ms) 108.9     201.32   866       Req/Sec      891.8     148.37   1000      Bytes/Sec    417.79 kB 50.76 kB 458.75 kB 

4k requests in 5s, 2.09 MB read
Copy after login

A bit miserable, right? But this is development mode, and we must use the online production mode to test it.

$ npm run compile
$ node www/production.js 
$ autocannon -c 100 -d 5 -p 10 localhost:8360Running 5s test @ http://localhost:8360100 connections with 10 pipelining factor

Stat         Avg       Stdev     Max       
Latency (ms) 61.76     124.71    763       Req/Sec      1567.2    734.94    1993      Bytes/Sec    679.12 kB 242.25 kB 884.74 kB 

8k requests in 5s, 3.4 MB read

$ autocannon -c 100 -d 5 -p 10 localhost:8360Running 5s test @ http://localhost:8360100 connections with 10 pipelining factor

Stat         Avg       Stdev     Max      
Latency (ms) 54.65     105.47    707      Req/Sec      1813.4    368.21    1999     Bytes/Sec    807.73 kB 156.09 kB 917.5 kB 

9k requests in 5s, 4.09 MB read

$ autocannon -c 100 -d 5 -p 10 localhost:8360Running 5s test @ http://localhost:8360100 connections with 10 pipelining factor

Stat         Avg       Stdev     Max     
Latency (ms) 54.14     89.81     465     Req/Sec      1816.4    319.14    2000    Bytes/Sec    914.23 kB 145.96 kB 1.05 MB 

9k requests in 5s, 4.55 MB read
Copy after login

The following uses the same function express + ejs template.

$ autocannon -c 100 -d 5 -p 10 localhost:3000Running 5s test @ http://localhost:3000100 connections with 10 pipelining factor

Stat         Avg       Stdev     Max       
Latency (ms) 53.85     177.72    1309      Req/Sec      1728      385.85    2075      Bytes/Sec    702.87 kB 159.56 kB 851.97 kB 

9k requests in 5s, 3.53 MB read

$ autocannon -c 100 -d 5 -p 10 localhost:3000Running 5s test @ http://localhost:3000100 connections with 10 pipelining factor

Stat         Avg       Stdev     Max       
Latency (ms) 46.06     141.52    739       Req/Sec      2061.2    320.53    2275      Bytes/Sec    842.14 kB 134.95 kB 950.27 kB 

10k requests in 5s, 4.2 MB read

$ autocannon -c 100 -d 5 -p 10 localhost:3000Running 5s test @ http://localhost:3000100 connections with 10 pipelining factor

Stat         Avg       Stdev    Max       
Latency (ms) 45.97     139.58   620       Req/Sec      2059.4    122.93   2167      Bytes/Sec    829.03 kB 52.43 kB 884.74 kB 

10k requests in 5s, 4.2 MB read
Copy after login

Module decomposition

After creating the project, the basic code framework has been established, and the default home and common are definitely unable to meet the requirements. We need to establish a relevant hierarchical structure for our projects. Here are some common module classification methods. for reference only.

Simple website

Official websites, blogs, communities, etc. This type of system structure is relatively simple, and usually one front-end and one back-end management can meet the requirements. Usually the following modules need to be included:

src/src/common/  # 通用模块,放置主配置参数、boostrap adapter middleware service 等相关组件
src/home/  # 前端默认模块
src/backend/  # 后端管理模块
src/util/  # 系统工具类
Copy after login

E-commerce platform

The e-commerce platform system mainly takes into account the user groups such as settled merchants, registered customers, managers, and operating personnel. It also needs to consider Segmentation of larger functional modules (if it is large enough to be a system similar to JD.com and Tmall, it needs to be segmented from data, functions, services, locations, etc.).

src/src/common/src/home/src/sso/  # 单点登录、令牌管理等
src/rest/  # 针对Wap、App等多客户端的 rest api
src/goods/  # 商品管理及服务
src/storage/  # 库存管理及服务
src/cart/  # 购物车
src/order/  # 订单
src/delivery/  # 快递
src/pay/  # 在线支付、空中支付
src/member/  #
src/coupon/  # 电子券
src/promotion/  # 促销
src/points/  # 积分
src/merchant/  # 入驻商户
src/shop/  # 商户门店
src/finance/  # 财务核算及款项清算
src/stat/src/log/src/monitor/src/util/src/task/src/message/  # 消息队列
Copy after login

Instant messaging platform

The real-time push platform not only handles WebSocket connections and message hoarding and sending, but also handles multiple users purchasing corresponding service packages, counting the number of connections, counting downstream traffic, and making connections. Authentication, etc. The modules usually included are as follows:

src/src/common/src/home/src/rest/src/storage/src/websocket/  # ws 或者 wss 服务
src/webhook/  # 钩子服务
src/middleware/  # 搭载中间件运行
src/pay/src/member/src/stat/src/log/src/monitor/src/util/src/message/  # 消息队列
Copy after login

Online education, live broadcast platform

Online education or live broadcast platforms usually have hard requirements such as real-time audio and video uploading, transcoding, storage, and broadcasting. Therefore, in addition to management, the system Related courseware, students, teachers, course selections, etc., and also responsible for processing related media files.

src/src/common/src/home/src/rest/src/sso/  # 单点登录、令牌管理等
src/media/  # 课件、音视频等媒体文件
src/bulk/  # 流媒体
src/process/  # 编解码处理
src/storage/src/live/  # 直播
src/pay/src/student/src/teacher/src/schedule/src/stat/src/log/src/monitor/src/util/src/task/src/message/  # 消息队列
Copy after login

Parameter configuration

The official website describes the configuration file loading sequence as follows: framework default configuration-> framework configuration in project mode-> project public configuration-> project mode Public configuration-> Configuration under module.

第三个和第四个则是在不同的项目创建模式下的默认 config 配置文件夹,位置在:

# normal mode
thinkjs_normal/src/config/*
# module mode
thinkjs_module/src/common/config/*
Copy after login

最后一个是指的在 module mode 下的项目,每个 module 自己的 config,位置在:

thinkjs_module/src/home/config/*
Copy after login

明白了多个地方多个配置文件的玩法之后,你可以创建多个 module,并给每个 module 配置自身独特的配置参数。

需要注意的是:thinkjs 加载配置文件是有顺序的!!!多个配置文件最终会在 thinkjs 运行时被全部加载,并合并在一起。所以当存在多个配置文件时,需要注意配置参数的 key(即属性名)尽量不要重复,因为按照加载顺序,后加载的 key 的值会覆盖先加载的 key 的值,导致出现不希望的结果。

举例来说,有两个配置文件 src/common/config/assets.js 和 src/home/config/assets.js,

// src/common/config/assets.jsexport default {  "site_title": "my site"};// src/home/config/assets.jsexport default {  "site_title": "my test"};// src/home/controller/index.jslet assets = this.config(&#39;assets&#39;);let siteTitle = assets[&#39;site_title&#39;];console.log(&#39;siteTitle is: &#39;, siteTitle); // my test
Copy after login

Babel 编译时删除注释

开发时的工作代码都在 src 下面,运行时才会编译到 app 下面成为运行脚本(经过 Babel 编译),如果不想自己写的各种注释也出现在 app 下面的代码中,可以修改项目目录下的一个隐藏文件 .babelrc 增加相应 comments 参数。

{  "presets": [    ["es2015", {"loose": true}],    "stage-1"  ],  "plugins": ["transform-runtime"],  "sourceMaps": true,  "comments": false  # <-- 就是这个参数}
Copy after login

controller

目前,thinkJs支持两种控制器:普通的控制器和多级控制器。 支持__before和__after这样的回调钩子,对于app和controller控制来说是非常实用的。使用co来实现也是可圈可点,此处如果使用koa可以更加优雅。例如:

class PathController extends BaseController {  constructor(app, ctx, next) {    super(app, ctx, next)    this.path = &#39;/c&#39;    // this.global_filter.push(&#39;custom_filter&#39;)    this.post_filter = [this.log]  }  before() {  }  log(ctx, next) {
    ctx.someText = &#39;some&#39;    // console.log(&#39;before&#39;)    return next().then(function(){      // console.log(&#39;after&#39;)    })  }  post(req, res) {
    console.log(this.ctx.someText)    var a = this.reqbody.a    return res.body = this.ctx.someText  } 

  after() {  }}
Copy after login

修改 pm2 日志位置

pm2 (官网 http://pm2.keymetrics.io)是一个优秀的 Node.js 进程管理器。thinkjs 推荐使用 pm2 来管理项目运行,并自动生成了 pm2 的配置文件 pm2.json 。

它的强大之处在于不仅可以作为 Node.js 项目的守护进程,还具备可配置化启动、分布式支持、内存监控、热重载(优雅重载)、支持数据统计、运行日志记录、实时运行监控、API 和脚本支持等强大的特性。

默认生成的 pm2 配置文件不含日志记录部分,如果不单独配置,pm2 的日志将会保存在安装目录中,查找起来很不方便。普遍的做法是:在项目目录下建立 logs 文件夹,用来放置 pm2 以及其他(诸如 log4js 等等)日志,打开 pm2.json ,给 apps[0] 增加如下几行配置参数:

{  "apps": [{    "error_file"      : "/data/www/thinkjs_module/logs/pm2-err.log",    "out_file"        : "/data/www/thinkjs_module/logs/pm2-out.log",    "log_date_format" : "YYYY-MM-DD HH:mm:ss Z",    "merge_logs"      : false  }]}
Copy after login
  • error_file pm2 捕捉到的致命错误记录在这里

  • out_file pm2 接收到的 console 输出记录在这里

  • log_date_format 日期和时间格式

  • merge_logs 是否给日志文件增加进程id的后缀

总结

主要优势:

  • 完全自己实现,对已有框架很少借鉴

  • 内置各种adapter,db,中间件,hook,插件,非常丰富,all in one 比组装更适合新手

  • 遵循mvc和coc

  • 使用最潮的es6/es7/ts特性,对aysnc函数,exports等都非常好的支持

  • 支持i18n等实用功能

  • 内置pm2和nginx集成,部署方便

  • 有自己的脚手架,稍弱

  • 性能不错,虽然比express稍弱,但功能强大许多

  • 测试丰富,代码质量有保障

  • 文档健全,是经过设计的,支持多语言

  • 背后有75团和李成银支持,最近一周内有更新,代码提交2600+,35人贡献,整体来说算健康

附:ThinkJS官网文档

相关推荐:

实例讲解thinkjs 文件上传功能

Node.js框架 ThinkJS 开发 controller讲解

ThinkJS 开发 config 实例教程

The above is the detailed content of Detailed explanation of front-end framework ThinkJS framework. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template