GithubHelp home page GithubHelp logo

yued-fe / yuenode Goto Github PK

View Code? Open in Web Editor NEW
34.0 6.0 7.0 166 KB

A Nodejs framework for Yuewen Group's project. 基于koa,适用于阅文web项目的 Nodejs 前后端分离框架。

JavaScript 97.07% Shell 2.93%

yuenode's Introduction

dependencies Status devDependencies Status

新版node框架机简介

[TOC]

文件目录结构

yuenode
    |
    |-+ bash
    |
    |-+ config          // 配置文件目录
    |
    |-+ lib
    |
    |-+ logs             // 默认日志文件输出目录
    |
    |-+ node_modules
    |
    |- app.js
    |
    |- gulpfile.js
    |
    |- package.json
    |
    |- README.md

使用方法

  1. 执行 (t)npm install

  2. 如果需要线上运行,则先要执行 sudo npm install pm2 -g

  3. 配置 config/*.config.js 中的环境变量、功能开关,可以自己复制多份不同的配置文件,每次根据文件启动不同的服务

  4. 本地调试用 gulp 启动,线上用 pm2 启动,如果增加配置需要在 npm scripts 中配置好,需要注意站点配置文件 name、NODE_SITE 以及 npm script 中的命令站点名需要一致。

     以 m 站为例:
     执行 'npm run dev:m' 为 gulp 开启 m 站本地调试
     执行 'npm run start:m' 为 pm2 开启 m 站线上运行启动
     执行 'npm run reload:m' 为 pm2 重载 m 站
     执行 'npm run stop:m' 为 pm2 停止 m 站
     执行 'npm run delete:m' 为 pm2 删除 m 站进程
    
  5. 注意 NODE_ENV 变量,需要启动时输入或者手动修改配置文件

  6. 运行环境需要 node 版本 >= 6

配置文件

const NODE_ENV = process.env.NODE_ENV || 'local';

module.exports = {
  /**
   * 服务环境配置
   */
  apps: [
    {
      // 服务别名
      name: 'm',
      script: 'app.js',
      node_args: '--harmony',
      instances: 0,
      exec_mode: 'cluster',
      // 以下是日志输出选项
      out_file: 'logs/m.qidian.com/out.log',
      error_file: 'logs/m.qidian.com/err.log',
      merge_logs: true,
      // 以下是站点配置
      env: {
        // 服务端口
        IP: '0.0.0.0',
        // 服务端口
        PORT: 10500,
        // 站点配置
        config: JSON.stringify({
          // NODE服务项目别名
          NODE_SITE: 'm',
          // 当前Node服务环境
          ENV_TYPE: NODE_ENV,
          // 是否开启L5 taf平台适用
          l5_on: false,

          // 项目配置文件夹地址
          path: '/Users/shilei/qidian-git/qidian-m/.cache/config',
          // 配置文件名,默认为 server.js
          server_conf_file: 'server',
          // 动态路由映射文件或文件夹名,默认为 routermap,如果是文件夹默认加载文件夹内的index
          routermap_file: 'routes', 
          // extends文件或文件夹名,如果是文件夹默认加载文件夹内的index,没有index的话加载loader
          extends_file: 'extends',
          // 是否开启简繁体转换功能
          character_conversion: true,

          // 是否开启静态化服务
          static_server_on: true,
          // 静态化路由配合文件,默认为 static_routermap
          static_routermap_file: 'static_routermap',
          // 静态化服务原有后端接口,后端post所有页面数据,不使用此静态化接口改为空字符串即可
          static_server_cgi: '/api/v2/setData',
          // 新静态化接口,复用动态路由,使用则注意在动态路由加入static字段,后端post请求动态路由,不需要传body数据,不使用此静态化接口改为空字符串即可
          static_dynamic_router: '/api/setStatic',

          // 显示错误密码,不配置则关闭
          error_show_pwd: false,
          // 接口超时时间
          timeout: 5000,
        })
      }
    }
  ]
};

可以在模板直接使用的全局变量:YUE

// YUE
{
  ua              // [String] user-agent
  location        // [Object] location obj
  cookie          // [string] cookie string
  cookieObj       // [Object] cookie obj
  header          // [Object] header

  staticConf      // [Object] 静态配置
  envType         // [String] 当前环境
  extends         // [Object] extends 方法
}

// YUE.location
{
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'm.qidian.com:80',
  port: '80',
  hostname: 'localm.qidian.com',
  hash: null,
  search: '?a=1',
  query: { a: '1' },
  pathname: '/fans',
  path: '/fans?a=1',
  href: 'http://m.qidian.com:80/fans?a=1'
}

以往约定格式

/**
 * 项目配置文件
 * 获取你的项目相关配置
 */
module.exports.genConf = { 
  local: {
    // 模板文件根目录
    views: {
      path: path.join(__dirname, '../views'),
    },
    // 静态化文件生成根目录
    index: '/data/website/static',
    // 传入模板渲染的参数,比如静态文件路径,可以任意设置,在模板中通过 YUE.staticConf 取得
    static: {
      domains: {
        m: 'oam.qidian.com',
        apps: 'oaapps.qidian.com',
        static: 'oaqidian.gtimg.com'
      }
    },
    // 后端请求接口配置,如后端ip,l5
    cgi: {
      ip: 'devm.qidian.com',
      domain: 'devm.qidian.com',
      L5: {
        enable: false,
        conf: {
          MODID: 123,
          CMDID: 321,
        }
      }
    }
  }
}

