NODE打包交付第三方使用之PKG

背景:这我来本公司的第一个任务,中间踩了很多坑。万幸的是最终解决了!我们所采用的技术栈是midway.js(node的框架,可以用koa、egg、express代替)+so+pkg。

so:作为现阶段可逆难度比较大的技术手段,采用so来做加密的案例有很多,这个就不过多的赘述了,动C++的做起来很方便,也可以用dll,用法大体类似。

pkg:作为JS的打包工具,会把环境和依赖都打包进一个可执行文件,随便复制到相应的地方就可以用了!

1、so的node使用,直接上代码

const [data, key] = base64.decode(deCryptoKey).split(',');
const libm = ffi.Library(path.join(process.cwd(), this.soPwd), {  
TKS: ['string', [GoString, GoString, GoString]],});
// 获取soConfigconst 
secStr = libm.TKS(  newGoString('sec_code'), newGoString(data), newGoString(key));
let soConfig = JSON.parse(secStr);
复制代码

2、PKG打包配置——package.json

package.json

"pkg": {"scripts": ["./dist/**/*.js", "./bootstrap.js"  ],  
"assets": [
    "./node_modules/ref-napi/**/*", 
    "./node_modules/ffi-napi/**/*", 
    "./node_modules/ref-struct-napi/**/*",  
    "./node_modules/node-gyp-build/**/*",    
    "./node_modules/grpc/**/*"  
],  
"targets": ["node12-linux-x64"]},
"scripts": {  
    "pkg-macos": "pkg . -t node12-macos-x64 --out-path=",  
    "pkg-linux": "pkg . -t node12-linux-x64 --out-path=",
},
复制代码

3、PKG打包配置——dockerfile

FROM nikolaik/python-nodejs:python3.8-nodejs12
ENV NODE_ENV=local ENV MIDWAY_LOGGER_DISABLE_COLORS=true 
WORKDIR /root 

COPY . .
RUN npm i midway-bin \    
    && npm i \    
    && npm run build \    
    && npm rebuild \    
    && npm run pkg-linux \    
    && ls |grep -v -E "^so|artery"|xargs -i rm -rf {} \    
    && cd so \    
    && ls |grep -v *${NODE_ENV}.so|xargs -i rm -rf {} 
EXPOSE 7001 

["/root/artery"]
复制代码

4、PKG打包配置——bootstrap.js

// 加载所有js文件-解决路由丢失问题
const getFiles = function (dir, list = []) {  
    const arr = fs.readdirSync(dir);  
    while (arr.length) {    
        const item = arr.pop();    
        const fullpath = path.join(dir, item);    
        const stats = fs.statSync(fullpath);    
        if (!stats.isDirectory()) {      
            if (/.js$/.test(fullpath)) list.push(require(fullpath));    
        } else {      
            getFiles(fullpath, list);    
        }  
    }  
    return list;
};
Bootstrap.before(async (container) => {  
    // 读取远程配置  
    web = createKoaweb(container.getConfigService().getConfiguration());
}).configure({    
    baseDir: path.join(__dirname, '/dist'), 
    preloadModules: getFiles(path.join(__dirname, '/dist')),  
}).load(() => {    
    return web;  
}).run();
复制代码

总结遇到的坑

1、python问题

换源、npm rebuild

2、项目启动问题

Node启动换为直接运行

3、npm build 丢失二进制文件问题

dockerfil复制进去

4、无效的内存地址或 nil 指针取消引用

so包不对

5、路由找不到

与作者沟通加了preloadModules方法

6、native complate have not......

将依赖放进打包目录assets下

7、V8报错

降低node版本

8、数据库dao无法加载

执行目录有问题,解决方案用:join(__dirname, '../', it)))

后续优化

1、因为我们用了SO,所以导致打出来的docker镜像比较大,后续可以采用二次打包,打出来要缩小十倍左右!

2、或者把SO做成服务,用SDK调用(我们的方案)