Appearance
Package.js
包是一个包含 package.js 文件的目录,该文件大致包含三个主要部分:基本描述、包定义和测试定义。默认情况下,目录名称是包的名称。
¥A package is a directory containing a package.js file, which contains roughly three major sections: a basic description, a package definition, and a test definition. By default, the directory name is the name of the package.
下面的 package.js
文件是如何使用打包 API 的示例。本节的其余部分将更详细地解释特定的 API 命令。
¥The package.js
file below is an example of how to use the packaging API. The rest of this section will explain the specific API commands in greater detail.
js
// Information about this package:
Package.describe({
// Short two-sentence summary
summary: 'What this does',
// Version number
version: '1.0.0',
// Optional, default is package directory name
name: 'username:package-name',
// Optional GitHub URL to your source repository
git: 'https://github.com/something/something.git'
});
// This defines your actual package:
Package.onUse((api) => {
// If no version is specified for an `api.use` dependency, use the one defined
// in Meteor 1.12.1.
api.versionsFrom('1.12.1');
// Use the `underscore` package, but only on the server. Version not
// specified, so it will be as of Meteor 1.12.1.
api.use('underscore', 'server');
// Use `ostrio:flow-router-extra`, version 3.9.0 or newer.
api.use('ostrio:flow-router-extra@3.9.0');
// Give users of this package access to active-route's JavaScript helpers.
api.imply('zimme:active-route@2.3.2')
// Export the object `Email` to packages or apps that use this package.
api.export('Email', 'server');
// Specify the source code for the package.
api.addFiles('email.js', 'server');
// When using `ecmascript` or `modules` packages, you can use this instead of
// `api.export` and `api.addFiles`.
api.mainModule('email.js', 'server');
});
// This defines the tests for the package:
Package.onTest((api) => {
// Sets up a dependency on this package.
api.use('username:package-name');
// Use the Mocha test framework.
api.use('practicalmeteor:mocha@2.4.5_6');
// Specify the source code for the package tests.
api.addFiles('email_tests.js', 'server');
});
// This lets you use npm packages in your package:
Npm.depends({
simplesmtp: '0.3.10',
'stream-buffers': '0.2.5'
});
api.mainModule
在 modules 部分有记录。
¥api.mainModule
is documented in the modules section.
构建插件是使用 Package.registerBuildPlugin
创建的。有关示例,请参阅 coffeescript 包。构建插件本身就是成熟的 Meteor 程序,具有自己的命名空间、包依赖、源文件和 npm 要求。
¥Build plugins are created with Package.registerBuildPlugin
. See the coffeescript package for an example. Build plugins are fully-fledged Meteor programs in their own right and have their own namespace, package dependencies, source files and npm requirements.
你可以使用本地包为你的应用定义自定义构建插件,但有一个警告。在已发布的包中,构建插件已经与其传递依赖打包在一起。因此,如果你希望本地包满足构建插件的依赖,则必须使用定义该插件的包的本地副本(即使你没有对该包进行任何更改),以便 Meteor 能够获取本地依赖。
¥You can use local packages to define custom build plugins for your app, with one caveat. In published packages, build plugins are already bundled with their transitive dependencies. So if you want a dependency of a build plugin to be satisfied by a local package, you must use a local copy of the package that defines the plugin (even if you make no changes to that package) so that Meteor will pick up the local dependency.
在包的生命周期中,可能会因为各种原因而结束开发,或者被取代。在任一情况下,Meteor 都允许你通过将弃用标志设置为 true 来轻松通知包的用户:包描述中的
deprecated: true
。此外,你还可以用字符串替换它,该字符串告诉用户在哪里可以找到替换文件或要做什么。¥In a lifecycle of a package there might come time to end the development for various reasons, or it gets superseded. In either case Meteor allows you to easily notify the users of the package by setting the deprecated flag to true:
deprecated: true
in the package description. In addition, you replace it with a string that tells the users where to find replacement or what to do.
提供 Package.describe(options)
的基本包信息。要发布包,你必须定义 summary
和 version
。
¥Provide basic package information with Package.describe(options)
. To publish a package, you must define summary
and version
.
api.describe package.js only
package.js only
Summary:
Provide basic package information.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
options | Object | Yes |
js
// api is an instance of PackageNamespace
api.describe(
options
);
使用 Package.onUse
处理程序定义依赖并公开包方法。本节让你定义你的包依赖于哪些包、你的包隐含哪些包以及你的包导出到哪个对象。
¥Define dependencies and expose package methods with the Package.onUse
handler. This section lets you define what packages your package depends on, what packages are implied by your package, and what object your package is exported to.
api.onUse package.js only
package.js only
Summary:
Define package dependencies and expose package methods.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
func | function | A function that takes in the package control | Yes |
js
// api is an instance of PackageNamespace
api.onUse(
() => {}
);
api.versionsFrom package.js only
package.js only
Summary:
Use versions of core packages from a release. Unless provided,
all packages will default to the versions released along with
meteorRelease
. This will save you from having to figure out the exact
versions of the core packages you want to use. For example, if the newest
release of meteor is METEOR@0.9.0
and it includes jquery@1.0.0
, you
can write api.versionsFrom('METEOR@0.9.0')
in your package, and when you
later write api.use('jquery')
, it will be equivalent to
api.use('jquery@1.0.0')
. You may specify an array of multiple releases,
in which case the default value for constraints will be the "or" of the
versions from each release: api.versionsFrom(['METEOR@0.9.0', 'METEOR@0.9.5'])
may cause api.use('jquery')
to be interpreted as
api.use('jquery@1.0.0 || 2.0.0')
.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
meteorRelease | String or Array.<String> | Specification of a release:
track@version. Just 'version' (e.g. | Yes |
js
// api is an instance of PackageAPI
api.versionsFrom(
"meteorRelease"
);
谨慎选择 Meteor 版本。首先确定你在包中使用的 API 所需的 Meteor 最低版本。这应该基于你的包的特定需求,例如需要 *Async 调用,这需要最低版本至少为 2.8。另一个示例是软件包有重大版本升级,例如 Meteor 2.3 中的账户软件包就发生过这种情况。如果你想要向后和向前兼容,最好在数组中包含 2.3 之前的 Meteor 版本,然后包含 2.3.6。对于大多数账户包兼容性的一般建议(除非你需要 Meteor 2.3 中受影响的 API),在
versionsFrom
中具有以下数组:['1.12.1', '2.3.6', '2.8.1']
,这给了我们最广泛的范围。对于一般软件包,你可以省略版本2.3.6
。如果你想要最广泛的兼容性范围,建议最低版本为1.12.1
,并且还包含接近当前 Meteor 版本的另一个版本。¥Choose Meteor versions carefully. First determine the minimum version of Meteor you need for the API you use in your package. This should be based on specific needs of your package like needed the *Async calls, which would require minimum version to be at least 2.8. Another example are where packages had a major version bump, for example this has happened with the accounts packages in Meteor 2.3. If you want to be backward and forward compatible it is good to include Meteor version before 2.3 and then 2.3.6 in the array. A general recommendation for most compatibility for accounts packages (unless you need API that was affected in Meteor 2.3) is to have the following array in
versionsFrom
:['1.12.1', '2.3.6', '2.8.1']
, this gives us the widest range. For general packages you can leave out version2.3.6
. If you want the widest compatibility range it is recommended that the lowest be1.12.1
and that you also include another version near the current version of Meteor.
api.use package.js only
package.js only
Summary:
Depend on package packagename
.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
packageNames | String or Array.<String> | Packages being depended on. Package names may be suffixed with an @version tag. In general, you must specify a package's version (e.g.,
| Yes |
architecture | String or Array.<String> | If you only use the package on the
server (or the client), you can pass in the second argument (e.g.,
| No |
options | Object | No |
js
// api is an instance of PackageAPI
api.use(
"packageNames",
"architecture", // this param is optional
options, // this param is optional
);
api.imply package.js only
package.js only
Summary:
Give users of this package access to another package (by passing
in the string packagename
) or a collection of packages (by passing in
an array of strings [packagename1
, packagename2
]
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
packageNames | String or Array.<String> | Name of a package, or array of package names, with an optional @version component for each. | Yes |
architecture | String or Array.<String> | If you only use the package on
the server (or the client), you can pass in the second argument (e.g.,
| No |
js
// api is an instance of PackageAPI
api.imply(
"packageNames",
"architecture", // this param is optional
);
api.export package.js only
package.js only
Summary:
Export package-level variables in your package. The specified
variables (declared without var
in the source code) will be available
to packages that use your package. If your package sets the debugOnly
,
prodOnly
or testOnly
options to true
when it calls
Package.describe()
, then packages that use your package will need to use
Package["package-name"].ExportedVariableName
to access the value of an
exported variable.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
exportedObjects | String or Array.<String> | Name of the object to export, or an array of object names. | Yes |
architecture | String or Array.<String> | If you only want to export the
object on the server (or the client), you can pass in the second argument
(e.g., 'server', 'client', 'web.browser', 'web.cordova') to specify what
architecture the export is used with. You can specify multiple
architectures by passing in an array, for example | No |
exportOptions | Object | ---- | No |
exportOptions.testOnly | Boolean | If true, this symbol will only be exported when running tests for this package. | Yes |
js
// api is an instance of PackageAPI
api.export(
"exportedObjects",
"architecture", // this param is optional
exportOptions, // this param is optional
false,
);
api.addFiles package.js only
package.js only
Summary:
Specify source code files for your package.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
filenames | String or Array.<String> | Paths to the source files. | Yes |
architecture | String or Array.<String> | If you only want to use the file
on the server (or the client), you can pass this argument
(e.g., 'server', 'legacy', 'client', 'web.browser', 'web.cordova') to specify
what architecture the file is used with. You can call api.addFiles(files, "legacy")
in your package.js configuration file to add extra files to the legacy bundle,
or api.addFiles(files, "client") to add files to all client bundles,
or api.addFiles(files, "web.browser") to add files only to the modern bundle.
You can specify multiple
architectures by passing in an array, for example
| No |
options | Object | Options that will be passed to build plugins. | No |
js
// api is an instance of PackageAPI
api.addFiles(
"filenames",
"architecture", // this param is optional
options, // this param is optional
);
api.addAssets package.js only
package.js only
Summary:
Specify asset files for your package. They can be accessed via
the Assets API from the server, or at the URL
/packages/username_package-name/file-name
from the client, depending on the
architecture passed.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
filenames | String or Array.<String> | Paths to the asset files. | Yes |
architecture | String or Array.<String> | Specify where this asset should be
available (e.g., 'server', 'client', 'web.browser', 'web.cordova'). You can
specify multiple architectures by passing in an array, for example
| Yes |
js
// api is an instance of PackageAPI
api.addAssets(
"filenames",
"architecture",
);
使用 Package.onTest
处理程序设置你的测试,该处理程序具有与 onUse
处理程序并行的接口。测试需要依赖于你刚刚创建的包。例如,如果你的包是 email
包,则必须调用 api.use('email')
才能测试该包。
¥Set up your tests with the Package.onTest
handler, which has an interface that's parallel to that of the onUse
handler. The tests will need to depend on the package that you have just created. For example, if your package is the email
package, you have to call api.use('email')
in order to test the package.
如果你使用 meteor create
来设置你的包,Meteor 将在 package.js
中创建所需的脚手架,你只需要在创建的 _test.js
文件中添加单元测试代码。
¥If you used meteor create
to set up your package, Meteor will create the required scaffolding in package.js
, and you'll only need to add unit test code in the _test.js
file that was created.
api.onTest package.js only
package.js only
Summary:
Define dependencies and expose package methods for unit tests.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
func | function | A function that takes in the package control 'api' object, which keeps track of dependencies and exports. | Yes |
js
// api is an instance of PackageNamespace
api.onTest(
() => {}
);
Meteor 包可以通过在 package.js
文件中使用 Npm.depends
和 Cordova.depends
来包含 NPM 包和 Cordova 插件。
¥Meteor packages can include NPM packages and Cordova plugins by using Npm.depends
and Cordova.depends
in the package.js
file.
api.depends package.js only
package.js only
Summary:
Specify which NPM packages your Meteor package depends on.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
dependencies | Object | An object where the keys are package names and the values are one of:
Https URL example:
Git URL example:
| Yes |
js
// api is an instance of PackageNpm
api.depends(
dependencies
);
Npm.require Server only
Server only
Summary:
Require a package that was specified using
Npm.depends()
.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
name | String | The name of the package to require. | Yes |
js
Npm.require(
"name"
);
api.depends package.js only
package.js only
Summary:
Specify which Cordova / PhoneGap plugins your Meteor package depends on.
Plugins are installed from plugins.cordova.io, so the plugins and versions specified must exist there. Alternatively, the version can be replaced with a GitHub tarball URL as described in the Cordova page of the Meteor wiki on GitHub.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
dependencies | Object | An object where the keys are plugin names and the values are version numbers or GitHub tarball URLs in string form. Example:
Alternatively, with a GitHub URL:
| Yes |
js
// api is an instance of PackageCordova
api.depends(
dependencies
);
api.registerBuildPlugin package.js only
package.js only
Summary:
Define a build plugin. A build plugin extends the build
process for apps and packages that use this package. For example,
the coffeescript
package uses a build plugin to compile CoffeeScript
source files into JavaScript.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
options | Object | No |
js
// api is an instance of PackageNamespace
api.registerBuildPlugin(
options
);
选项
¥Options
在某些情况下,我们需要在包中提供选项,这些选项在运行时不会更改。
¥In some cases we need to offer options in packages where these options are not going to change in runtime.
我们更喜欢在配置文件中定义这些选项,而不是使用 JS 代码调用特定函数在运行时定义选项。
¥We prefer to have these options defined in a configuration file instead of using JS code to call specific functions to define options in runtime.
例如,在 quave:collections
包中,你可以强制集合仅在服务器中可用,如下所示:
¥For example, in quave:collections
package you can force collections to be available only in the server like this:
json
"packages": {
"quave:collections": {
"isServerOnly": true
}
}
我们鼓励每个软件包作者遵循此标准来提供选项:
¥We encourage every package author to follow this standard to offer options:
使用官方 Meteor
settings
文件¥Use the official Meteor
settings
file在从
Meteor
.packages
.<package name>
.<your option name>
读取的settings
文件中¥Inside the
settings
file read from aMeteor
.packages
.<package name>
.<your option name>
如果需要在客户端中可用,请遵循
public
键内的相同结构。¥If it needs to be available in the client follow the same structure inside the
public
key.
你可以使用 quave:settings 包读取上述格式的选项,已经合并了私有和公共选项。
¥You can use quave:settings package to read options in the format above already merging the private and public options.
这样,我们就避免了在包中的另一个特定代码之前调用特定代码,因为设置存储在设置中,并且包可以在必要时加载它,而不是依赖于应用代码中开发者的特定调用顺序。
¥This way we avoid having to call a specific code before another specific code in a package as the setting is stored in the settings, and the package can load it when necessary instead of relying on a specific order of calls from the developer in the app code.
我们也已经开始在 Meteor 1.10.2 的核心包中采用此标准。
¥We've started to adopt this standard also in core packages on Meteor 1.10.2.
Plugin.registerSourceHandler Build Plugin only
Build Plugin only
Summary:
Inside a build plugin source file specified in Package.registerBuildPlugin, add a handler to compile files with a certain file extension.
Arguments:
Source codeName | Type | Description | Required |
---|---|---|---|
fileExtension | String | The file extension that this plugin
should handle, without the first dot.
Examples: | Yes |
handler | function | A function that takes one argument, a CompileStep object. Documentation for CompileStep is available on the GitHub Wiki. | Yes |
js
Plugin.registerSourceHandler(
"fileExtension",
() => {},
);
构建插件 API
¥Build Plugins API
Meteor 软件包可以提供构建插件 - 与用于编译和打包应用的构建工具 Isobuild 集成的程序。
¥Meteor packages can provide build plugins - programs that integrate with the build tool Isobuild used to compile and bundle your application.
从 Meteor 1.2 开始,用于插入构建过程的 API 称为 "构建插件"。包的插件可以运行 3 个阶段:linting、编译和压缩。下面是 Isobuild 对应用和包源执行的操作概述:
¥Starting with Meteor 1.2, the API used to plug into the build process is called "Build Plugins". There are 3 phases when a package's plugin can run: linting, compilation and minification. Here is an overview of operations Isobuild performs on the application and packages source:
从应用文件夹收集源文件或读取包的
package.js
文件。¥Gather source files from the app folder or read
package.js
file for a package.检查所有源文件并打印检查警告。
¥Lint all source files and print the linting warnings.
将源文件(如 CoffeeScript、ES2015、Less 或 Templates)编译为纯 JavaScript 和 CSS。
¥Compile the source files like CoffeeScript, ES2015, Less, or Templates to plain JavaScript and CSS.
链接 JavaScript 文件:将它们封装到闭包中并提供必要的包导入。
¥Link the JavaScript files: wrap them into closures and provide necessary package imports.
缩小 JavaScript 和 CSS 文件。还可以包括所有文件的串联。
¥Minify JavaScript and CSS files. Can also include concatenation of all files.
构建插件填补了第 2、3 和 5 阶段。
¥Build plugins fill the phases 2, 3 and 5.
通常,构建插件会实现一个类,该类会给出要处理的文件列表。通常,此类文件具有以下方法:
¥Usually build plugins implement a class that is given a list of files to process. Commonly, such files have the following methods:
getContentsAsBuffer
- 以缓冲区形式返回文件的全部内容。¥
getContentsAsBuffer
- Returns the full contents of the file as a buffer.getContentsAsString
- 以字符串形式返回文件的全部内容。¥
getContentsAsString
- Returns the full contents of the file as a string.getPackageName
- 如果文件不在包中,则返回包的名称或null
。¥
getPackageName
- Returns the name of the package ornull
if the file is not in a package.getPathInPackage
- 返回文件相对于包或应用根目录的相对路径。返回的路径始终使用正斜杠。¥
getPathInPackage
- Returns the relative path of file to the package or app root directory. The returned path always uses forward slashes.getSourceHash
- 返回可用于实现缓存的文件的哈希字符串。¥
getSourceHash
- Returns a hash string for the file that can be used to implement caching.getArch
- 返回处理此文件时针对的体系结构。¥
getArch
- Returns the architecture that is targeted while processing this file.getBasename
- 返回文件的文件名。¥
getBasename
- Returns the filename of the file.getDirname
- 返回相对于包或应用根目录的目录路径。返回的路径始终使用正斜杠。¥
getDirname
- Returns the directory path relative to the package or app root. The returned path always uses forward slashes.error
- 调用此方法可引发文件的编译或 linting 错误。¥
error
- Call this method to raise a compilation or linting error for the file.
Linters
Linter 是检查代码中是否存在未声明变量或查找不符合某些样式指南的代码的程序。一些流行的 linter 示例是 JSHint 和 ESLint。一些非 JavaScript linter 示例包括 CoffeeScript 的 CoffeeLint 和 CSS 的 CSSLint。
¥Linters are programs that check the code for undeclared variables or find code that doesn't correspond to certain style guidelines. Some of the popular examples of linters are JSHint and ESLint. Some of the non-JavaScript linter examples include CoffeeLint for CoffeeScript and CSSLint for CSS.
要在你的包中注册 linter 构建插件,你需要在你的 package.js
中执行几件事:
¥To register a linter build plugin in your package, you need to do a couple of things in your package.js
:
依赖于
isobuild:linter-plugin@1.0.0
包¥depend on the
isobuild:linter-plugin@1.0.0
package注册构建插件:
Package.registerBuildPlugin({ name, sources, ... });
(参见 docs)¥register a build plugin:
Package.registerBuildPlugin({ name, sources, ... });
(see docs)
在你的构建插件源中,注册一个 Linter 插件:提供详细信息,例如插件将处理的扩展名和文件名列表以及返回 linter 类实例的工厂函数。示例:
¥In your build plugin sources, register a Linter Plugin: provide details such as a name, list of extensions and filenames the plugin will handle and a factory function that returns an instance of a linter class. Example:
js
Plugin.registerLinter({
extensions: ['js'],
filenames: ['.linterrc']
}, () => new MyLinter);
在此示例中,我们注册了一个在所有 js
文件上运行的 linter,还读取名为 .linterrc
的文件以获取配置。
¥In this example, we register a linter that runs on all js
files and also reads a file named .linterrc
to get a configuration.
MyLinter
类现在应该实现 processFilesForPackage
方法。该方法应接受两个参数:文件列表和选项对象。
¥The MyLinter
class should now implement the processFilesForPackage
method. The method should accept two arguments: a list of files and an options object.
js
class MyLinter {
processFilesForPackage(files, options) {
files.forEach((file) => {
// Lint the file.
const lint = lintFile(file.getContentsAsString());
if (lint) {
// If there are linting errors, output them.
const { message, line, column } = lint;
file.error({ message, line, column });
}
});
}
}
全局变量在选项对象中传递,以便 linters 可以忽略有关看起来像全局变量的包导入的警告。
¥The globals are passed in the options object so that the linters can omit the warnings about the package imports that look like global variables.
列表中的每个文件都是一个对象,它具有上述所有构建插件提供的所有方法。
¥Each file in the list is an object that has all the methods provided by all build plugins, described above.
查看 Core 中实现的 linting 插件的示例:jshint。
¥See an example of a linting plugin implemented in Core: jshint.
编译器
¥Compilers
编译器是获取源文件并输出 JavaScript 或 CSS 的程序。它们还可以输出添加到 <head>
标签和静态资源的 HTML 部分。编译器插件的示例如下:CoffeeScript、Babel.js、JSX 编译器、Pug 模板编译器等。
¥Compilers are programs that take the source files and output JavaScript or CSS. They also can output parts of HTML that is added to the <head>
tag and static assets. Examples for the compiler plugins are: CoffeeScript, Babel.js, JSX compilers, Pug templating compiler and others.
要在你的包中注册编译器插件,你需要在你的 package.js
文件中执行以下操作:
¥To register a compiler plugin in your package, you need to do the following in your package.js
file:
依赖于
isobuild:compiler-plugin@1.0.0
包¥depend on the
isobuild:compiler-plugin@1.0.0
package注册构建插件:
Package.registerBuildPlugin({ name, sources, ... });
(参见 docs)¥register a build plugin:
Package.registerBuildPlugin({ name, sources, ... });
(see docs)
在你的构建插件源中,注册一个 Compiler 插件:与其他类型的构建插件类似,提供详细信息、扩展名和文件名以及返回编译器实例的工厂函数。例如:
¥In your build plugin source, register a Compiler Plugin: similar to other types of build plugins, provide the details, extensions and filenames and a factory function that returns an instance of the compiler. Ex.:
js
Plugin.registerCompiler({
extensions: ['pug', 'tpl.pug'],
filenames: []
}, () => new PugCompiler);
编译器类必须实现 processFilesForTarget
方法,该方法为目标(包/应用的服务器或客户端部分)提供了源文件。
¥The compiler class must implement the processFilesForTarget
method that is given the source files for a target (server or client part of the package/app).
js
class PugCompiler {
processFilesForTarget(files) {
files.forEach((file) => {
// Process and add the output.
const output = compilePug(file.getContentsAsString());
file.addJavaScript({
data: output,
path: `${file.getPathInPackage()}.js`
});
});
}
}
除了输入文件类上可用的常用方法外,还有以下方法可用:
¥Besides the common methods available on the input files' class, the following methods are available:
getExtension
- 返回与编译器插件匹配的扩展。首选最长的前缀。¥
getExtension
- Returns the extension that matched the compiler plugin. The longest prefix is preferred.getDeclaredExports
- 返回在此目标中声明为导出的符号列表。目标的控制文件(如 package.js)中api.export('symbol')
调用的结果。¥
getDeclaredExports
- Returns a list of symbols declared as exports in this target. The result ofapi.export('symbol')
calls in target's control file such as package.js.getDisplayPath
返回可用于形成错误消息或其他显示属性的相对路径。可以用作源映射的输入。¥
getDisplayPath
Returns a relative path that can be used to form error messages or other display properties. Can be used as an input to a source map.addStylesheet
- 仅限 Web 目标。将样式表添加到文档。不适用于 linter 构建插件。¥
addStylesheet
- Web targets only. Add a stylesheet to the document. Not available for linter build plugins.addJavaScript
- 添加 JavaScript 代码。添加的代码将仅看到此包使用 'api.use' 作为运行时依赖导入的命名空间。如果正在编译的文件添加了 bare 标志,则生成的 JavaScript 将不会被封装在闭包中。¥
addJavaScript
- Add JavaScript code. The code added will only see the namespaces imported by this package as runtime dependencies using 'api.use'. If the file being compiled was added with the bare flag, the resulting JavaScript won't be wrapped in a closure.addAsset
- 根据目标,添加一个文件以按原样提供给浏览器或包含在浏览器中。在网络上,它将在请求的确切路径上提供服务。对于服务器目标,可以使用Assets.getTextAsync
或Assets.getBinaryAsync
进行检索。¥
addAsset
- Add a file to serve as-is to the browser or to include on the browser, depending on the target. On the web, it will be served at the exact path requested. For server targets, it can be retrieved usingAssets.getTextAsync
orAssets.getBinaryAsync
.addHtml
- 仅适用于 Web 目标。将标记添加到文档的head
或body
部分。¥
addHtml
- Works in web targets only. Add markup to thehead
orbody
section of the document.hmrAvailable
- 如果文件可以使用 HMR 更新,则返回 true。除其他事项外,它检查 HMR 是否支持当前架构和构建模式,以及 unibuild 是否使用hot-module-replacement
包。在极少数情况下,hmrAvailable
返回 true,但在构建过程的后期有更多信息可用时,Meteor 决定无法使用 HMR 更新文件。¥
hmrAvailable
- Returns true if the file can be updated with HMR. Among other things, it checks if HMR supports the current architecture and build mode, and that the unibuild uses thehot-module-replacement
package. There are rare situations wherehmrAvailable
returns true, but when more information is available later in the build process Meteor decides the file can not be updated with HMR.readAndWatchFileWithHash
- 接受绝对路径,并返回 { contents, hash } 确保 Meteor 监视文件,以便对它的任何更改都会触发重建¥
readAndWatchFileWithHash
- Accepts an absolute path, and returns { contents, hash } Makes sure Meteor watches the file so any changes to it will trigger a rebuild
Meteor 实现了几个编译器作为核心包,很好的例子是 Blaze 模板 包和 ecmascript 包(将 ES2015+ 编译为可以在浏览器中运行的 JavaScript)。
¥Meteor implements a couple of compilers as Core packages, good examples would be the Blaze templating package and the ecmascript package (compiles ES2015+ to JavaScript that can run in the browsers).
压缩器
¥Minifiers
Minifiers 在源代码编译并链接 JavaScript 代码后最后运行。Minifiers 仅针对客户端程序(web.browser
和 web.cordova
)运行。
¥Minifiers run last after the sources has been compiled and JavaScript code has been linked. Minifiers are only ran for the client programs (web.browser
and web.cordova
).
可以添加两种类型的压缩器:处理 JavaScript 的压缩器(注册扩展名:['js']
)和处理 CSS 的压缩器(扩展名:['css']
).
¥There are two types of minifiers one can add: a minifier processing JavaScript (registered extensions: ['js']
) and a minifier processing CSS (extensions: ['css']
).
要在你的包中注册 minifier 插件,请在你的 package.js
文件中添加以下内容:
¥To register a minifier plugin in your package, add the following in your package.js
file:
依赖于
isobuild:minifier-plugin@1.0.0
包¥depend on
isobuild:minifier-plugin@1.0.0
package注册构建插件:
Package.registerBuildPlugin({ name, sources, ... });
(参见 docs)¥register a build plugin:
Package.registerBuildPlugin({ name, sources, ... });
(see docs)
在你的构建插件源中,注册一个 Minifier 插件。与 Linter 和 Compiler 插件类似,指定感兴趣的扩展(css
或 js
)。工厂函数返回 minifier 类的实例。
¥In your build plugin source, register a Minifier Plugin. Similar to Linter and Compiler plugin, specify the interested extensions (css
or js
). The factory function returns an instance of the minifier class.
js
Plugin.registerMinifier({
extensions: ['js']
}, () => new UglifyJsMinifier);
minifier 类必须实现方法 processFilesForBundle
。第一个参数是已处理文件的列表,选项对象指定压缩器是在生产模式还是开发模式下运行。
¥The minifier class must implement the method processFilesForBundle
. The first argument is a list of processed files and the options object specifies if the minifier is ran in production mode or development mode.
信息
此方法可以是异步的。如果它返回一个 Promise,构建过程将等待它解析后再继续。
¥This method can be asynchronous. If it returns a Promise, the build process will wait for it to resolve before continuing.
js
class UglifyJsMinifier {
processFilesForBundle(files, options) {
const { minifyMode } = options;
if (minifyMode === 'development') {
// Don't minify in development.
file.forEach((file) => {
file.addJavaScript({
data: file.getContentsAsBuffer(),
sourceMap: file.getSourceMap(),
path: file.getPathInBundle()
});
});
return;
}
// Minify in production.
files.forEach((file) => {
file.addJavaScript({
data: uglifyjs.minify(file.getContentsAsBuffer()),
path: file.getPathInBundle()
});
});
}
}
在此示例中,我们在开发模式下重新添加相同的文件以避免不必要的工作,然后在生产模式下缩小文件。
¥In this example, we re-add the same files in the development mode to avoid unnecessary work and then we minify the files in production mode.
除了常见的输入文件方法外,还有以下方法可用:
¥Besides the common input files' methods, these methods are available:
getPathInBundle
- 返回包中已处理文件的路径。¥
getPathInBundle
- returns a path of the processed file in the bundle.getSourcePath
- 如果可用,则返回输入文件的绝对路径,否则返回 null。¥
getSourcePath
- returns absolute path of the input file if available, or null.getSourceMap
- 如果有,则返回已处理文件的源映射。¥
getSourceMap
- returns the source-map for the processed file if there is such.addJavaScript
- 与编译器相同¥
addJavaScript
- same as compilersaddStylesheet
- 与编译器相同¥
addStylesheet
- same as compilersreadAndWatchFileWithHash
- 仅适用于 css 压缩器。与编译器相同。¥
readAndWatchFileWithHash
- only available for css minifiers. Same as compilers.
目前,Meteor Core 附带 standard-minifiers
包,可以用自定义包替换。该包的 source 是如何构建自己的压缩插件的一个很好的例子。
¥Right now, Meteor Core ships with the standard-minifiers
package that can be replaced with a custom one. The source of the package is a good example how to build your own minification plugin.
在开发版本中,压缩器必须满足这些要求才能不阻止热模块替换:
¥In development builds, minifiers must meet these requirements to not prevent hot module replacement:
为每个文件调用一次
addJavasScript
以添加文件的内容¥Call
addJavasScript
once for each file to add the file's contents文件的内容不会被修改
¥The contents of the files are not modified
将来,Meteor 将允许 minifiers 在开发中连接或修改文件,而不会影响热模块替换。
¥In the future Meteor will allow minifiers to concatenate or modify files in development without affected hot module replacement.
缓存
¥Caching
由于 API 允许构建插件一次处理多个文件,因此我们鼓励包作者为其插件实现至少一些内存缓存。如果文件未重新处理,即使内容未更改,使用 getSourceHash
函数进行 linters 和编译器也将允许快速增量重新编译。
¥Since the API allows build plugins to process multiple files at once, we encourage package authors to implement at least some in-memory caching for their plugins. Using the getSourceHash
function for linters and compilers will allow quick incremental recompilations if the file is not reprocessed even when the contents didn't change.
对于 Isobuild 进程运行之间的快速重建,插件可以实现磁盘缓存。如果插件实现了 setDiskCacheDirectory
方法,它将不时被调用,并在磁盘上的新路径中写入插件可以写入其离线缓存。当插件重建或缓存因任何原因失效时(例如,所选的软件包版本集已更改),文件夹会正确重置。
¥For the fast rebuilds between the Isobuild process runs, plugins can implement on-disk caching. If a plugin implements the setDiskCacheDirectory
method, it will be called from time to time with a new path on disk where the plugin can write its offline cache. The folder is correctly reset when the plugin is rebuilt or cache should be invalidated for any reason (for example, picked package versions set has changed).
缓存编译器
¥Caching Compiler
有一个名为 caching-compiler
的核心包,它实现了保留内存和磁盘缓存的大部分通用逻辑。正确实现缓存的最简单方法是从构建插件中的此包中子类化 CachingCompiler
或 MultiFileCachingCompiler
类。CachingCompiler
适用于完全独立考虑每个文件的编译器;MultiFileCachingCompiler
适用于允许文件相互引用的编译器。要将此类放入你的插件命名空间,请向插件定义添加依赖:
¥There is a core package called caching-compiler
that implements most of the common logic of keeping both in-memory and on-disk caches. The easiest way to implement caching correctly is to subclass the CachingCompiler
or MultiFileCachingCompiler
class from this package in your build plugin. CachingCompiler
is for compilers that consider each file completely independently; MultiFileCachingCompiler
is for compilers that allow files to reference each other. To get this class in your plugin namespace, add a dependency to the plugin definition:
js
Package.registerBuildPlugin({
name: 'compileGG',
use: ['caching-compiler@1.0.0'],
sources: ['plugin/compile-gg.js']
});
访问文件系统
¥Accessing File System
由于构建插件作为 Meteor 工具的一部分运行,因此它们遵循相同的文件系统访问约定 - 所有文件系统路径始终看起来像 Unix 路径:使用正斜杠并在 '/' 处有一个根,即使在 Windows 上也是如此。例如:路径 /usr/bin/program
和 /C/Program Files/Program/program.exe
是有效路径,而 C:\Program Files\Program\program.exe
不是。
¥Since the build plugins run as part of the Meteor tool, they follow the same file-system access convention - all file system paths always look like a Unix path: using forward slashes and having a root at '/', even on Windows. For example: paths /usr/bin/program
and /C/Program Files/Program/program.exe
are valid paths, and C:\Program Files\Program\program.exe
is not.
因此,每当你通过 getPathInPackage
或在 setDiskCacheDirectory
方法的参数中获取构建插件实现中的路径时,该路径都将是 Unix 路径。
¥So whenever you get a path in your build plugin implementation, via getPathInPackage
or in an argument of the setDiskCacheDirectory
method, the path will be a Unix path.
现在,在 Windows 上运行时,通常的 Node 模块 fs
和 path
需要获得 DOS 路径。为了帮助你编写正确的代码,Plugin
符号提供了其自己的 fs
和 path
版本,你可以改用它们(请注意,fs
上的所有方法都是纤程化的,同步版本更喜欢使用 Fibers 而不是冻结整个事件循环)。
¥Now, on running on Windows, the usual node modules fs
and path
expect to get a DOS path. To assist you to write correct code, the Plugin
symbol provides its own versions of fs
and path
that you can use instead (note that all methods on fs
are fiberized and sync versions prefer using Fibers rather than freezing the whole event loop).
此外,Plugin
还提供了辅助函数 convertToStandardPath
和 convertToOSPath
,用于转换为 Unix 路径或 Node 库所需的路径,而不管路径来源如何。
¥Also Plugin
provides helper functions convertToStandardPath
and convertToOSPath
to convert to a Unix path or to the path expected by the node libraries regardless of the path origin.
示例:
¥Example:
js
// On Windows
const fs = Plugin.fs;
const path = Plugin.path;
const filePath = path.join('/C/Program Files', 'Program/file.txt');
console.log(filePath); // Prints '/C/Program Files/Program/file.txt'
fs.writeFileSync(filePath, 'Hello.'); // Writes to 'C:\Program Files\Program\file.txt'
console.log(Plugin.convertToOsPath(filePath)); // Prints 'C:\Program Files\Program\file.txt'
Isobuild 功能包
¥Isobuild Feature Packages
从 Meteor 1.2 开始,包可以声明它们需要一个 Meteor 工具版本,该版本的 Isobuild 构建系统支持某个功能。例如,包必须写入 api.use('isobuild:compiler-plugin@1.0.0')
才能调用 Plugin.registerCompiler
。这意味着包可以从旧的 registerSourceHandler
API 过渡到 registerCompiler
,并且 Version Solver 将正确阻止不知道如何处理它的旧工具选择 registerCompiler
版本。
¥Starting with Meteor 1.2, packages can declare that they need a version of the Meteor tool whose Isobuild build system supports a certain feature. For example, packages must write api.use('isobuild:compiler-plugin@1.0.0')
in order to call Plugin.registerCompiler
. This means that a package can transition from the old registerSourceHandler
API to registerCompiler
and Version Solver will properly prevent the registerCompiler
version from being chosen by older tools that don't know how to handle it.
这是已知的 Isobuild 功能 "packages",按支持它们的 Meteor 的第一个版本排序。
¥This is the known Isobuild feature "packages" sorted by the first release of Meteor which supports them.
在 Meteor 1.2s 中引入
¥Introduced in Meteor 1.2s
compiler-plugin@1.0.0
:允许使用Plugin.registerCompiler
。¥
compiler-plugin@1.0.0
: Allows use ofPlugin.registerCompiler
.linter-plugin@1.0.0
:允许使用Plugin.registerLinter
。¥
linter-plugin@1.0.0
: Allows use ofPlugin.registerLinter
.minifier-plugin@1.0.0
:允许使用Plugin.registerMinifier
。¥
minifier-plugin@1.0.0
: Allows use ofPlugin.registerMinifier
.isopack-2@1.0.0
:此软件包仅以isopack-2
格式发布,并且在 Meteor 不支持该格式的版本中不起作用。¥
isopack-2@1.0.0
: This package is published only inisopack-2
format and won't work in versions of Meteor that don't support that format.prod-only@1.0.0
:允许在Package.describe
中使用prodOnly
标志。¥
prod-only@1.0.0
: Allows use of theprodOnly
flag inPackage.describe
.isobuild:cordova@5.4.0
:此软件包依赖于 Cordova 的特定版本,很可能是因为它依赖 Cordova 插件。¥
isobuild:cordova@5.4.0
: This package depends on a specific version of Cordova, most likely as a result of the Cordova plugins it depends on.