问题:

  公司有个工具型项目使用node.js 开发,需要部署到客户的服务器中,遇到的问题:

  1、客户的服务器没有外网。环境配置,依赖安装等都比较麻烦,只能手工上传,最好能一个文件直接搞定;

  2、直接包源码部署到客户的机器中,存在源码泄露的风险。

方案:

  使用pkg npm包可以很好的解决我们以上的问题。

  先参考前人的经验 : Egg.js线上部署——利用pkg打包Egg.js工程

pkg原理:

  pkg打包工具主要会按平台(支持window、mac、linux)分别打包。

  pkg中会包含node的可执行文件,还会包含你要打包进去的代码。代码通过一个虚拟的文件系统把所有的代码和资源文件都挂载到 /snapshot/${被打包项目的文件夹名} 下面(pkg hack了 fs 的很多方法,拦截文件操作,如果发现读的文件路径是在挂载目录下就特殊处理,返回打包进去的文件信息,如果不在挂载目录下,则按node默认逻辑进行)

  pkg 会根据被打包项目的package.json 中的licence声明判断是否要对源码进行编译,npm上安装的依赖包基本都是开源的,会以源码的形式打包;而用户的源码如果没有声明开源的协议,则会把js文件编译为v8字节码进行保存(在项目中也就没法通过fs读取到源码,会给出抛错,即使是破解安装包也只能拿到v8字节码)

实现:

1、安装(也可以考虑只安装到项目内,通过npm script 调用打包) 

npm install pkg -g

2、在egg配置文件中把涉及到写文件的路径都移到包外(pkg的虚拟文件系统只是用来应对读的行为,所有写相关都得移出包外)

// 通过process.cwd()获取当前执行文件执行的路径
config.rundir = process.cwd() + '/run';// 配置执行时临时文件的路径
config.logger = {
dir: path.join(process.cwd(), 'logs', logDir),//配置普通日志文件地址
};
config.customLogger = {
scheduleLogger: {
file: path.join(process.cwd(), 'logs', logDir, 'egg-schedule.log'),//配置定时任务日志的地址
},
};
config.static = { // 必须把public移出项目,否则在pkg的包中egg的static中间件会有对public操作(确保文件夹),会有抛错
prefix: '/',
dir: process.cwd() + '/public',//配置静态文件的地址
};

3、修改package.json文件

{
... "bin": "pkg-entry.js", // 执行包的入口文件,可执行包启动的时候默认会调用该文件 "pkg": {// 以下主要是声明那些文件需要被打包(pkg会解析require中的静态路径,但在egg.js中很多文件都是通过框架引用的,无法依赖解析)
"scripts": [ // 这里是声明需要打包的js文件,这里的声明的js文件都会被编译为v8字节码(建议主动声明,不要依赖pkg自动引入)
"./app/**/*.js",
"./config/**/*.js",
"./normalJs/**/*.js", // 不只是egg的文件,只要要用到就要声明打包
"./app.js",
"./agent.js"
],
"assets": [ // 这里是声明需要打包的静态文件(即使有js文件也不进行编译)。
"./lib/**/*",// lib中是我打算开放的一些egg组件,所有不需要编译
"./app/public/**/*",// 如果要把前端静态文件打包进来,就直接声明(但是在egg中static中间件会有抛错,需要hack egg或者 hack pkg)
"./node_modules/**/*"// npm安装的所有依赖包全部打包进来,不要依赖自动引入,很容易导致部分文件没打包,出现各种意料外的错误
]
},
}

4、增加入口文件pkg-entry.js(名字保持和package.json中一致)

const fs = require('fs');

// 如果是egg的ts项目,由于egg-script会给ts项目通过-r引入sourcemap的注入文件,但是pkg的spawn不支持,所以把项目标识为飞ts
// 如果不是ts项目忽略一下两行
const pkgInfo = require('./package');
pkgInfo.egg.typescript = false; // 防止egg-script识别为 typescript 自动添加soucemap支持(--require 在pkg的spawn中不支持) //我自己的工具包的配置文件是直接打包到安装包里面的,这样就不方便修改配置了。于是把提供给运维配置的配置都适用dotenv来配置,以下引入dotenv的预执行脚本
//也可以考虑把配置文件放到包外,不过因为包内执行包外js,会增加被攻击的风险
require('dotenv/config'); // 由于egg-script是默认以当前执行proccess.cwd() 路径为默认项目的,打包后需要每次输入 /snapshot/${项目文件夹名} 作为指定目录
// 所以,以下为修改参数,自动嵌入“/snapshot/${项目文件夹名}”
const baseDir = '/snapshot/' + fs.readdirSync('/snapshot')[0];
console.log('baseDir:', baseDir);
// 当 start 的时候,自动嵌入bashDir为 /snapshot/${项目文件夹名}
const startIndex = process.argv.indexOf('start');
if (startIndex > -1) {
process.argv = [].concat(
process.argv.slice(0, startIndex + 1),
baseDir,
process.argv.slice(startIndex + 1),
);
} // 然后直接调起egg-scripts执行
require('./node_modules/egg-scripts/bin/egg-scripts.js');

5、 执行打包

## --targets 用于制定平台和node版本,不指定时默认为3个平台以package.json中的node版本配置为准
## --out-path 指定执行包输出文件夹,默认为当前文件夹
## --debug 用于调试,可了解哪些文件被打包
pkg . --targets node8-linux-x64 --out-path /usr/dist --debug

6、运行

> chmod a+x ./appName #给可执行包增加执行权限
> ./appName start # 启动项目,除项目路径其它参数都和egg-scripts一致 可以用--title指定egg服务名
>./appName stop # 关闭项目(会关闭当前服务器的所有egg服务,如果有多个,最好用--title来指定要关闭的项目)

