在我们开发NPM包的时候,经常需要测试才能保证包的正常使用,本文总结了几种测试NPM包的方法

下文中,项目名以project代替

要发布的npm包名以@zxkfall/audio-player代替,包所在的文件夹名为audio-player

1. 发布后安装包(极度不推荐)

测试NPM包最好的方法就是将其发布,然后在项目中安装包,进而测试包是否可用,流程如下

# 修改完代码后,版本号+1,然后发布
$ npm publish --access=public
# 在project根目录下安装模块
$ npm install @zxkfall/audio-player
# 自己进行对应的测试....

当然这样的流程是不推荐的,一方面,频繁的发布与安装,会消耗大量的时间,另一方面,每次发布包都需要增加版本号,这样就会导致版本号数字很大,而且由于没有经过测试就已经发布,如果测试出现问题,需要重新修改并发布,会导致版本号管理比较混乱。

正常的流程应该是在本地测试没有问题后,再将包发布,等使用者发现问题并提交后,再根据使用者的反馈,对一些代码进行修改,因此便有以下几种方法可以在本地测试包

2.通过npm link命令

  1. 将开发的包创建成本地依赖包
$ cd audio-player
$ npm link
  1. 进入项目中,建立链接
$ cd project
$ npm link @zxkfall/audio-player

这样@zxkfall/audio-player这个包就会与项目project关联,后面包的代码更新时,project里面对应包的代码也是最新的。

如果项目要解除链接

# 在project下
$ npm unlink @zxkfall/audio-player

如果要取消模块的链接

# 在audio-player下,这样所有用到包的其他项目链接都会失效
$ npm unlink @zxkfall/audio-player
# unlink为uninstall的别名

3. 使用Yalc

yalc 可以在本地将npm包模拟发布,将发布后的资源存放在一个全局的存储中。然后可以通过yalc将包添加进需要引用的项目中。

这时候package.json的依赖表中会多出一个file:.yalc/...的依赖包,这就是yalc创建的flie:软链接。同时也会在项目根目录创建一个yalc.lock确保引用资源的一致性。因此,测试完项目还需要执行删除yalc包的操作,才能正常使用。当然,yalc也是支持link:链接方式

a.首先安装yalc

$ npm install yalc -g

b.发布包

# 在audio-player下
$ yalc publish

此时如果存在npm 生命周期脚本:prepublishprepareprepublishOnlyprepackpreyalcpublish,会按此顺序逐一执行。如果存在:postyalcpublishpostpackpublishpostpublish,也会按此顺序逐一执行。

想要完全禁用脚本执行需要使用

$ yalc publish --no-scripts

此时就已经将依赖发布到本地仓库了。此命令只是在本地发布包并不会主动推送到远端。

当修改包的代码后,需要重新在本地发布时,可以使用推送命令快速更新所有依赖,相当于帮依赖这个包的项目执行了update命令

$ yalc publish --push
$ yalc push # 简写

c.添加包

进入到project,执行

$ yalc add @zxkfall/audio-player

可以看到项目中添加了yalc.lock文件,package.json对应的包名会有个地址为file:.yalc/开头的项目。 也可以使用

$ yalc add @zxkfall/audio-player@1.0.0

将版本锁定,避免因为本地新包推送产生影响。

参数:

  • --dev,将依赖添加进dependency
  • --pure,不会影响package.json文件
  • --link,使用link方式引用依赖包,yalc add [my-package] --link
  • --workspace (or -W),添加依赖到workspace:协议中

d.当本地的包修改完毕,重新推送后,获取更新后的版本

$ yalc update # 更新全部
$ yalc update @zxkfall/audio-player # 只更新这一个包

e.其他命令

当我们要查看本地仓库里存在的包时

$ yalc installations show

要清理不需要的包时

$ yalc installations clean @zxkfall/audio-playe

yalc

3.包内测试

很多时候,其实有些功能我们完全可以使用一些测试工具,在包内进行测试,这里以jest为例

a.安装jest

$ npm install --save-dev jest

