当你将要编写的代码脱离 Meteor 就无法正确编译时,适于编写成 Atmosphere package. 反之,推荐直接编写成 npm package.
那么有哪些情况脱离 Meteor 就无法正确编译了呢?
- 依赖 Meteor 自带的核心 packages.
- 依赖第三方 Atmosphere packages.
- 面向前后端的代码和行为是不同的。
- 除了 JavaScript,还包含 CSS, Less, Sass, Stylus, CoffeScript 和静态文件。
通常来讲,以上四种情况最为常见,更多情况可参考 Atmosphere vs. npm.
如果你将要编写的代码的逻辑具有普适性,可在多个场景重复调用,那么推荐编写为 npm package. 当前 npm packages 既可在 server 端也可在 client 端调用并运行。
第一步(可选),创建一个专门存放 packages 的目录。
mkdir my-packages
第二步,创建一个 package.
meteor create --package username:my-package
创建包裹时,包裹名应遵循特定的命名方式,比如 username:my-package
, username
指你在 Meteor 官网注册的用户名,也可以是某个已注册过的组织的名字;my-package
是包裹名,可随意起名,只要不和 username
发布过的包裹名重复即可。
第三步,创建文件。
包裹中的文件加载方式和项目中的不同,它没有任何默认的加载逻辑,完全需要我们自己定义。因此,文件之间应有完备的 import/export 关系,并且在主文件集中 import,同时把接口 export 出去。什么是主文件,怎么把接口输出,请看第四步。
第四步,配置 package.js
正确配置 package.js 文件是创建一个能被恰当编译的包裹的最重要步骤。Meteor 通过 package.js 中配置的逻辑来加载、编译相应代码,不仅包括你编写的代码,而且包括依赖的第三方编写的代码。为了说明方便,我们分块解释 package.js 中的代码。
Package.describe({
name: 'username:my-package',
version: '0.0.1',
documentation: 'README.md'
})
这块代码负责描述包裹的基本信息。其中 name
和 version
最为重要,这里的 name
对应 meteor add username:my-package
,version
遵循语义化版本规范(SemVer),以告知那些依赖本包裹的包裹,新版本是否还能被依赖。documentation
默认为 README.md
,其中应写明包裹的用途,并介绍主要 API 的使用方法。
Package.onUse(function (api) {
// 1
api.versionsFrom('1.2.1')
// 2.1
api.use('ecmascript')
api.use([
'service-configuration',
'accounts-base',
'oauth',
'oauth2',
'accounts-oauth',
'lzl:[email protected]'
])
// 2.2
api.use('random', 'client')
api.use('http', 'server')
// 3
api.mainModule('client.js', 'client')
api.mainModule('server.js', 'server')
})
这块代码是 package.js 的核心,Meteor 正是通过这块代码完成加载和编译的。
第一部分指定 Meteor 的版本号,默认 1.2.1 即可,有特殊需要再作调整。
第二部分指定引用的核心包裹和第三方包裹,可用字符串或包含字符串的数组来表示,第二个参数表示限定在哪里(浏览器或服务器)引用,空缺则不做限制。值得注意的是,引用的第三方包裹要明确版本号,否则将无法识别。
第三部分指定上一步提到的主文件。一般来讲,这两行就足够了,其他文件的 import/export 要在这两个文件中完成,而无需在 package.js 中赘述。同样的,第二个参数表示限定在哪里有效。
为了理解得更加清晰,这里再把 client.js 展开,看一看这个主文件的 API 接口是如何输出的。
import { Random } from 'meteor/random'
export const secretSeed = Random.secret()
你没看错,它就可以这么简单的两行搞定,甚至一行都可以,只要 export 出去东西就行。值得注意的是,因为这里在 client 端 import 了一个名为 meteor/random 的核心包裹,所以必须在上面那段代码中声明 api.use('random', 'client')
,否则将无法识别。
在本例中,只要 meteor add username:my-package
后,便可在 client 端引用。
import { secretSeed } from 'meteor/username:my-package'
console.log(secretSeed)
值得注意的是,因为你编写的是 Atmosphere packages,引用包裹名时要加入 meteor 前缀,Meteor 的 build 工具便可据此将 Atmosphere packages 和 npm packages 区分开来。