npm 支持

从小程序基础库版本 2.2.1 或以上、及开发者工具 1.02.1808300 或以上开始,小程序支持使用 npm 安装第三方包。

此文档要求开发者们对 npm 有一定的了解,因此不会再去介绍 npm 的基本功能。如若之前未接触过 npm,请翻阅 官方 npm 文档 进行学习。

tips:在小程序中使用npm包前,需先构建 npm

使用 npm 包

1. 安装 npm 包

在小程序 package.json 所在的目录中执行命令安装 npm 包:

  1. npm install

此处要求参与构建 npm 的 package.json 需要在 project.config.js 定义的 miniprogramRoot 之内。

tips:开发者工具 v1.02.1811150 版本开始,调整为根据 package.json 的 dependencies 字段构建,所以声明在 devDependencies 里的包也可以在开发过程中被安装使用而不会参与到构建中。如果是这之前的版本,则建议使用--production选项,可以减少安装一些业务无关的 npm 包,从而减少整个小程序包的大小。

tips: miniprogramRoot 字段不存在时,miniprogramRoot 就是 project.config.js 所在的目录

2. 构建 npm

点击开发者工具中的菜单栏:工具 —> 构建 npm
construction

为何要有此步骤?

3. 勾选“使用 npm 模块”选项:

use npm

4. 构建完成后即可使用 npm 包。

js 中引入 npm 包:

  1. const myPackage = require('packageName')
  2. const packageOther = require('packageName/other')

使用 npm 包中的自定义组件:

  1. {
  2. "usingComponents": {
  3. "myPackage": "packageName",
  4. "package-other": "packageName/other"
  5. }
  6. }

tips:此处使用 npm 包时如果只引入包名,则默认寻找包名下的 index.js 文件或者 index 组件。

发布 npm 包

发布小程序 npm 包的约束

这里要发布的 npm 包是特指专为小程序定制的 npm 包(下称小程序 npm 包)。因为小程序自定义组件的特殊性,原有的 npm 包机制无法满足我们的需求,所以这里需要对小程序 npm 包做一些约束:

  1. 小程序 npm 包要求根目录下必须有构建文件生成目录(默认为 miniprogram_dist 目录),此目录可以通过在 package.json 文件中新增一个 miniprogram 字段来指定,比如:
  1. {
  2. "name": "miniprogram-custom-component",
  3. "version": "1.0.0",
  4. "description": "",
  5. "miniprogram": "dist",
  6. "devDependencies": {},
  7. "dependencies": {}
  8. }
  1. 小程序 npm 包里只有构建文件生成目录会被算入小程序包的占用空间,上传小程序代码时也只会上传该目录的代码。如果小程序 npm 包有一些测试、构建相关的代码请放到构建文件生成目录外。另外也可以使用.npmignore文件来避免将一些非业务代码文件发布到 npm 中。
  2. 测试、构建相关的依赖请放入 devDependencies 字段中避免被一起打包到小程序包中。

发布其他 npm 包的约束

如果是已经发布过的一些 npm 包,因为一些原因无法改造成小程序 npm 包的结构的话,也可以通过微调后被使用,但是请确保遵循以下几点:

  1. 只支持纯 js 包,不支持自定义组件。
  2. 必须有入口文件,即需要保证 package.json 中的 main 字段是指向一个正确的入口,如果 package.json 中没有 main 字段,则以 npm 包根目录下的 index.js 作为入口文件。
  3. 测试、构建相关的依赖请放入 devDependencies 字段中避免被一起打包到小程序包中,这一点和小程序 npm 包的要求相同。
  4. 不支持依赖 c++ addon,不支持依赖 nodejs 的内置库:
  1. const addon = require('./addon.node'); // 不支持!
  2. const http = require('http'); // 不支持!

