标签: npm

  • 【视频】Node.js 开发 RAR 解压缩命令行工具

    【视频】Node.js 开发 RAR 解压缩命令行工具

    拖来拖去,终于把 使用 node.js 开发命令行工具 workshop 的视频剪出来了,前几天上传到 B 站,访问量很一般,所以在自己的博客再捞一下。

    这次视频主要面向新手,主要呈现从 0 到 1 实现命令行工具的做法,希望观众无论基础如何,都能在看完视频之后,掌握封装仓库、实现命令行工具的做法。内容大约是:

    1. 不同系统下安装 node.js
    2. 创建命令行工具项目
    3. package.json 结构介绍
    4. 介绍 unrar-promise
    5. 介绍 yargs 实现命令行接口
    6. 开发功能
    7. 发布到 npm

    完成的项目放在 GitHub:meathill/unrar: a simple script to unarchive rar files (github.com) 非常简单,大家可以参考。

    有任何问题、建议均欢迎留言讨论。新的一年,我会努力多做视频、多做好视频,希望大家支持我。

  • 使用 GitHub Registry 托管私有 NPM 源

    使用 GitHub Registry 托管私有 NPM 源

    我厂有不少私有仓库,都是日常开发中提炼出来的,在几个项目中共享,比如 UI、Vuex、网络请求(axios 封装)等。以前的主要形式是使用 npm 安装 GitHub 仓库,即

    npm i openresty/some-repo

    这样 npm 会自动去 GitHub 查找对应的仓库,然后 clone 下来完成安装。项目中的 .npmignore 文件也会正常生效,安装后的目录会忽略不需要的文件。这样做的好处就是简单,只要仓库存在,安装依赖的系统有足够的权限(比如 ssh key),就能顺利安装。在过去的三年时间里,我们一直都这样做。

    但是这样会有一些问题:

    1. package-lock.json 里记录的是 commit hash,只看这个值无法判断版本,npm 也没法使用版本号解决依赖冲突的问题。换言之,比如 A 仓库需要 C 仓库的 1 版本,B 仓库需要 C 仓库的 2 版本,那么就只能同时安装两个版本,因为 npm 无法判断两个版本是否兼容。
    2. 安装的时候要走 git clone,下载量很大,速度很慢,经常被同事吐槽。也会影响 CI 的效率。
    3. git 仓库里要提交编译后的代码,一方面浪费时间和空间,另一方面大量编译后的代码也影响 code review

    所以,考虑之后决定改用 GitHub Registry。GitHub Registry 是 GitHub 提供的私有源,感兴趣的同学可以访问这个页面了解详情。这个服务需要收费,不过我厂本来就是 Team 用户,额度比较富裕,所以并没有阻力。

    经过一段时间的摸索,终于搞成了,下面简单说一下做法。

    对依赖项目

    修改 package.json,把项目名称改成 @openresty/some-repo,即“@公司名/仓库名”。然后增加 publishConfig 字段,设置源为 GitHub registry:

    {
      "publishConfig": {
        "registry": "https://npm.pkg.github.com/"
      },
    }

    接下来,正常使用 npm publish 发布依赖即可。不过在发布之前,最好使用 .npmignore 忽略掉开发时的源文件和配置文件,一方面这些文件对于其它项目的开发没有价值,另一方面无论是存储还是下载消耗流量,都要收费,能省则省嘛。

    对业务项目

    因为这些依赖仓库都是私有项目,所以我们先得解决身份认证的问题。GitHub 提供了 Personal access tokens 方式,生成 token 后,添加到 ~/.npmrc 文件即可:

    //npm.pkg.github.com/:_authToken=<TOKEN>

    接下来,在业务项目中,添加 .npmrc 文件,指名依赖源:

    registry=https://registry.npmjs.org/
    @openresty:registry=https://npm.pkg.github.com

    这段配置分两部分:其它域的依赖,直接从 npm 的源下载;@openresty 域下的依赖,从 GitHub Registry 下载。

    最后,正常使用 npm i @openresty/some-repo 安装依赖即可。


    最后的最后附上修改前后的效果对比,可以看出,改造后效果明显:

    国内修改前real 0m39.543s
    user 0m17.768s
    sys 0m3.944s
    阿里云
    修改后real 0m16.450s
    user 0m15.204s
    sys 0m3.380s
    阿里云
    国外修改前real 0m49.350s
    user 0m22.352s
    sys 0m4.144s
    阿里云
    修改后real 0m30.807s
    user 0m15.780s
    sys 0m3.936s
    阿里云
  • 几步简单的操作解决 `npm audit` vulnerabilities

    几步简单的操作解决 `npm audit` vulnerabilities

    NPM 是 JavaScript 生态最重要的组成部分,我们的项目中会大量使用 NPM 安装第三方包(安装后就称为“项目依赖”)解决问题。这些第三方包也会带来他们的依赖,最终一个项目里可能安装成百上千个依赖。

    有道是:没有完美的代码,代码里一定藏有隐患。所以用的依赖多了,其中有问题的概率也提升了,三五不时的,npm 就会提示我们:found N low/medium/high severity vulnerabilities

    npm 提供命令 npm audit fix,理论上可以修复这些隐患,但在实际操作中,以我的经验来看,并不容易生效。我猜测可能是因为依赖间的复杂关系,想彻底解决并升级不太容易。所以我一般是这样做的:

    (更多…)
  • 解决新机不能 npm install 私有仓库的问题

    解决新机不能 npm install 私有仓库的问题

    前些天换了电脑,从 iMac 27 Retina 2014 late 升级到 iMac 27 2019。关于前因后果,我写在张大妈,感兴趣的同学可以看下:《肉山的电子产品 篇九:机不如新,人不如故——iMac 27 换新记》

    换机器要搭环境。有两个选择:

    1. 整盘复制,利用 Time Machine 之类的工具
    2. 自己慢慢搭

    考虑到老电脑已经工作了 5 年,经历了小十个系统版本,各种软件删装无数,里面的垃圾很多;再加上我的环境并不复杂,所以我决定自己慢慢搭。

    然后遇到一个问题:npm install 会卡住,没有明显的提示信息,只有一段比较可疑:

    The authenticity of host 'GitHub.com (1.1.1.1)' can't be established.
    ECDSA key fingerprint is SHA256:abcdefg.
    Are you sure you want to continue connecting (yes/no)? 

    因为项目中用到一些私有仓库的依赖,所以我怀疑是它们的问题。于是我把私有仓库从 package.json 里移除,再安装,成功。看来猜的没错。

    然后我手动 git clone 一个项目到本地,clone 的过程中,会看到上面的提示,手动输入 yes,记录目标机器的指纹,视它安全可靠。clone 完成。再把私有仓库依赖加回 package.json,安装,成功。问题解决。

    原因:使用 npm 安装 GitHub 仓库作为依赖,实际上等同于使用 git clone 将目标仓库 clone 到 node_modules 里。而 git 协议依托于 ssh 协议。在新机器上安装时,因为没有访问过目标机器,本地不信任目标机器,而 npm 又没有对这个异常做处理,所以就会卡住,不上不下。

  • npm 支持开发者添加募款链接

    npm 支持开发者添加募款链接

    昨天随手升级个人首页的依赖,更新完之后,npm 提示:

    6 packages are looking for funding
      run `npm fund` for details

    如果你执行 npm fund,可以看到类似这样的信息:

    your-repo@0.1.0
    ├─┬ core-js@3.4.2
    │ ├── type: opencollective
    │ └── url: https://opencollective.com/core-js
    ├─┬ eslint@6.7.0
    │ └── url: https://opencollective.com/eslint
    └─┬ swiper@5.2.1
      ├── type: patreon
      └── url: https://www.patreon.com/vladimirkharlampidi

    opencollective 和 patreon 都是众筹网站,只不过众筹的内容不是实物商品,而是支持你喜欢的创作者,无论他是摄影师、画家,还是开源软件作者。据说 Vue 的作者尤雨溪每年可以从 Patreon 上获得将近 $20w 的捐赠,这笔钱可以帮助他以独立身份继续开发 Vue,还可以雇佣一名全职开发者帮助他把这份工作做得更好。

    我去 NPM 官网找了一下,npm fund 的文档还没更新上去,只找到这篇 RFC: Add funding support to package.json,大意是包开发者可以在包的描述文件(package.json)里放上一段募款声明,这样包的用户在安装的时候,就会看到我开篇写的那些文字。提醒包的开发者:你们可以通过捐赠的方式,表达对依赖开发者的感谢。

    我觉得这种形式挺好的。当然,有些人可能看不惯这种有“伸手嫌疑”的行为,但是,与其在无酬工作中纠结、放弃自己的项目、甚至被别有用心的人利用埋后门,任何不影响安全性、不增加使用负担的变现方式都是合理且值得鼓励的。

    希望开源软件开发者越过越好,开源基建开发者越过越好,世界越来越好。

  • 网站抓取工具 website-scraper

    网站抓取工具 website-scraper

    临时需要抓一个网站,搜索了一下,发现 website-scraper,用了一下感觉不错。它有如下优点:

    1. 基于 Node.js 和 NPM,系统无关
    2. 可以根据链接抓取整个网站
    3. 文档齐全,仓库还有人维护
  • 使用 Electron 开发桌面应用

    使用 Electron 开发桌面应用

    这个标题比较大,先挖个坑,日后再填。

    忘记哪里看来的:nw(原 node-webkit)的作者从 Intel 离职后,无法继续维护 nw,此时 Github 向他抛来橄榄枝,请他去做 Electron(主要是为 Atom 做基础),于是便有了 Electron。

    这两个东西虽然基础架构不一样,不过大体上都是 V8 + Chromium,实现使用 JavaScript 构建系统交互,使用 Web 提供 UI。简单对比了一下我觉得明显 Electron 好多了嘛,所以选择用它来开发桌面应用。

    经过几天摸索,开发出来一个应用。不过太小,可分享的东西不多,所以先记几条 Tips。

    封装 Electron 应用

    打包工具

    Electron 构建了一套完整的环境,只需要替换里面的 Web 部分就可以发布。这样最大的好处是每次发布的时候只需要简单压缩一下网页部分,放到包里,不用构建整套系统,对开发机的要求大大降低。

    坏处就是,对于我们墙内用户而言,安装 Electron 必须用小水管拉一个将近 100M 的包回来,简直痛苦的要死。更别提后面如果享用 [electron-packager] 之类的工具封装的话还要再下一遍……每到这个时候,都要给病魔加油,愿他早日战胜方校长。

    这里建议使用淘宝的 cnpm 镜像,速度会好很多。不过它似乎和 npm 有点冲突。

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    cnpm install electron -g
    

    至于 electron-packager,因为它使用 [electron-download] 下载 Electron 运行包,可以按照提示,修改下载的源,走淘宝镜像,这样也会快很多:

    npm config set ELECTRON_MIRROR https://npm.taobao.org/mirrors/electron/
    

    环境选择

    至少在我这里,在 Mac 下只能打包 Mac 应用;在 Windows 下只能打包 Windows 应用。所以需要多平台的话,请准备多台开发机。

  • npm start, npm stop

    npm start, npm stop

    使用 npm 可以直接调用 package.json 里面 scripts 标签里定义的脚本。比如,Astinus 项目中,index.js 是入口JS,并且需要 ES6 支持,就可以这样:

        // package.json
        {
          "scripts": {
            “start": "node index --harmony"
          }
        }
    

    然后直接运行

        npm start
    

    即可。

    那么怎么终止进程呢?

    首先要在 index.js 里增加一句

        process.title = 'astinus';
    

    声明该应用的标题是“astinus”,然后增加脚本:

        {
          "scripts": {
            "start": "node index --harmony",
            "stop": "killall SIGINT astinus"
          }
        }
    

    之后就可以

        npm stop
    

    参考: