Meteor.js自动重载报错:已存在名为books的集合
Meteor 2.9.0热重载触发"There is already a collection named 'books'"错误的解决方案
问题场景
使用Meteor.js 2.9.0开发时,保存api目录下的服务端文件触发自动热重载后,出现集合重复创建的报错,但正常启动应用时无异常。相关目录结构与核心代码如下:
目录结构
/imports/api/books.js/server/main.js
核心代码
/imports/api/books.js:
import { Meteor } from 'meteor/meteor'; import SimpleSchema from 'simpl-schema'; export const Books = new Mongo.Collection("books");
/server/main.js:
import "../imports/api/books.js";
完整报错信息
HMR: Error while applying changes: Error: There is already a collection named "books" at Collection._maybeSetUpReplication (collection.js:314:15) at new Collection (collection.js:121:8) at eval (books.js:5:22) at module (books.js:713:1) at hot-module-replacement.js?hash=8bbefadb77097ac852d6d5dd3db9f23e39ee3511:415:7 at fileEvaluate (modules-runtime-hot.js?hash=325e29e1f9abcee55f3cef85ec8a56670bbc6194:388:7) at Module.require (modules-runtime-hot.js?hash=325e29e1f9abcee55f3cef85ec8a56670bbc6194:270:27) at require (modules-runtime-hot.js?hash=325e29e1f9abcee55f3cef85ec8a56670bbc6194:310:21) at hot-module-replacement.js?hash=8bbefadb77097ac852d6d5dd3db9f23e39ee3511:602:7 at Set.forEach (<anonymous>)
问题原因
热模块替换(HMR)机制在重载时会重新执行目标模块的代码,导致new Mongo.Collection("books")被再次调用。MongoDB不允许同名集合重复实例化,即使是同一模块的重载操作也会触发该报错。而正常启动时模块仅执行一次,集合只会被创建一次,因此不会出现问题。
解决方案
方案1:复用已存在的集合实例
修改/imports/api/books.js,创建集合前先检查是否已存在同名集合,存在则直接复用:
import { Meteor } from 'meteor/meteor'; import SimpleSchema from 'simpl-schema'; // 优先获取已存在的集合,不存在则创建新实例 export const Books = Mongo.Collection.get("books") || new Mongo.Collection("books");
该方法能让热重载时直接复用原有集合实例,避免重复创建。
方案2:禁用目标模块的HMR
如果方案1无效,可在集合模块中添加HMR忽略逻辑,让Meteor对该模块触发全量重启而非热重载:
import { Meteor } from 'meteor/meteor'; import SimpleSchema from 'simpl-schema'; // 禁用当前模块的热重载,触发全量重启 if (module.hot) { module.hot.dispose(() => { module.hot.invalidate(); }); } export const Books = new Mongo.Collection("books");
方案3:升级Meteor版本
该问题可能是Meteor 2.9.0的HMR已知bug,尝试升级到2.10及以上版本,官方可能已修复该热重载时集合重复创建的问题。
内容的提问来源于stack exchange,提问作者Kyle Bachan
相关产品推荐
相关产品推荐