tips:对于一些纯 js 实现的 nodejs 内置库(如 path 模块),可以通过额外安装其他开发者实现的 npm 包来支持。

  1. 使用 require 依赖的时候下列几种方式也是不允许的:
  1. // 不允许将 require 赋值给其他变量后再使用,以下代码不会去解析出具体依赖
  2. let r;
  3. r = require;
  4. r('testa');
  5. let r2 = require;
  6. r2('testa');
  7. // 不允许 require 一个变量,以下代码依赖运行时,无法解析出具体依赖
  8. let m = 'testa';
  9. require(m);
  1. 小程序环境比较特殊,一些全局变量(如 window 对象)和构造器(如 Function 构造器)是无法使用的。

发布流程

发布 npm 包的流程简述如下:

  1. 如果还没有 npm 帐号,可以到 npm 官网 注册一个 npm 帐号。
  2. 在本地登录 npm 帐号,在本地执行:
  1. npm adduser

或者

  1. npm login
  1. 在已完成编写的 npm 包根目录下执行:
  1. npm publish

到此,npm 包就成功发布到 npm 平台了。

tips:一些开发者在开发过程中可能修改过 npm 的源,所以当进行登录或发布时需要注意要将源切回 npm 的源。

原理介绍

为了帮助大家更好的理解发布 npm 包中提到的各种要求,这里简单介绍一下原理:

  1. 首先 node_modules 目录不会参与编译、上传和打包中,所以小程序想要使用 npm 包必须走一遍“构建 npm”的过程,在每一份 miniprogramRoot 内开发者声明的 package.json 的最外层的 node_modules 的同级目录下会生成一个 miniprogram_npm 目录,里面会存放构建打包后的 npm 包,也就是小程序真正使用的 npm 包。
  2. 构建打包分为两种:小程序 npm 包会直接拷贝构建文件生成目录下的所有文件到 miniprogram_npm 中;其他 npm 包则会从入口 js 文件开始走一遍依赖分析和打包过程(类似 webpack)。
  3. 寻找 npm 包的过程和 npm 的实现类似,从依赖 npm 包的文件所在目录开始逐层往外找,直到找到可用的 npm 包或是小程序根目录为止。 下面简单介绍下构建打包前后的目录情况,构建之前的结构:
  1. |--node_modules
  2. | |--testComp // 小程序 npm 包
  3. | | |--package.json
  4. | | |--src
  5. | | |--miniprogram_dist
  6. | | |-index.js
  7. | | |-index.json
  8. | | |-index.wxss
  9. | | |-index.wxml
  10. | |--testa // 其他 npm 包
  11. | |--package.json
  12. | |--lib
  13. | | |--entry.js
  14. | |--node_modules
  15. | |--testb
  16. | |--package.json
  17. | |--main.js
  18. |--pages
  19. |--app.js
  20. |--app.wxss
  21. |--app.json
  22. |--project.config.js

构建之后的结构:

  1. |--node_modules
  2. |--miniprogram_npm
  3. | |--testComp // 小程序 npm 包
  4. | | |-index.js
  5. | | |-index.json
  6. | | |-index.wxss
  7. | | |-index.wxml
  8. | |--testa // 其他 npm 包
  9. | |--index.js // 打包后的文件
  10. | |--miniprogram_npm
  11. | |--testb
  12. | |--index.js // 打包后的文件
  13. | |--index.js.map
  14. |--pages
  15. |--app.js
  16. |--app.wxss
  17. |--app.json
  18. |--project.config.js

tips:打包生成的代码在同级目录下会生成 source map 文件,方便进行逆向调试。

js 模块示例

以下为官方提供的 js 模块,可以参考并使用:

自定义组件相关示例

请查阅开发第三方自定义组件文档。

Tips

从 1.03.2006302 (或 1.03.2006302) 开始,我们提供了两种构建 npm 的方式:

默认的构建 npm 方式

默认情况下,在 miniprogramRoot 内正确配置了 package.json 并执行 npm install 之后,其构建 npm 的结果是,为每一个 package.json 对应的 node_modules 构建一份 miniprogram_npm,并放置在对应 package.json 所在目录的子目录中。参考 demo

