Appearance
Meteor 打包系统:Atmosphere 包
¥Meteor packaging system: Atmosphere packages
在本教程中,我们将介绍 Meteor 的打包系统:Atmosphere 软件包。Atmosphere 包是一种创建可重用代码的方法,这些代码可以被多个应用共享。它们可以包含客户端和服务端代码,以及图片和样式表等资源。
¥In this tutorial we will present the Meteor packaging system: Atmosphere packages. Atmosphere packages are a way to create reusable code that can shared by multiple apps. They can contain both client and server code, as well as assets like images and stylesheets.
当然,你也可以在 Meteor 应用中使用 npm 包。本教程仅关注 Meteor 包,这是一个不同的系统。
¥Of course, you can also use npm packages in your Meteor apps. This tutorial only focuses on Meteor packages, which are a different system.
目前存在两个公开的 Meteor 包仓库:
¥Two public repositories of Meteor packages exist:
Atmosphere:Meteor 软件包的原始仓库,其中包含各种社区贡献的软件包。
¥Atmosphere: The original repository for Meteor packages, which hosts a wide variety of community-contributed packages.
Packosphere:一个更新的、由社区维护的 Atmosphere 替代方案。Packosphere 提供了有关包质量和维护状态的更多信息。
¥Packosphere: A newer repository and community maintained alternative to Atmosphere. Packosphere has more information about package quality and maintenance status.
目录
¥Table of Contents
使用 Atmosphere 包
¥Using Atmosphere packages
何时使用 Atmosphere 包
¥When to use Atmosphere packages
Atmosphere 包是专门为 Meteor 编写的包,与 npm 相比,在与 Meteor 一起使用时具有诸多优势。特别是,Atmosphere 包可以:
¥Atmosphere packages are packages written specifically for Meteor and have several advantages over npm when used with Meteor. In particular, Atmosphere packages can:
依赖 Meteor 核心包,例如
ddp、mongo或accounts¥Depend on core Meteor packages, such as
ddp,mongooraccounts显式包含非 JavaScript 文件,例如 CSS、Less 或静态资源。
¥Explicitly include non-javascript files including CSS, Less or static assets
为客户端和服务端提供不同的代码,从而在不同的上下文中实现不同的行为。
¥Have a well defined way to ship different code for client and server, enabling different behavior in each context
无需显式使用 ES2015
import,即可直接访问 Meteor 的 包命名空间 和全局导出包¥Get direct access to Meteor's package namespacing and package global exports without having to explicitly use ES2015
import使用 Meteor 的 约束解析器 强制包之间保持精确的版本依赖
¥Enforce exact version dependencies between packages using Meteor's constraint resolver
为 Meteor 的构建系统包含 构建插件
¥Include build plugins for Meteor's build system
包含适用于不同服务器架构(例如 Linux 或 Windows)的预构建二进制代码
¥Include pre-built binary code for different server architectures, such as Linux or Windows
如果你的包依赖于另一个 Atmosphere 包,或者需要利用 Meteor 的 构建系统,那么目前编写一个 Atmosphere 包可能是最佳选择。
¥If your package depends on another Atmosphere package, or needs to take advantage of Meteor's build system, writing an Atmosphere package might be the best option for now.
包命名
¥Package naming
Atmosphere 上的所有包的名称都采用 prefix:package-name 的形式。前缀是发布该软件包的组织或用户的 Meteor 开发者用户名。Meteor 使用这种包命名约定,以确保清楚地知道哪个包是由谁发布的,并避免使用临时命名空间约定。Meteor 平台包不包含任何 prefix:,或者可以使用 mdg:。
¥All packages on Atmosphere have a name of the form prefix:package-name. The prefix is the Meteor Developer username of the organization or user that published the package. Meteor uses such a convention for package naming to make sure that it's clear who has published a certain package, and to avoid an ad-hoc namespacing convention. Meteor platform packages do not have any prefix: or may use mdg:.
安装 Atmosphere 包
¥Installing Atmosphere Packages
要安装 Atmosphere 包,请在你的应用目录中使用 meteor add:
¥To install an Atmosphere package, you use meteor add inside your app directory:
bash
meteor add ostrio:flow-router-extra这将添加所需软件包的最新版本,该版本与你的应用中的其他软件包以及你的 Meteor 应用版本兼容。如果你想指定特定版本,可以在包名后添加后缀,例如:meteor add ostrio:flow-router-extra@3.12.0。
¥This will add the newest version of the desired package that is compatible with the other packages in your app and your Meteor app version. If you want to specify a particular version, you can specify it by adding a suffix to the package name like: meteor add ostrio:flow-router-extra@3.12.0.
无论你如何将包添加到你的应用中,其实际版本都将在 .meteor/versions 文件中跟踪。这意味着与你协作开发同一应用的任何人,其包版本都将与你相同。如果你想在安装包后更新到更高版本,请使用 meteor update。你可以运行 meteor update 而不带任何参数,以将所有包和 Meteor 本身更新到最新版本;或者你可以传递一个特定的包来仅更新该包,例如 meteor update ostrio:flow-router-extra。
¥Regardless of how you add the package to your app, its actual version will be tracked in the file at .meteor/versions. This means that anybody collaborating with you on the same app is guaranteed to have the same package versions as you. If you want to update to a newer version of a package after installing it, use meteor update. You can run meteor update without any arguments to update all packages and Meteor itself to their latest versions, or pass a specific package to update just that one, for example meteor update ostrio:flow-router-extra.
如果你的应用在添加新包时正在运行,Meteor 将自动下载该包并重启你的应用。
¥If your app is running when you add a new package, Meteor will automatically download it and restart your app for you.
给定版本的 Atmosphere 包的实际文件存储在本地
~/.meteor/packages目录中。¥The actual files for a given version of an Atmosphere package are stored in your local
~/.meteor/packagesdirectory.
要查看所有已安装的 Atmosphere 软件包,请运行:
¥To see all the Atmosphere packages installed run:
bash
meteor list要删除不需要的 Atmosphere 软件包,请运行:
¥To remove an unwanted Atmosphere package run:
bash
meteor remove ostrio:flow-router-extra你可以在 Meteor 命令行文档 中获取有关所有包命令的更多详细信息。
¥You can get more details on all the package commands in the Meteor Command line documentation.
在应用内使用 Atmosphere 包
¥Using Atmosphere Packages inside your app
要在应用中使用 Atmosphere 包,你可以使用 meteor/ 前缀导入它:
¥To use an Atmosphere Package in your app you can import it with the meteor/ prefix:
js
import { Mongo } from "meteor/mongo";通常,一个包会导出一个或多个符号,你需要使用解构语法来引用这些符号。你可以通过在包的 package.js 文件中查找 api.export 调用,或者在包的主 JavaScript 文件中查找类似 export const packageName = 'package-name'; 的 ES2015 export 调用来找到这些导出的符号。
¥Typically a package will export one or more symbols, which you'll need to reference with the destructuring syntax. You can find these exported symbols by either looking in that package's package.js file for api.export calls or by looking in that package's main JavaScript file for ES2015 export calls like export const packageName = 'package-name';.
有时,某个包可能没有导出,并且在应用中包含它时会产生副作用。在这种情况下,安装后完全不需要导入该包。
¥Sometimes a package will have no exports and have side effects when included in your app. In such cases you don't need to import the package at all after installing.
为了向后兼容 Meteor 1.2 及早期版本,Meteor 默认会将你已安装的任何包中
api.export引用的所有符号直接提供给你的应用。但是,建议你在使用这些符号之前先导入它们。¥For backwards compatibility with Meteor 1.2 and early releases, Meteor by default makes available directly to your app all symbols referenced in
api.exportin any packages you have installed. However, it is recommended that you import these symbols first before using them.
从 Atmosphere 包中导入样式
¥Importing styles from Atmosphere packages
使用 Meteor 支持的任何 CSS 预处理器,只要将其他样式文件指定为延迟解析为 "import" 文件,就可以使用 {package-name} 语法导入这些文件。有关如何确定此目录的更多详细信息,请参阅 CSS 源文件与导入文件 文件。
¥Using any of Meteor's supported CSS pre-processors you can import other style files using the {package-name} syntax as long as those files are designated to be lazily evaluated as "import" files. To get more details on how to determine this see CSS source versus import files.
less
@import '{prefix:package-name}/buttons/styles.import.less';Atmosphere 包中的 CSS 文件使用
api.addFiles声明,因此默认情况下会被立即执行,然后与应用中的所有其他 CSS 文件打包在一起。¥CSS files in an Atmosphere package are declared with
api.addFiles, and therefore will be eagerly evaluated by default, and then bundled with all the other CSS in your app.
对等 npm 依赖
¥Peer npm dependencies
Atmosphere 包可以包含 npm 依赖,在这种情况下,你无需进行任何操作即可使其正常工作。但是,某些 Atmosphere 包会要求你在应用中安装特定的 "peer" npm 依赖。
¥Atmosphere packages can ship with contained npm dependencies, in which case you don't need to do anything to make them work. However, some Atmosphere packages will expect that you have installed certain "peer" npm dependencies in your application.
通常情况下,如果你没有这样做,包会发出警告。例如,如果你将 react-meteor-data 包安装到你的应用中,则还需要安装 react 和 react-addons-pure-render-mixin 包:
¥Typically the package will warn you if you have not done so. For example, if you install the react-meteor-data package into your app, you'll also need to install the react and the react-addons-pure-render-mixin packages:
bash
meteor npm install --save react react-addons-pure-render-mixin
meteor add react-meteor-dataAtmosphere 包命名空间
¥Atmosphere package namespacing
你在应用中使用的每个 Atmosphere 包都存在于其独立的命名空间中,这意味着它只能看到自己的全局变量以及它所依赖的包提供的变量。在包中定义顶层变量时,它要么声明为局部作用域,要么声明为包作用域。
¥Each Atmosphere package that you use in your app exists in its own separate namespace, meaning that it sees only its own global variables and any variables provided by the packages that it specifically uses. When a top-level variable is defined in a package, it is either declared with local scope or package scope.
js
/**
* local scope - this variable is not visible outside of the block it is
* declared in and other packages and your app won't see it
*/
const alicePerson = {name: "alice"};
/**
* package scope - this variable is visible to every file inside of the
* package where it is declared and to your app
*/
bobPerson = {name: "bob"};请注意,这只是声明局部变量或全局变量的普通 JavaScript 语法。Meteor 会扫描你的源代码,查找全局变量赋值,并生成一个封装器,以确保你的全局变量不会跳出其相应的命名空间。
¥Notice that this is just the normal JavaScript syntax for declaring a variable that is local or global. Meteor scans your source code for global variable assignments and generates a wrapper that makes sure that your globals don't escape their appropriate namespace.
除了本地作用域和包作用域之外,还有包导出。包导出是一个 "伪全局变量" 变量,包会在你安装该包时将其提供给你使用。例如,email 包导出 Email 变量。如果你的应用使用了 email 包(并且仅当它使用了 email 包时!),那么你的应用就可以访问 Email 符号,并且可以调用 Email.send。大多数包只有一个导出项,但有些包可能有两到三个导出项(例如,提供多个协同工作的类的包)。
¥In addition to local scope and package scope, there are also package exports. A package export is a "pseudo global" variable that a package makes available for you to use when you install that package. For example, the email package exports the Email variable. If your app uses the email package (and only if it uses the email package!) then your app can access the Email symbol and you can call Email.send. Most packages have only one export, but some packages might have two or three (for example, a package that provides several classes that work together).
建议你使用
ecmascript包,并在应用中先调用import { Email } from 'meteor/email';,然后再调用Email.send。建议包开发者现在在其主 JavaScript 文件中使用 ES2015export而不是api.export。¥It is recommended that you use the
ecmascriptpackage and first callimport { Email } from 'meteor/email';before callingEmail.sendin your app. It is also recommended that package developers now use ES2015exportfrom their main JavaScript file instead ofapi.export.
你的应用只能访问你直接使用的包的导出内容。如果你使用包 A,而包 A 又使用了包 B,那么你只会看到包 A 的导出。即使你使用了包 A,包 B 的导出也不会自动添加到你的命名空间中。每个应用或包只能看到自己的全局变量以及它所依赖的包的 API。
¥Your app sees only the exports of the packages that you use directly. If you use package A, and package A uses package B, then you only see package A's exports. Package B's exports don't "leak" into your namespace just because you used package A. Each app or package only sees their own globals plus the APIs of the packages that they specifically use and depend upon.
编写 Atmosphere 包
¥Writing Atmosphere packages
要开始编写包,请使用 Meteor 命令行工具:
¥To get started writing a package, use the Meteor command line tool:
bash
meteor create --package my-package如果你计划将包发布到 Atmosphere,则
my-package的名称必须采用username:my-package的形式,其中username是你的 Meteor 开发者用户名。¥It is required that your
my-packagename take the form ofusername:my-package, whereusernameis your Meteor Developer username, if you plan to publish your package to Atmosphere.
如果在应用中运行此命令,它会将新生成的包放置在该应用的 packages/ 目录中。在应用外部,它只会创建一个独立的包目录。该命令还会为你生成一些样板文件:
¥If you run this inside an app, it will place the newly generated package in that app's packages/ directory. Outside an app, it will just create a standalone package directory. The command also generates some boilerplate files for you:
txt
my-package
├── README.md
├── package.js
├── my-package-tests.js
└── my-package.jspackage.js 文件是每个 Meteor 包中的主文件。这是一个 JavaScript 文件,用于定义 Meteor 包的元数据、加载的文件、架构、npm 包和 Cordova 包。
¥The package.js file is the main file in every Meteor package. This is a JavaScript file that defines the metadata, files loaded, architectures, npm packages, and Cordova packages for your Meteor package.
在本教程中,我们将介绍构建包的一些要点,但不会详细解释 package.js API 的每个部分。要了解所有选项,请运行 阅读 Meteor 文档中的 package.js API 相关信息。
¥In this tutorial, we will go over some important points for building packages, but we won't explain every part of the package.js API. To learn about all of the options, read about the package.js API in the Meteor docs.
完成包的开发后,请务必运行
meteor add [my-package]以便使用它;如果软件包是仅供内部使用的本地软件包,或者你已将软件包发布到 Atmosphere,则此规则适用。¥Don't forget to run
meteor add [my-package]once you have finished developing your package in order to use it; this applies if the package is a local package for internal use only or if you have published the package to Atmosphere.
添加文件和资源
¥Adding files and assets
Atmosphere 包的主要功能是包含源代码(JS、CSS 和任何转译后的语言)和资源(图片、字体等),这些资源将在不同的应用之间共享。
¥The main function of an Atmosphere package is to contain source code (JS, CSS, and any transpiled languages) and assets (images, fonts, and more) that will be shared across different applications.
添加 JavaScript
¥Adding JavaScript
要向包中添加 JavaScript 文件,请在包的 onUse 代码块中指定一个入口点,并使用 api.mainModule()(这已由上面的 meteor create --package 完成):
¥To add JavaScript files to a package, specify an entrypoint with api.mainModule() in the package's onUse block (this will already have been done by meteor create --package above):
js
Package.onUse(function(api) {
api.mainModule('my-package.js');
});从该入口点,你可以将包内的其他文件以 import 或 就像在应用中一样 格式渲染。
¥From that entrypoint, you can import other files within your package, just as you would in an application.
如果你想在客户端和服务器端包含不同的文件,可以使用函数的第二个参数指定多个入口点:
¥If you want to include different files on the client and server, you can specify multiple entry points using the second argument to the function:
js
Package.onUse(function(api) {
api.mainModule('my-package-client.js', 'client');
api.mainModule('my-package-server.js', 'server');
});你还可以以类似的方式添加任何会被编译成 JS 文件的源文件(例如 CoffeeScript 文件),前提是你已为相应的构建插件添加了 depend 前缀。
¥You can also add any source file that would be compiled to a JS file (such as a CoffeeScript file) in a similar way, assuming you depend on an appropriate build plugin.
添加 CSS
要将 CSS 文件包含在你的包中,你可以使用 api.addFiles():
¥To include CSS files with your package you can use api.addFiles():
js
Package.onUse(function(api) {
api.addFiles('my-package.css', 'client');
});CSS 文件将自动加载到任何使用你的包的应用中。
¥The CSS file will be automatically loaded into any app that uses your package.
添加 Sass、Less 或 Stylus mixin/变量
¥Adding Sass, Less, or Stylus mixins/variables
就像包可以导出 JavaScript 代码一样,它们也可以导出可重用的 CSS 预处理器代码片段。你还可以创建一个实际上不包含任何 CSS,而只是导出不同可重用 mixin 和变量的包。更多详情请参阅 Meteor 构建工具 CSS 预处理器:
¥Just like packages can export JavaScript code, they can export reusable bits of CSS pre-processor code. You can also have a package that doesn't actually include any CSS, but just exports different bits of reusable mixins and variables. To get more details see Meteor build tool CSS pre-processors:
js
Package.onUse(function(api) {
api.addFiles('my-package.scss', 'client');
});此 Sass 文件将被立即执行,其编译后的形式将立即添加到应用的 CSS 中。
¥This Sass file will be eagerly evaluated and its compiled form will be added to the CSS of the app immediately.
js
Package.onUse(function(api) {
api.addFiles([
'stylesheets/_util.scss',
'stylesheets/_variables.scss'
], 'client', {isImport: true});
});这两个 Sass 文件将采用惰性求值,并且只有在从其他文件导入时才会包含在应用的 CSS 中。
¥These two Sass files will be lazily evaluated and only included in the CSS of the app if imported from some other file.
添加其他资源
¥Adding other assets
你可以使用 api.addAssets 将其他资源(例如字体、图标或图片)包含到你的包中:
¥You can include other assets, such as fonts, icons or images, to your package using api.addAssets:
js
Package.onUse(function(api) {
api.addAssets([
'font/OpenSans-Regular-webfont.eot',
'font/OpenSans-Regular-webfont.svg',
'font/OpenSans-Regular-webfont.ttf',
'font/OpenSans-Regular-webfont.woff',
], 'client');
});然后,你可以从客户端通过 URL /packages/username_my-package/font/OpenSans-Regular-webfont.eot 访问这些文件,或者从服务器端使用 Assets API 访问这些文件。
¥You can then access these files from the client from a URL /packages/username_my-package/font/OpenSans-Regular-webfont.eot or from the server using the Assets API.
导出
¥Exporting
虽然有些包的存在仅仅是为了给应用提供一些副作用,但大多数包提供的是一段可重用的代码,供用户使用 import。要从你的包中导出符号,请在 mainModule 中使用 ES2015 export 语法:
¥While some packages exist just to provide side effects to the app, most packages provide a reusable bit of code that can be used by the consumer with import. To export a symbol from your package, use the ES2015 export syntax in your mainModule:
js
// in my-package.js:
export const myName = 'my-package';现在,你的包的用户可以使用以下方式导入符号:
¥Now users of your package can import the symbol with:
js
import { myName } from 'meteor/username:my-package';依赖
¥Dependencies
你的包很可能需要使用其他包。为了确保依赖可用,你可以声明依赖。Atmosphere 包可以依赖于其他 Atmosphere 包以及来自 npm 的包。
¥Chances are your package will want to make use of other packages. To ensure they are available, you can declare dependencies. Atmosphere packages can depend both on other Atmosphere packages, as well as packages from npm.
Atmosphere 依赖
¥Atmosphere dependencies
要依赖其他 Atmosphere 包,请使用 api.use:
¥To depend on another Atmosphere package, use api.use:
js
Package.onUse(function(api) {
// This package depends on 1.2.0 or above of validated-method
api.use('mdg:validated-method@1.2.0');
});Atmosphere 包系统的一个重要特性是单次加载:同一应用中的两个包不能依赖于同一包的不同版本。请参阅下方关于版本限制的部分,了解更多信息。
¥One important feature of the Atmosphere package system is that it is single-loading: no two packages in the same app can have dependencies on conflicting versions of a single package. Read more about that in the section about version constraints below.
依赖于 Meteor 版本
¥Depending on Meteor version
请注意,Meteor 的版本号主要是一种营销手段。 - Meteor 核心软件包本身通常不共享版本号。这意味着包只能依赖于 Meteor 版本中特定版本的包,但不能依赖于特定版本本身。我们提供了一个名为 api.versionsFrom 的便捷简写 API,它会自动填充特定版本中的包版本号,从而为你处理此问题:
¥Note that the Meteor release version number is mostly a marketing artifact - the core Meteor packages themselves typically don't share this version number. This means packages can only depend on specific versions of the packages inside a Meteor release, but can't depend on a specific release itself. We have a helpful shorthand api called api.versionsFrom that handles this for you by automatically filling in package version numbers from a particular release:
js
// Use versions of core packages from Meteor 1.2.1
api.versionsFrom('1.2.1');
api.use([
// Don't need to specify version because of versionsFrom above
'ecmascript',
'check',
// Still need to specify versions of non-core packages
'mdg:validated-method@1.2.0',
'mdg:validation-error@0.1.0'
]);上面的代码片段等效于下面的代码,后者单独指定了所有版本号:
¥The above code snippet is equivalent to the code below, which specifies all of the version numbers individually:
js
api.use([
'ecmascript@0.1.6',
'check@1.1.0',
'mdg:validated-method@1.2.0',
'mdg:validation-error@0.1.0'
]);此外,你可以多次调用 api.versionsFrom(<release>),或使用数组(例如 api.versionsFrom([<release1>, <release2>]))。Meteor 会将其解释为该包将与所有列出的版本中的包兼容。
¥Additionally, you can call api.versionsFrom(<release>) multiple times, or with an array (eg api.versionsFrom([<release1>, <release2>]). Meteor will interpret this to mean that the package will work with packages from all the listed releases.
js
api.versionsFrom('1.2.1');
api.versionsFrom('1.4');
api.versionsFrom('1.8');
// or
api.versionsFrom(['1.2.1', '1.4', '1.8']);通常情况下不需要这样做,但在你需要支持核心包的多个主要版本时会很有帮助。
¥This usually isn't necessary, but can help in cases where you support more than one major version of a core package.
语义化版本控制和版本约束
¥Semantic versioning and version constraints
Meteor 的软件包系统严重依赖于 语义化版本控制,即语义化版本控制 (SemVer)。当一个包声明对另一个包的依赖时,它总是带有版本约束。这些版本约束将由 Meteor 的工业级版本求解器解决,从而得出满足所有要求的软件包版本集;如果找不到解决方案,则会显示有用的错误信息。
¥Meteor's package system relies heavily on Semantic Versioning, or SemVer. When one package declares a dependency on another, it always comes with a version constraint. These version constraints are then solved by Meteor's industrial-grade Version Solver to arrive at a set of package versions that meet all of the requirements, or display a helpful error if there is no solution.
这里的思维模型是:
¥The mental model here is:
主版本号必须始终完全匹配。如果软件包
a依赖于b@2.0.0,则只有当软件包b的版本号以2开头时,该约束才能得到满足。这意味着同一个应用中永远不能存在两个不同的包主版本。¥The major version must always match exactly. If package
adepends onb@2.0.0, the constraint will only be satisfied if the version of packagebstarts with a2. This means that you can never have two different major versions of a package in the same app.次版本号和补丁版本号必须大于或等于请求的版本号。如果依赖请求版本
2.1.3,则2.1.4和2.2.0可以正常工作,但2.0.4和2.1.2则不行。¥The minor and patch version numbers must be greater or equal to the requested version. If the dependency requests version
2.1.3, then2.1.4and2.2.0will work, but2.0.4and2.1.2will not.
由于 Meteor 的包系统是单加载的,因此需要约束求解器。 - 也就是说,同一个应用中永远不能并排加载同一软件包的两个不同版本。这对于包含大量客户端代码的软件包,或者预期为单例的软件包尤其有用。
¥The constraint solver is necessary because Meteor's package system is single-loading - that is, you can never have two different versions of the same package loaded side-by-side in the same app. This is particularly useful for packages that include a lot of client-side code, or packages that expect to be singletons.
请注意,版本求解器也包含 "gravity" 的概念。 - 当一组依赖存在多个可能的解决方案时,系统总是选择最早的版本。如果你正在开发一个要分发给大量用户的软件包,这将非常有用,因为它能确保你的软件包与依赖的最低公分母兼容。如果你的包需要比某个依赖当前选择的版本更新的版本,则需要更新 package.js 以设置更新的版本约束。
¥Note that the version solver also has a concept of "gravity" - when many solutions are possible for a certain set of dependencies, it always selects the oldest possible version. This is helpful if you are trying to develop a package to ship to lots of users, since it ensures your package will be compatible with the lowest common denominator of a dependency. If your package needs a newer version than is currently being selected for a certain dependency, you need to update your package.js to have a newer version constraint.
如果你的包支持依赖的多个主版本,你可以像这样同时向 api.use 提供这两个版本:
¥If your package supports multiple major versions of a dependency, you can supply both versions to api.use like so:
js
api.use('blaze@1.0.0 || 2.0.0');Meteor 将使用与你的其他软件包兼容的主版本,或给定选项中的最新版本。
¥Meteor will use whichever major version is compatible with your other packages, or the most recent of the options given.
npm 依赖
¥npm dependencies
Meteor 包可以包含 npm 包,以便使用来自 Meteor 包生态系统之外的 JavaScript 代码,或包含具有原生依赖的 JavaScript 代码。在 package.js 文件的顶层使用 Npm.depends。例如,以下是如何包含 github npm 包:
¥Meteor packages can include npm packages to use JavaScript code from outside the Meteor package ecosystem or to include JavaScript code with native dependencies. Use Npm.depends at the top level of your package.js file. For example, here's how you would include the github npm package:
js
Npm.depends({
github: '0.2.4'
});如果你想使用本地 npm 包(例如在开发过程中),可以使用目录名代替版本号:
¥If you want to use a local npm package, for example during development, you can give a directory instead of a version number:
js
Npm.depends({
my-package: 'file:///home/user/npms/my-package'
});你可以像在应用中一样,从包代码中导入依赖:
¥You can import the dependency from within you package code in the same way that you would inside an application:
js
import github from 'github';对等 npm 依赖
¥Peer npm dependencies
Npm.depends() 的版本要求相当严格(你只能依赖一个确切的版本),如果许多不同的 Atmosphere 包依赖于同一个 npm 包,通常会导致安装该包的多个版本。因此,在客户端使用它并不理想,因为将同一包代码的多个副本发送到浏览器是不切实际的。客户端包通常也假定只会加载一个副本。例如,如果 React 在应用包中被多次包含,它会报错。
¥Npm.depends() is fairly rigid (you can only depend on an exact version), and will typically result in multiple versions of a package being installed if many different Atmosphere packages depend on the same npm package. This makes it less than ideal to use on the client, where it's impractical to ship multiple copies of the same package code to the browser. Client-side packages are also often written with the assumption that only a single copy will be loaded. For example, React will complain if it is included more than once in an application bundle.
为了避免包作者遇到此问题,你可以要求包的用户在应用级别安装你想要使用的 npm 包。这类似于 npm 软件包的 对等依赖(尽管该工具的支持较少)。你可以使用 tmeasday:check-npm-versions 包来确保他们已完成此操作,并在未完成时发出警告。
¥To avoid this problem as a package author, you can request that users of your package have installed the npm package you want to use at the application level. This is similar to a peer dependency of an npm package (although with less support in the tool). You can use the tmeasday:check-npm-versions package to ensure that they've done this, and to warn them if not.
例如,如果你正在编写一个 React 包,则不应直接依赖 react,而应使用 check-npm-versions 来检查用户是否已安装它:
¥For instance, if you are writing a React package, you should not directly depend on react, but instead use check-npm-versions to check the user has installed it:
js
import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
checkNpmVersions({
'react': '0.14.x'
}, 'my:awesome-package');
// If you are using the dependency in the same file, you'll need to use require, otherwise
// you can continue to `import` in another file.
const React = require('react');请注意,只有当用户安装了不兼容版本的 npm 包时,
checkNpmVersions才会输出警告。因此,你的require调用可能不会返回你预期的结果。这与 npm 对 对等依赖 的处理方式一致。¥Note that
checkNpmVersionswill only output a warning if the user has installed a incompatible version of the npm package. So yourrequirecall may not give you what you expect. This is consistent with npm's handling of peer dependencies.
Cordova 插件
¥Cordova plugins
Atmosphere 包可以包含 Cordova 插件,以便为 Meteor 移动应用容器提供原生代码。这样,你就可以与原生相机界面交互、使用陀螺仪、在本地保存文件等等。
¥Atmosphere packages can include Cordova plugins to ship native code for the Meteor mobile app container. This way, you can interact with the native camera interface, use the gyroscope, save files locally, and more.
使用 Cordova.depends 将 Cordova 插件包含到你的 Meteor 包中。
¥Include Cordova plugins in your Meteor package by using Cordova.depends.
了解更多关于在 移动端指南 中使用 Cordova 的信息。
¥Read more about using Cordova in the mobile guide.
测试包
¥Testing packages
Meteor 有一个名为 meteor test-packages 的包测试模式。如果你位于某个包的目录中,可以运行以下命令:
¥Meteor has a test mode for packages called meteor test-packages. If you are in a package's directory, you can run
bash
meteor test-packages ./ --driver-package meteortesting:mocha这将运行一个仅包含你的软件包 "test" 版本的特殊应用,并启动一个 Mocha 测试驱动程序包。
¥This will run a special app containing only a "test" version of your package and start a Mocha test driver package.
当你的包在测试模式下启动时,Meteor 不会加载 onUse 代码块,而是加载 onTest 代码块:
¥When your package starts in test mode, rather than loading the onUse block, Meteor loads the onTest block:
js
Package.onTest(function(api) {
// You almost definitely want to depend on the package itself,
// this is what you are testing!
api.use('my-package');
// You should also include any packages you need to use in the test code
api.use(['ecmascript', 'random', 'meteortesting:mocha']);
// Finally add an entry point for tests
api.mainModule('my-package-tests.js');
});在测试入口点中,你可以像在包中一样导入其他文件。
¥From within your test entry point, you can import other files as you would in the package proper.
你可以在 测试文章 中了解更多关于 Meteor 测试的信息。
¥You can read more about testing in Meteor in the Testing article.
发布你的包
¥Publishing your package
要将你的软件包发布到 Atmosphere,请从软件包目录运行 meteor publish。要发布软件包,软件包名称必须遵循 username:my-package 的格式,并且软件包必须包含 SemVer 版本号。
¥To publish your package to Atmosphere, run meteor publish from the package directory. To publish a package the package name must follow the format of username:my-package and the package must contain a SemVer version number.
请注意,如果你的包中存在本地
node_modules目录,请在运行meteor publish之前将其删除。虽然 Meteor 包中允许存在本地node_modules目录,但它们的路径在发布时可能会与Npm.depends依赖的路径冲突。¥Note that if you have a local
node_modulesdirectory in your package, remove it before runningmeteor publish. While localnode_modulesdirectories are allowed in Meteor packages, their paths can collide with the paths ofNpm.dependsdependencies when published.
缓存格式
¥Cache format
如果你曾经查看过 Meteor 在 ~/.meteor/packages 上的包缓存,你就会知道,已构建的 Meteor 包的磁盘格式与你在开发包时源代码的格式完全不同。这样做的目的是即使开发 API 发生变化,包的目标格式也能保持一致。
¥If you've ever looked inside Meteor's package cache at ~/.meteor/packages, you know that the on-disk format of a built Meteor package is completely different from the way the source code looks when you're developing the package. The idea is that the target format of a package can remain consistent even if the API for development changes.
本地包
¥Local packages
除了将包发布到 Atmosphere 之外,如果你想保持包的私有性,你可以将其放在 Meteor 应用的 packages/ 目录中,例如 packages/foo/,然后使用 meteor add foo 将其添加到你的应用中。
¥As an alternative to publishing your package on Atmosphere, if you want to keep your package private, you can place it in your Meteor app in the packages/ directory, for instance packages/foo/, and then add it to your app with meteor add foo.
使用 git submodules 处理私有包是一种常见模式。
¥Using git submodules to handle private packages is a common pattern.
使用本地版本覆盖已发布的包
¥Overriding published packages with a local version
如果你需要修改 Atmosphere 包以实现已发布版本未实现的功能,可以在本地计算机上编辑该包的本地版本。
¥If you need to modify an Atmosphere package to do something that the published version doesn't do, you can edit a local version of the package on your computer.
Meteor 应用可以通过三种方式加载 Atmosphere 包,并按以下顺序查找匹配的包名:
¥A Meteor app can load Atmosphere packages in one of three ways, and it looks for a matching package name in the following order:
在你的应用内部的
packages/目录中的包源代码。¥Package source code in the
packages/directory inside your app.在运行任何
meteor命令之前,通过设置METEOR_PACKAGE_DIRS环境变量来指定目录中的包源代码。你可以通过在 OSX 或 Linux 系统上使用:分隔路径,或在 Windows 系统上使用;分隔路径,来添加多个目录。例如:METEOR_PACKAGE_DIRS=../first/directory:../second/directory,或在 Windows 系统上:set PACKAGE_DIRS=..\first\directory;..\second\directory。¥Package source code in directories indicated by setting a
METEOR_PACKAGE_DIRSenvironment variable before running anymeteorcommand. You can add multiple directories by separating the paths with a:on OSX or Linux, or a;on Windows. For example:METEOR_PACKAGE_DIRS=../first/directory:../second/directory, or on Windows:set PACKAGE_DIRS=..\first\directory;..\second\directory.
注意:在 Meteor 1.4.2 之前,
METEOR_PACKAGE_DIRS是PACKAGE_DIRS。出于兼容性考虑,开发者应继续使用METEOR_PACKAGE_DIRS。¥Note: Prior to Meteor 1.4.2,
METEOR_PACKAGE_DIRSwasPACKAGE_DIRS. For compatibility reasons, developers should useMETEOR_PACKAGE_DIRSgoing forward.
来自 Atmosphere 的预构建包。该软件包在 Mac/Linux 系统上缓存于
~/.meteor/packages,在 Windows 系统上缓存于%LOCALAPPDATA%\.meteor\packages,并且仅在构建应用时加载到你的应用中。¥Pre-built package from Atmosphere. The package is cached in
~/.meteor/packageson Mac/Linux or%LOCALAPPDATA%\.meteor\packageson Windows, and only loaded into your app as it is built.
你可以使用 (1) 或 (2) 来覆盖 Atmosphere 中的版本。你甚至可以使用此功能加载 Meteor 核心包的补丁版本。 - 只需复制 Meteor 的 GitHub 代码库 包的代码,然后进行编辑即可。
¥You can use (1) or (2) to override the version from Atmosphere. You can even do this to load patched versions of Meteor core packages - just copy the code of the package from Meteor's GitHub repository, and edit away.