ps:

  如果需要动态配置或者包中使用了c++编译的node依赖包,可参考该文章  Egg.js线上部署——利用pkg打包Egg.js工程 。

可能遇到问题:

第一次打包的时候,会遇到下包很慢很可能超时的问题。如下:

到https://github.com/zeit/pkg-fetch/releases下载对应的包,然后
~/.pkh-cache/2.5/目录下,改名为fetched-v8.11.3-macos-x64(参考运行时下的包名字改)即可。参考https://github.com/zeit/pkg/issues/419

使用pkg打包node.js项目(egg框架)为可执行包的更多相关文章

  1. 使用pkg打包Node.js应用的方法步骤

    Node.js应用不需要经过编译过程,可以直接把源代码拷贝到部署机上执行,确实比C++.Java这类编译型应用部署方便.然而,Node.js应用执行需要有运行环境,意味着你需要先在部署机器上安装Nod ...

  2. Node.JS 项目打包 JXCore

    哈哈,又回来了 当你开发完成了Node.JS项目,你应该需要打包发行吧 好,JXCore就是干这个的啦! 嗯,可能你会这样来安装 1. curl http://jxcore.com/xil.sh | ...

  3. [Node.js] Node.js项目的持续集成

    原文地址:http://www.moye.me/2016/03/03/nodejs_ci_by_jenkins 引子 持续集成 (Continuous Integration,简称CI)是一种软件工程 ...

  4. node.js Web应用框架Express.js(一)

    什么是Express.js Express 是一个简洁而灵活的 node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用,提供丰富的HTTP工具以及来自Connect框架的中间件随 ...

  5. WebStorm中Node.js项目配置教程(1)——创建项目

    Node.js绝对是一个web开发的热点话题,作为web神器的WebStorm也是开发Node.js的佼佼者. 接下来就Node.js项目在WebStorm的配置操作就行详细的讲解,首先是创建项目.两 ...

  6. node.js使用express框架进行文件上传

    关于node.js使用express框架进行文件上传,主要来自于最近对Settings-Sync插件做的研究.目前的研究算是取得的比较好的进展.Settings-Sync中通过快捷键上传文件,其实主要 ...

  7. 基于 Token 的身份验证:JSON Web Token(附:Node.js 项目)

    最近了解下基于 Token 的身份验证,跟大伙分享下.很多大型网站也都在用,比如 Facebook,Twitter,Google+,Github 等等,比起传统的身份验证方法,Token 扩展性更强, ...

  8. [Node.js]Express web框架

    摘要 Express是一个简洁灵活的node.js web应用框架,提供了一系列强大特性帮助你创建各种web应用和丰富的http工具.使用express可以快速创建一个完整功能的网站. Express ...

  9. WebStorm中Node.js项目配置教程——项目设置

    上一章讲解了Node.js项目在WebStorm中的两种创建方式,当完成Node.js项目创建以后,剩下的就是涉及配置设置工作. 为了确保Node.js全局和Node.js核心模块的代码完成功能,打开 ...

随机推荐

  1. 项目Beta冲刺--7/7

    项目Beta冲刺--7/7 作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Beta冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合评估及 ...

  2. 项目Beta冲刺(团队)——总结篇

    项目Beta冲刺(团队)--总结篇 格式描述 课程名称:软件工程1916|W(福州大学) 作业要求:项目Beta冲刺(团队) 团队名称:为了交项目干杯 作业目标:Beta冲刺总结 团队信息 队员学号 ...

  3. tomcat和apache的区别--http server vs application server

    1. Apache是web服务器,Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展. 2. Apache和Tomcat都可以做为独立的web服务器来运行,但是A ...

  4. accept返回的socket的端口号和连接socket一样的!!! socket绑定信息结构

    今天与同学争执一个话题:由于socket的accept函数在有客户端连接的时候产生了新的socket用于服务该客户端,那么,这个新的socket到底有没有占用一个新的端口? 讨论完后,才发现,自己虽然 ...

  5. fitnesse生成的FitNesseRoot路径问题

    运行fitnesse命令的时候,会生成FitNesseRoot这个文件夹. 但是需要注意的是你在哪个路径下开启服务,就在当前路径下生成FitNesseRoot这个文件夹,而不是说你的fitnesse- ...

  6. Longest Common Substring II SPOJ - LCS2 (后缀自动机)

    Longest Common Substring II \[ Time Limit: 236ms\quad Memory Limit: 1572864 kB \] 题意 给出\(n\)个子串,要求这\ ...

  7. [PHP] Laravel 5.5 打印SQL语句

    [PHP] Laravel 5.5 打印SQL语句 四种方法 第一种方法: 打印SQL默认是关闭的,需要在/vendor/illuminate/database/Connection.php中打开. ...

  8. 彻底理解C++指针

    目录 目录 1 1. 概念 1 1.1. 双指针 1 1.2. 指针数组 1 1.3. 数组指针 1 1.4. 常见指针定义解读 1 2. 区别 2 3. 兼容性 2 4. 为何列数须相等? 2 5. ...

  9. 中国大学生计算机系统与程序设计竞赛 CCF-CCSP-2017 串行调度(serial)

    串行调度(serial) 除等价条件, 根据题意设置限制条件,然后求字典序最小拓扑序. 简洁版 #include<bits/stdc++.h> using namespace std; ; ...

  10. Java程序设计学习知识点总结

    Java程序设计学习知识点总结 Java语言简单,面向对象,分布式,解释性,健壮,安全与系统无关,可移植,高性能,多线程,动态语言. 什么是框架 可以认为是某种应用的半成品,就是一组组件用来完善自己的 ...