构建 npm 前

  1. ├── miniprogram
  2. ├── app.js
  3. ├── app.json
  4. ├── app.wxss
  5. ├── index
  6. ├──
  7. ├── node_modules // 可被默认方式构建 npm,因为它在 miniprogramRoot 内
  8. ├── package.json
  9. └── sub_package
  10. ├── node_modules // 可被默认方式构建 npm,因为它在 miniprogramRoot 内
  11. ├── package.json
  12. └── sub_package_page
  13. ├── node_modules // 不被默认方式构建 npm,因为它不在 miniprogramRoot 内
  14. ├── package.json
  15. └── project.config.json // 其中存在配置 `"miniprogramRoot": "./miniprogram"`

构建 npm 后

  1. ├── miniprogram
  2. ├── app.js
  3. ├── app.json
  4. ├── app.wxss
  5. ├── index
  6. ├──
  7. ├── miniprogram_npm
  8. ├── node_modules // 可被默认方式构建 npm,因为它在 miniprogramRoot 内 --> 同级的 miniprogram_npm 是这份 node_modules 的构建结果
  9. ├── package.json
  10. └── sub_package
  11. ├── miniprogram_npm
  12. ├── node_modules // 可被默认方式构建 npm,因为它在 miniprogramRoot 内 --> 同级的 miniprogram_npm 是这份 node_modules 的构建结果
  13. ├── package.json
  14. └── sub_package_page
  15. ├── node_modules // 不被默认方式构建 npm,因为它不在 miniprogramRoot 内 --> 它并没有对应的 miniprogram_npm 生成
  16. ├── package.json
  17. └── project.config.json // 其中存在配置 `"miniprogramRoot": "./miniprogram"`

自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式

与 “默认的构建 npm 方式” 不一样,此种方式需要开发者在 project.config.json 中指定 node_modules 的位置 和目标 miniprogram_npm 的位置。参考demo

使用方法

  • 配置 project.config.json 的 setting.packNpmManuallytrue,开启自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式
  • 配置 project.config.json 的 setting.packNpmRelationList 项,指定 packageJsonPathminiprogramNpmDistDir 的位置

其中 packNpmRelationList 的格式为

  1. packageNpmRelationList: Array<{
  2. "packageJsonPath": string,
  3. "miniprogramNpmDistDir": string
  4. }>
  • packageJsonPath 表示 node_modules 源对应的 package.json
  • miniprogramNpmDistDir 表示 node_modules 的构建结果目标位置

构建 npm 前

  1. .
  2. ├── miniprogram
  3. ├── app.js
  4. ├── app.json
  5. ├── app.wxss
  6. ├── index
  7. ├── sitemap.json
  8. └── sub_package
  9. └── sub_package_page
  10. ├── project.config.json
  11. ├── src_node_modules_1
  12. ├── node_modules
  13. └── package.json
  14. └── src_node_modules_2
  15. ├── node_modules
  16. └── package.json

其中 project.config.json 存在配置

  1. "setting": {
  2. "packNpmManually": true,
  3. "packNpmRelationList": [
  4. {
  5. "packageJsonPath": "./src_node_modules_1/package.json",
  6. "miniprogramNpmDistDir": "./miniprogram/"
  7. },
  8. {
  9. "packageJsonPath": "./src_node_modules_2/package.json",
  10. "miniprogramNpmDistDir": "./miniprogram/sub_package"
  11. }
  12. ]
  13. }

构建 npm 后

  1. .
  2. ├── miniprogram
  3. ├── app.js
  4. ├── app.json
  5. ├── app.wxss
  6. ├── index
  7. ├── miniprogram_npm // 由 src_node_modules_1/node_modules 构建得到
  8. ├── sitemap.json
  9. └── sub_package
  10. ├── miniprogram_npm // 由 src_node_modules_2/node_modules 构建得到
  11. └── sub_package_page
  12. ├── project.config.json
  13. ├── src_node_modules_1
  14. ├── node_modules
  15. └── package.json
  16. └── src_node_modules_2
  17. ├── node_modules
  18. └── package.json