前言
在微信小程序开发中,Day.js 是一个非常流行的轻量级日期时间处理库。然而,在实际使用过程中,我们发现微信小程序的 npm 构建工具在处理 Day.js 的插件模块时存在兼容性问题。本文将详细记录问题的排查过程、解决方案以及最佳实践。
问题背景
在项目中引入 Day.js 及其插件(duration、relativeTime、weekday、isBetween)后,在微信开发者工具中构建 npm 时遇到以下问题:
- 插件目录缺失 :构建后的
miniprogram_npm/dayjs/目录下没有plugin子目录 - 模块加载失败 :运行时报错
module 'dayjs/plugin/duration.js' is not defined - 路径解析错误:尝试使用不同的引用路径都未能解决问题
环境配置
软件版本
- 操作系统: macOS Sequoia 15.6.1 (Darwin Kernel Version 24G90, arm64)
- Shell: zsh
- 微信开发者工具: 2.01.2510260 darwin-arm64
- 微信小程序基础库: 3.13.2 / 2.19.4
- Node.js: v23.11.0
- npm: 10.9.2
项目依赖
wxapp/package.json
json
{
"name": "wxapp",
"version": "1.0.0",
"description": "微信小程序",
"main": "app.js",
"dependencies": {
"dayjs": "^1.11.20",
...
},
"devDependencies": {
"eslint": "^8.0.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.25.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"miniprogram-api-typings": "^3.9.0"
},
...
}
小程序配置
wxapp/project.config.json
json
{
"setting": {
"es6": true,
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
],
"nodeModules": true,
"libVersion": "3.13.2",
...
},
...
}
问题复现与排查
初始代码
utils/date-time.js
javascript
const dayjs = require('dayjs')
/**
* 扩展 duration 插件
*/
const duration = require('dayjs/plugin/duration.js')
dayjs.extend(duration)
/**
* 扩展 relativeTime 插件(相对时间)
*/
const relativeTime = require('dayjs/plugin/relativeTime.js')
dayjs.extend(relativeTime)
/**
* 扩展 weekday 插件(星期)
*/
const weekday = require('dayjs/plugin/weekday.js')
dayjs.extend(weekday)
/**
* 扩展 isBetween 插件(判断是否在两个日期之间)
*/
const isBetween = require('dayjs/plugin/isBetween.js')
dayjs.extend(isBetween)
/**
* 日期时间工具类
*/
const DateTimeUtil = {
format(date, format = 'YYYY-MM-DD HH:mm:ss') {
if (!date) return ''
return dayjs(date).format(format)
},
// ... 其他方法
}
module.exports = DateTimeUtil
问题现象
执行微信开发者工具的"构建 npm"后,检查 miniprogram_npm/dayjs/ 目录:
bash
$ ls -lh miniprogram_npm/dayjs
total 40
-rw-r--r--@ 1 yakoo5 staff 8.4K 3 21 22:48 index.js
-rw-r--r--@ 1 yakoo5 staff 7.3K 3 21 22:48 index.js.map
关键发现 :miniprogram_npm/dayjs/ 目录下没有 plugin 子目录,导致插件文件无法被正确加载。
运行时的错误信息:
页面【pages/paper-detail/paper-detail]错误:
Error: module 'dayjs/plugin/duration.js' is not defined, require args is 'dayjs/plugin/duration'
at q (VM2704 WASubContext.js:1)
at n (VM2704 WASubContext.js:1)
at date-time.js? [sm]:10
解决方案
经过实际测试和验证,我们找到了两种有效的解决方案。
方案一:手动复制插件到 miniprogram_npm 目录
适用场景:希望保持 npm 标准引用方式,不修改代码中的 require 路径。
步骤 1:创建插件目录
bash
cd wxapp
mkdir -p miniprogram_npm/dayjs/plugin
步骤 2:复制插件文件
bash
# 从 node_modules 复制所需的插件文件到 miniprogram_npm/dayjs/plugin/
cp -vf node_modules/dayjs/plugin/duration.js miniprogram_npm/dayjs/plugin
cp -vf node_modules/dayjs/plugin/isBetween.js miniprogram_npm/dayjs/plugin
cp -vf node_modules/dayjs/plugin/relativeTime.js miniprogram_npm/dayjs/plugin
cp -vf node_modules/dayjs/plugin/weekday.js miniprogram_npm/dayjs/plugin
步骤 3:验证目录结构
bash
$ ls -lh miniprogram_npm/dayjs/plugin
total 40
-rw-r--r--@ 1 yakoo5 staff 4.7K 3 21 22:48 duration.js
-rw-r--r--@ 1 yakoo5 staff 546B 3 21 22:48 isBetween.js
-rw-r--r--@ 1 yakoo5 staff 1.4K 3 21 22:48 relativeTime.js
-rw-r--r--@ 1 yakoo5 staff 427B 3 21 22:48 weekday.js
步骤 4:重新编译
在微信开发者工具中选择"工具 > 编译",验证问题是否解决。
方案二:本地化插件文件(推荐)✅
适用场景:希望完全控制依赖,便于版本管理和团队协作。
步骤 1:创建插件目录
bash
cd wxapp
mkdir -p utils/plugins/dayjs
步骤 2:复制插件文件
bash
# 从 node_modules 复制所需的插件文件到 utils/plugins/dayjs/
cp -vf node_modules/dayjs/plugin/duration.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/isBetween.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/relativeTime.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/weekday.js utils/plugins/dayjs
步骤 3:修改 utils/date-time.js
javascript
/**
* 日期时间工具类
* 基于 Day.js 实现
*/
const dayjs = require('dayjs')
/**
* 扩展 duration 插件
*/
const duration = require('./plugins/dayjs/duration.js')
dayjs.extend(duration)
/**
* 扩展 relativeTime 插件(相对时间)
*/
const relativeTime = require('./plugins/dayjs/relativeTime.js')
dayjs.extend(relativeTime)
/**
* 扩展 weekday 插件(星期)
*/
const weekday = require('./plugins/dayjs/weekday.js')
dayjs.extend(weekday)
/**
* 扩展 isBetween 插件(判断是否在两个日期之间)
*/
const isBetween = require('./plugins/dayjs/isBetween.js')
dayjs.extend(isBetween)
/**
* 日期时间工具类
*/
const DateTimeUtil = {
format(date, format = 'YYYY-MM-DD HH:mm:ss') {
if (!date) return ''
return dayjs(date).format(format)
},
// ... 其他方法
}
module.exports = DateTimeUtil
步骤 4:构建 npm 并重新编译
bash
# 在微信开发者工具中依次执行:
# 1. 工具 > 清除缓存 > 全部清除
# 2. 工具 > 构建 npm
# 3. 工具 > 编译
方案对比
| 特性 | 方案一:复制到 miniprogram_npm | 方案二:本地化插件(推荐) |
|---|---|---|
| 代码修改 | 无需修改代码 | 需要修改 require 路径 |
| 版本控制 | 不纳入版本控制(临时文件) | 纳入版本控制 |
| 团队协作 | 每个开发者需要手动复制 | 自动同步 |
| 可维护性 | 较低 | 较高 |
| npm 构建 | 仍然需要 | 仍然需要 |
| 推荐度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
微信小程序基础库版本的影响
在实际测试中,我们发现不同的基础库版本对 Day.js 插件的支持存在差异:
测试场景
| 基础库版本 | 项目配置最低基础库版本 | 构建结果 | 插件目录 |
|---|---|---|---|
| 3.13.2 | libVersion: "3.13.2" | ✅ 成功 | 缺失 plugin 目录 |
| 3.13.2 | libVersion: "2.19.4" | ✅ 成功 | 缺失 plugin 目录 |
结论:无论使用哪个基础库版本(3.13.2 或 2.19.4),微信小程序的 npm 构建工具都无法自动处理 Day.js 的插件子目录。这是一个普遍存在的问题,与基础库版本无关。
问题根因分析
1. 微信小程序 npm 构建工具的限制
微信小程序的 npm 构建工具在处理某些 npm 包的子模块时存在兼容性问题:
- 路径解析问题 :当使用
require('dayjs/plugin/duration.js')时,构建工具无法正确解析插件子模块的路径 - 构建产物问题 :构建后的
miniprogram_npm/dayjs/目录下缺少plugin子目录
2. Day.js 插件文件的格式
Day.js 的插件文件是 UMD 模块格式,并且是压缩后的单行代码:
javascript
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define(s):(t="undefined"!=typeof globalThis?globalThis:t||self).dayjs_plugin_duration=s()}(this,(function(){"use strict";var t,s,n=1e3,...(大量压缩代码)...
补充说明:虽然插件文件是压缩后的单行代码,但在实际测试中,并未出现之前偶现的语法错误("Missing semicolon")。只要文件被正确复制到指定目录,微信小程序的模块加载器可以正常解析。
3. 微信小程序的模块解析机制
微信小程序的 require() 机制与 Node.js 的 CommonJS 规范存在差异:
- 不支持 npm 包的子模块路径 :
require('package-name/submodule')在小程序中可能无法正确解析 - 需要明确的相对路径:需要使用相对于当前文件的明确路径
最佳实践建议
1. 项目目录结构
wxapp/
├── package.json
├── project.config.json
├── utils/
│ ├── plugins/ # 本地化的第三方插件(如果使用方案二)
│ │ └── dayjs/ # Day.js 插件
│ │ ├── duration.js
│ │ ├── relativeTime.js
│ │ ├── weekday.js
│ │ └── isBetween.js
│ ├── date-time.js # 日期时间工具类
│ └── ...
├── miniprogram_npm/ # npm 构建产物
│ └── dayjs/
│ ├── index.js
│ ├── index.js.map
│ ├── package.json
│ └── plugin/ # 手动创建的插件目录(如果使用方案一)
│ ├── duration.js
│ ├── relativeTime.js
│ ├── weekday.js
│ └── isBetween.js
├── node_modules/ # npm 依赖
│ └── dayjs/
│ ├── plugin/
│ ├── esm/
│ └── ...
└── ...
2. 依赖管理
- 纳入版本控制:将本地化的插件文件纳入 Git 版本控制
- 记录版本信息:在代码注释中记录对应的 dayjs 版本号
- 按需引入:只复制项目实际使用的插件文件,减少项目体积
3. 构建流程
在引入新的 npm 包或更新 dayjs 版本时,建议按以下步骤操作:
bash
# 1. 清理旧的构建产物
cd wxapp
rm -rf node_modules
rm -rf miniprogram_npm
# 2. 安装依赖
npm install
# 3. 复制插件文件(如果使用方案二)
mkdir -p utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/duration.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/isBetween.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/relativeTime.js utils/plugins/dayjs
cp -vf node_modules/dayjs/plugin/weekday.js utils/plugins/dayjs
# 4. 在微信开发者工具中构建 npm
# 工具 > 清除缓存 > 全部清除
# 工具 > 构建 npm
4. 团队协作建议
- 编写文档:在项目的 README 或开发文档中记录插件引入的步骤
- 自动化脚本:可以编写 npm script 自动化插件复制过程
- 代码审查:在 Pull Request 中检查插件文件是否正确更新
自动化脚本示例
为了简化插件文件的管理,可以创建一个自动化脚本:
scripts/copy-dayjs-plugins.sh
bash
#!/bin/bash
# 复制 Day.js 插件文件的自动化脚本
cd "$(dirname "$0")/.."
echo "开始复制 Day.js 插件文件..."
# 创建插件目录
mkdir -p utils/plugins/dayjs
# 复制插件文件
plugins=("duration.js" "relativeTime.js" "weekday.js" "isBetween.js")
for plugin in "${plugins[@]}"; do
if [ -f "node_modules/dayjs/plugin/$plugin" ]; then
cp -vf "node_modules/dayjs/plugin/$plugin" "utils/plugins/dayjs/"
echo "✓ 已复制: $plugin"
else
echo "✗ 文件不存在: node_modules/dayjs/plugin/$plugin"
fi
done
echo "Day.js 插件文件复制完成!"
在 package.json 中添加脚本:
json
{
"scripts": {
"copy:dayjs": "bash scripts/copy-dayjs-plugins.sh",
"postinstall": "npm run copy:dayjs"
}
}
这样在执行 npm install 后会自动复制插件文件。
常见问题 FAQ
Q1: 为什么不直接使用 require('dayjs/plugin/duration')?
A: 微信小程序的 npm 构建工具无法正确处理这种子模块路径,导致 plugin 目录不被复制到 miniprogram_npm 下。
Q2: 方案一和方案二哪个更好?
A: 推荐使用方案二(本地化插件),因为:
- 纳入版本控制,便于团队协作
- 不依赖于构建产物的临时性
- 更容易进行版本管理
Q3: 更新 dayjs 版本时需要注意什么?
A: 需要检查新版本中的插件文件是否有变化,并重新复制插件文件。建议使用自动化脚本减少人为错误。
Q4: 是否需要将复制的插件文件提交到 Git?
A: 如果使用方案二(本地化插件),建议提交到 Git。如果使用方案一(复制到 miniprogram_npm),不推荐提交,应该将其添加到 .gitignore。
Q5: 是否可以使用 esm 版本的插件?
A: 微信小程序目前不完全支持 ES6 模块语法,建议使用 CommonJS 版本的插件文件。
总结
微信小程序的 npm 构建工具在处理 Day.js 插件时存在兼容性问题,主要表现为 plugin 子目录缺失。通过手动复制插件文件到指定目录,可以成功解决问题。
核心要点:
- 问题根源:微信小程序 npm 构建工具无法正确处理 Day.js 的插件子目录
- 解决方案 :手动复制插件文件到
utils/plugins/dayjs/或miniprogram_npm/dayjs/plugin/ - 推荐方案:使用方案二(本地化插件),纳入版本控制
- 版本影响:问题与基础库版本无关(3.13.2 和 2.19.4 都存在此问题)
- 最佳实践:自动化插件复制流程,纳入版本控制,编写团队文档
通过本文提供的解决方案和最佳实践,可以避免在微信小程序项目中遇到类似问题,提高开发效率和团队协作效率。
参考资料
文档创建日期 : 2026-03-21
最后更新日期 : 2026-03-21
文档版本 : 1.0
测试环境: 微信小程序基础库 3.13.2 / 2.19.4
注:本文基于实际项目经验整理,希望对遇到类似问题的开发者有所帮助。如有疑问或建议,欢迎交流讨论。