• PM2与Babel踩坑


    PM2与Babel踩坑

    PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。官方文档 中文快速入门

    Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。官方文档 中文

    项目背景

    node服务,采用es6语法,import模块导入、async/await语法糖、箭头函数等等,以及koa-swagger-decorator自动生成swagger.json(api接口的注解,通过注解在swagger页面展现出每个api接口的详细描述)
    项目部署采用pm2,集群 + 环境区分(开发、测试、生产)

    babel

    如果使用koa-swagger-decorator,在github仓库中说明了使用时依赖babel-plugin-transform-decorators-legacy这个babel插件,但是This plugin is specifically for Babel 6.x. If you're using Babel 7, this plugin is not for you.(npm原话),如果你使用Babel7的话,你可以使用@babel/plugin-proposal-decorators, 但是在.babelrc中必须如下设置

    "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ]
    

    好, 我们用babel-7.4.0试一下 安装babel依赖

    "dependencies": {
        "@babel/cli": "^7.4.4",
        "@babel/core": "^7.4.5",
        "@babel/plugin-proposal-decorators": "^7.4.4",
        "@babel/plugin-transform-runtime": "^7.4.4",
        "@babel/preset-env": "^7.4.5",
        "@babel/runtime": "^7.4.5",
        "@babel/runtime-corejs3": "^7.4.5",
        ...你的其他依赖
    }
    

    完整的.babelrc配置

    {
        "presets": [
            ["@babel/preset-env", {
                "targets": {"node": true},
                } 
            ]
        ],
        "plugins": [
        // 可以做到最小化加载babel-polyfill减小项目体积,虽然在node环境中无所谓
            ["@babel/plugin-transform-runtime", {
                "corejs": 3 // 可选 false | 2 | 3
            }],
            ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ]
    }
    

    ok 通过上述的babel安装及.babelrc设置试一试转码

    • 入口文件app.js
    import config from './config'
    import eurekaServer from './eureka'
    import {connectDB} from './db'
    import Koa from 'koa';
    import router from './swagger/index'
    import responseHandler from './middleware/response_handle'
    import mqServer from './mq/MQServer'
    import cron from './cron'
    
    const koaCors = require('koa-cors');
    const koaBody = require('koa-body');
    const app = new Koa();
    async function initApp (){
        //连接mysql
        await connectDB();
        //连接mq
        await mqServer.connect();
        //启动Eureka
        await eurekaServer.start();
        //Eureka心跳
        app.use(eurekaServer.info()); 
        //启动定时拉取微信公众号图文及统计任务
        await cron();
        app.use(async function (ctx, next) {
            ctx.response.get("Access-Control-Allow-Origin", "*");
            ctx.response.set("Access-Control-Allow-Headers", "Content-Type,Content-Length,Accept,X-Requested-With,token");
            ctx.response.set("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
            if (ctx.request.method == "OPTIONS") ctx.response.status = 200;
            await next();
        })         
                
        //restful 中间件
        app.use(responseHandler.restify());
        app.use(koaCors());
        app.use(koaBody({ multipart: true }));
        app.use(router.routes());
        app.use(router.allowedMethods());
        app.listen(config.port, _ =>  console.log(`app started at port ${config.port}`));
        return app;
    }
    
    initApp()
    .catch(err => `未知服务错误:${err.message}`)
    
    
    • 项目目录
    
    src/
     'app.js',
     'config/',
     'controllers/',
     'cron/',
     'dao/',
     'db/',
     'domain/',
     'eureka/',
     'middleware/',
     'model/',
     'mq/',
     'repository/',
     'swagger/',
     'util/' 
     
    
    • 下一步 在package.json 中build
    
    "scripts": {
      "build": "babel src -d dist"
    },
    
    
    • 启动 node dist/app.js
    pan@ubuntu18:~/disk/panyanan/project/website_node$ node dist/app.js 
    加载local环境的配置文件成功
    sequelize deprecated The logging-option should be either a function or false. Default: console.log node_modules/sequelize/lib/sequelize.js:193:13
    Executing (default): SELECT 1+1 AS result
    connect MQ queues: {"queueNames":["q.upa_logs_node"],"connectOption":{"vhost":"OuterHost","hostname":"192.168.10.200","port":5672,"username":"admin","password":"123456"}}
    registered with eureka:  NTDWebsit/192.168.10.49:8989
    eureka注册成功
    koa deprecated Support for generators will be removed in v3. See the documentation for examples of how to convert old middleware https://github.com/koajs/koa/blob/master/docs/migration.md dist/app.js:47:7
    app started at port 8989
    
    

    用babel-6.0+试一下 安装依赖

    
     "dependencies": {
       "babel-cli": "^6.26.0",
       "babel-core": "^6.26.3",
       "babel-preset-env": "^1.7.0",
       "babel-plugin-transform-decorators-legacy": "^1.3.5",
       "babel-polyfill": "^6.26.0",
       ...其它依赖
       }
       
    

    .babelrc

    
    {
       "presets": [
           ["env", {
                   "targets": {"node": true},
                   //会加载所有polyfill
                   "useBuiltIns":true
               }
           ]
       ],
       "plugins": [
           "transform-decorators-legacy"
       ]
    }
    
    

    转码

    
    "scripts": {
    "build": "babel src -d dist"
      },
      
    

    bable6中转码过程会显示所有被转码的文件

    > selected@1.0.0 build /home/pan/disk/panyanan/project/website_node
    > babel src -d dist
    
    src/app.js -> dist/app.js
    src/config/config.dev.js -> dist/config/config.dev.js
    src/config/config.local.js -> dist/config/config.local.js
    src/config/config.pred.js -> dist/config/config.pred.js
    src/config/config.prod.js -> dist/config/config.prod.js
    src/config/index.js -> dist/config/index.js
    src/controllers/article_controller.js -> dist/controllers/article_controller.js
    src/controllers/category_controller.js -> dist/controllers/category_controller.js
    src/cron/articleTask.js -> dist/cron/articleTask.js
    src/cron/index.js -> dist/cron/index.js
    src/dao/article_dao.js -> dist/dao/article_dao.js
    src/dao/article_day_summary_dao.js -> dist/dao/article_day_summary_dao.js
    src/dao/category_dao.js -> dist/dao/category_dao.js
    src/db/index.js -> dist/db/index.js
    src/domain/article_domain.js -> dist/domain/article_domain.js
    src/domain/category_domain.js -> dist/domain/category_domain.js
    src/eureka/index.js -> dist/eureka/index.js
    src/middleware/response_handle.js -> dist/middleware/response_handle.js
    src/model/article_day_summary_model.js -> dist/model/article_day_summary_model.js
    src/model/article_model.js -> dist/model/article_model.js
    src/model/category_model.js -> dist/model/category_model.js
    src/mq/MQServer.js -> dist/mq/MQServer.js
    src/mq/UpalogsSendMsg.js -> dist/mq/UpalogsSendMsg.js
    src/repository/article_day_summary_repository.js -> dist/repository/article_day_summary_repository.js
    src/repository/article_repository.js -> dist/repository/article_repository.js
    src/repository/category_repository.js -> dist/repository/category_repository.js
    src/swagger/api.js -> dist/swagger/api.js
    src/swagger/index.js -> dist/swagger/index.js
    src/util/index.js -> dist/util/index.js
    
    

    启动 node dist/app.js

    pan@ubuntu18:~/disk/panyanan/project/website_node$ node dist/app.js 
    加载local环境的配置文件成功
    sequelize deprecated The logging-option should be either a function or false. Default: console.log node_modules/sequelize/lib/sequelize.js:193:13
    Executing (default): SELECT 1+1 AS result
    connect MQ queues: {"queueNames":["q.upa_logs_node"],"connectOption":{"vhost":"OuterHost","hostname":"192.168.10.200","port":5672,"username":"admin","password":"123456"}}
    registered with eureka:  NTDWebsit/192.168.10.49:8989
    eureka注册成功
    koa deprecated Support for generators will be removed in v3. See the documentation for examples of how to convert old middleware https://github.com/koajs/koa/blob/master/docs/migration.md dist/app.js:59:9
    app started at port 8989
    
    

    ok 以上就是在node服务中使用babel转码的尝试,babel中的配置及插件很多.设置起来也很麻烦,需要耐心的阅读官方文档,及前辈们的博客,总结一下基本概念.

    • babel-core 是babel的核心
    • babel-preset-env 是针对环境设置不同的转码规则
    • babel-polyfill,用于转码es6的api,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。babel 默认只转换语法 如() => {}
    • babe-runtime可以做到按需转码,减少转码后的代码体积
    • 利用useBuiltIns选项,可以不必在代码中require(bable-polyfill)
    • 通过提前build的方式可以提高性能,相比之下 babel-node则很重,内存使用率很高
    • babel6/bable7的使用有很大不同,无论是.babelrc配置还是插件

    PM2

    pm2 基础命令可以看看官方文档
    这里说一下与babel相关的小坑,如果采用上面的build的方式是没有任何问题的,只需要修改配置文件的目录为转码之后的启动文件 apps.config.js

    pm2 start apps.config.js 启动
    如果设置env 则需要加上参数如 pm2 start apps.config.js --env prod
    则process.env.NODE_ENV == 'production'

    module.exports = {
      apps : [{
        name: 'websit_node',
        script: './dist/app.js',
        args: 'one two',
        instances: 1,
        autorestart: true,
        watch: false,
        max_memory_restart: '1G',
        env: {
          NODE_ENV: 'local'
        },
        env_dev: {
          NODE_ENV: 'development'
        },
        env_pred: {
          NODE_ENV: 'pred'
        },
        env_prod: {
          NODE_ENV: 'production'
        }
      }],
    };
    

    如果采用babel-node方式启动,则需要增加解释器配置

    module.exports = {
      apps : [{
        name: 'websit_node',
        script: './src/app.js',
        args: 'one two',
        instances: 1,
        autorestart: true,
        watch: false,
        max_memory_restart: '1G',
        interpreter: 'node_modules/babel-cli/bin/babel-node.js',
        env: {
          NODE_ENV: 'local'
        },
        env_dev: {
          NODE_ENV: 'development'
        },
        env_pred: {
          NODE_ENV: 'pred'
        },
        env_prod: {
          NODE_ENV: 'production'
        }
      }],
    };
    

    注意:

    • script字段则是未转码的项目入口文件,
    • interpreter字段,使用babe-node作为编译器执行script指定的入口文件,
    • babel-node启动的方式在pm2中不支持集群模式,就是说instances字段只能写1,而提前build的方式则没有这个限制.
  • 相关阅读:
    【SpringBoot/Oracle】如何解决 “[error code]17056 不支持的字符集,在类路径添加orai18n.jar”
    Spring Initializr
    【SpringBoot】如何在SpringBoot工程启动时建表和填充数据
    最简SpringBoot工程,仅有Oracle支持,可作为起始工程
    【SpringBoot/MyBatis/Oracle】如何在SpringBoot工程中配置编撰一个访问Oracle数据库的MyBatis
    【MyBatis/Oracle】通过MyBatis执行Oracle的批量插入语句,插入千万数据进一表用时1h22m59s151ms
    ASP处理多语言版本的商务网站
    XML指南——XML CDATA
    .NET环境下五种邮件发送解决方案
    什麼是WPF?
  • 原文地址:https://www.cnblogs.com/pandapeter/p/11099251.html
Copyright © 2020-2023  润新知