/**
 * 模板渲染路由配置形式
 * views 和 cgi 是必需的,views 为静态模板位置,cgi 为后端接口
 * static 非必需,为静态化资源生成后存放位置,如果配置了static,则可以通过后端post路由path进行静态化
 */
module.exports = {
  'm.qidian.com/category': {
    views: '/m.qidian.com/category/index',
    cgi: '/mpage/category/index?gender=male',
    static: '/m.qidian.com/demo.html'
  }
}

/**
 * 静态化路由配置形式
 * views 和 static 是必需的,views 为静态模板位置,static 为静态化资源生成后存放位置
 * 主要兼容过去的静态化接口形式,以下为原有 static 书写规则:
 * 若为子频道页面,统一使用 channel/index.html 方式
 * 若为具体的单独页面,则使用 channel/name.html 方式
 */
module.exports = {
  '/m.qidian.com/male': {
    views: '/m.qidian.com/homepage/male.html',
    static: '/m.qidian.com/male/index.html'
  }
}

/**
 * 自定义扩展
 * 可以将一些自定义方法注入到框架机中通过 YUE.extends.{方法名} 直接调用
 */
module.exports = {
  getBookUrl: function(bookId) {
    return '/book/' + bookId + '/catalog';
  }
}

工作流程

yuenode

这里有一个丑萌的图,相信大家看完了应该是不太理解,没关系我们还有文字描述:

模板渲染

因为有些项目有多域名的情况,所以首先会将动态路由变为 path.host.config 的形式,可以支持多域名的情况。收到客户端请求后根据 path 去寻找相应的域名下的路由配置,取得 views 模板,向后端发送 cgi 取得数据,cgi 返回不为 200/301/302,则发生对应错误。返回 200 但 code 不为 0 则发生 400 错误。

向后端发送 cgi 请求前如果开启 L5 且正确配置,会从 L5 取得相应后端 ip,否则采用项目配置文件中的 cgi.ip。cgi.domain 为后端请求 headers 中的 host 字段,配置错误有可能造成后端拒绝请求。

在模板渲染时跳过 <script type="text/ejs-template"></script> 标签中的相关模板,返回客户端供客户端使用;如果开启了简繁体转换,则会根据 cookie 中的 lang 字段判断简繁体,如果 lang 为 zht,则会将内容转换为繁体输出到客户端;如果配置了 extends 则添加到模板渲染中。

框架机的模板渲染逻辑

错误处理

发生错误时,如果模板文件根目录中存在有 error/{状态码}.html(如 error 文件夹下 404.html),则渲染对应状态码的页面,否则会渲染普通 error 页面。

寻找顺序为:模板文件根目录中对应域名文件夹下 error/{状态码}.html 页面 => 模板文件根目录 error/{状态码}.html 页面 => 模板文件根目录中对应域名文件夹下 error.html 页面 => 模板文件根目录 error.html 页面 => 框架机自带 error.html 页面。顺序寻找,找到即渲染。

为兼容已有项目,请注意 error.html 页面与 error 文件夹为平级。以上为强约定,不需要配置。

pro 环境添加你配置的 error_show_pwd 到 query 可以显示错误信息。

/**
 * 完整顺序示例目录结构
 */
views
    |
    |-+ m.qidian.com
    |    |
    |    |-+ error
    |    |    |
    |    |    |- 404.html   // ① 模板文件根目录中对应域名文件夹下 error/{状态码}.html 页面
    |    |
    |    |- error.html      // ③ 模板文件根目录中对应域名文件夹下 error.html 页面
    |
    |-+ error
    |    |
    |    |- 404.html        // ② 模板文件根目录 error/{状态码}.html 页面
    |
    |- error.html           // ④ 模板文件根目录 error.html 页面

                            // ⑤ 框架机自带 error 页

/**
 * error 页面渲染变量
 */
{
  code                      // [String] statusCode
  envType                   // [String] 当前环境
  staticConf                // [Object] 静态配置
  msg                       // [String] 错误描述信息
  stack                     // [String] 错误堆栈信息
}

静态化服务

静态化一律由后端 post 请求进行发起,旧有接口需要将页面所需 data 全部 post 过来,新接口则可以复用模板渲染的路由,可以直接 post 请求模板渲染的路由 path (例如 '/api/setStatic/m.qidian.com/male'),只要在模板渲染的路由中配置好相应的 static 字段即可。

收到后端请求后,取得对应 path 的路由配置,取得 views 模板,从请求 body 中(新接口则向后端发送请求)获得数据,渲染完成后保存在 static 配置的文件路径中。

框架机的静态化逻辑

如果生成静态文件成功,后端则后收到 statusCode 为 200、body.code 为 0 的回应。否则 body.msg 为相应的原因。

关于请求

我们强烈建议客户端访问 host(包括涉及 nginx 转换的 host)、前端 routerMap 中的 host、后端接口 host(cgi.domain)以及其他可能涉及 host 的任何环节能够将 host 保持一致,这样的好处是不言而喻的。但假如实在有不可抗力导致 host 在某一环节产生了变换,框架机提供了以下方案进行容错(但不建议依赖这些方案):

  1. 如果请求 host 在 nginx 中做过变换(例如将 www.webnovel.com 转换成 en.qidian.com),可以在 nginx 转换时将客户端的真实 host 加入到请求 header 中的 x-host,这样全局变量 YUE.location 中所有 host 将为 x-host 中的 host。
  2. 如果客户端 host 与后端请求 host 不一致,后端服务可以在 框架机请求 header 中的 x-host 与 x-url 中取到框架机接收到的相应 host(这一步已经包括对 nginx 中 x-host 的获取) 与 url。

yuenode's People

Contributors

foru17 avatar nervouself avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.