b.使用

导出的函数

// index.js
const createAudioPlayer = () => {
    console.log('CreateAudioPlayer')
};

const AudioPlayer = function () {
    console.log('new')
    this.createAPlayer = createAudioPlayer
}

module.exports = AudioPlayer

测试文件

// index.test.js //这里不要用import来导入,会报错
let AudioPlayer = require("../index")
describe('Test', function () {
    it('should log', function () {
        let mk = new AudioPlayer()
        new AudioPlayer().createAPlayer()
    });
});

4.使用webpack进行打包

我们很多需要用的包,都是可以直接通过CDN引用的,如果我们使用module.exportsexports进行导出,这样在原始的HTML文件里面,实际上是无法使用的,因为浏览器不支持es6的语法,而es5里面实际上是不识别moduleexports的。

用webpack进行打包,如果没有定义全局变量,是无法把函数给外面的代码使用的,因为webpack打包是用的闭包,立即执行的函数,这点这里不做深入探讨。

有时候,我们希望我们开发的模块,既可以在ES5的语法环境中使用,即直接调用函数,又希望它兼容ES6语法,即通过NPM安装后,可以通过import进行导入,这里就需要用到全局变量,以及webpack打包。

这里预设一个场景:

我们希望我们的测试可以全部在这个模块里运行,不希望通过yalc或者link指令通过另一个项目进行测试。那我们就需要新建一个index.html文件,在index.html里面通过script标签引入我们的js文件,配合live-server,就可以实现实时加载更新后文件的功能。

1.安装webpack与live-server

$  npm install --save-dev webpack
$  npm install --save-dev live-server

2.根目录新建webpack.config.js

内容如下

const path = require('path');

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
    },
    watch: true //auto config file
};

3.package.json增加配置

"scripts": {
    "serve": "live-server --port=8080" // 当运行npm run serve命令时,会在本地建立端口号为8080的服务器,服务器的根目录为项目的目录,会自动找到index.html文件并打开
  },

4.index.js

里面的示例代码如下

const createAudioPlayer = () => {
    console.log('CreateAudioPlayer')
};

const AudioPlayer = function () {
    console.log('new')
    this.createAPlayer = createAudioPlayer
}

window.$AudidoPlayer = AudioPlayer
module.exports = AudioPlayer

这里注意,增加了window.$AudidoPlayer = AudioPlayer,这样AudioPlayer这个函数才能被外部直接调用

5.新建index.html文

内容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Hello Test

<script type="text/javascript" src="dist/index.js"></script>
<script type="text/javascript">
    const audioPlayer = new window.$AudidoPlayer()
    audioPlayer.createAPlayer();
    console.log('ddd')
</script>

</body>
</html>

6.打包

$ webpack

7.运行live-server

$ npm run serve

之后,只要文件内容发生变化,html页面也会刷新。

8.总结

其实live-serve和vscode或者idea的一些自动刷新插件都类似,所以具体选用哪个,看自己需求,这里只是提供了一种在大部分情况下可用的一种方法。

由于我们的包发布后,其实就有一个默认的CDN链接,即

https://cdn.jsdelivr.net/npm/(packagename)@(version)/(filePath)

这里的file是相对路径,如:

https://cdn.jsdelivr.net/npm/@zxkfall/audio-player@1.0.0/dist/index.js

通常,一些静态网页需要通过以CDN的方式引入第三方组件,由于没有使用NPM进行管理,那么ES6的一些语法就无法支持,这时候,就可以使用

const audioPlayer = new window.$AudidoPlayer() //在项目中定义的

这样就实现了ES5与ES6功能的兼容。

当然,也可以使用

https://cdn.jsdelivr.net/npm/@zxkfall/audio-player@1.0.0/index.js

那么项目中就直接使用

const audioPlayer = new AudioPlayer()

进行后续的操作,这也是可以的,但是浏览器会报错,因为module这个变量实际上是无法识别的,这样用户体验就会很差。

注意发布包的时候,别忘了忽略一些文件的提交