构建系统
Meteor 构建系统是安装 Meteor 后获得的实际命令行工具。你可以通过在终端中键入 meteor
命令来运行它,后面可能跟着一组参数。阅读 关于命令行工具的文档 或在终端中键入 meteor help
以了解所有命令。
它做了什么?
Meteor 构建工具用于编译、运行、部署和发布所有 Meteor 应用和包。它是 Meteor 内置的解决方案,用于解决 Grunt、Gulp、Webpack、Browserify、Nodemon 等工具也解决的问题,并在内部使用许多流行的 Node.js 工具(如 Babel 和 UglifyJS)以提供无缝体验。
文件更改时重新加载应用
执行 meteor
命令启动构建工具后,你应该在进一步开发应用时保持其运行状态。构建工具使用文件监视系统自动检测任何相关的文件更改并重新编译必要的更改,根据需要重新启动客户端或服务器环境。热模块替换 可选,因此你可以更快地查看和测试你的更改。
使用构建插件编译文件
Meteor 构建工具的主要功能是运行“构建插件”。这些插件定义了应用构建过程的不同部分。Meteor 重点关注减少或移除构建配置文件,因此你不会看到像 Gulp 或 Webpack 中那样的大型构建过程配置文件。Meteor 构建过程几乎完全通过向应用添加和移除包以及将文件放入特殊命名的目录来配置。例如,要在你的应用中获得所有最新的稳定 ES2015 JavaScript 功能,你需要添加 ecmascript
包。此包提供对 ES2015 模块的支持,这使你可以使用 ES2015 的 import
和 export
对文件加载顺序进行更细粒度的控制。随着新的 Meteor 版本向此包添加新功能,你可以免费获得它们。
控制要构建的文件
默认情况下,Meteor 将根据你的应用 文件结构 和 Meteor 的 默认文件加载顺序 规则构建某些文件。但是,你可以使用 .meteorignore
文件覆盖默认行为,这些文件会导致构建系统忽略某些文件和目录,使用与 .gitignore
文件相同的模式语法。这些文件可能出现在应用或包的任何目录中,指定其下方目录树的规则。这些 .meteorignore
文件也与 Meteor 的文件监视系统完全集成,因此可以在开发过程中添加、移除或修改它们。
合并和压缩代码
Meteor 构建工具的另一个重要功能是它会自动连接你的应用资产文件,并在生产环境中压缩这些捆绑包。这使你可以向源代码中添加所有你想要的注释和空格,并将代码分成尽可能多的文件,而无需担心应用性能和加载时间。这是由 standard-minifier-js
和 standard-minifier-css
包启用的,这两个包默认包含在所有 Meteor 应用中。如果你需要不同的压缩行为,可以替换这些包(例如,请参阅 zodern:standard-minifier-js)。
开发环境与生产环境
在开发环境中运行应用的关键在于快速的迭代时间。应用的各种不同部分都以不同的方式处理和检测,以实现更好的重新加载和调试。在生产环境中,应用会减少到必要的代码和功能,就像任何标准的 Node.js 应用一样。因此,你不应该通过执行 meteor run
命令在生产环境中运行你的应用。相反,请按照 部署 Meteor 应用 中的说明进行操作。如果在生产环境中发现你怀疑与压缩相关的错误,可以使用 meteor --production
在本地运行应用的压缩版本进行测试。
JavaScript 转换
如今,JavaScript 工具和框架的格局不断变化,语言本身也在快速发展。等待 Web 浏览器实现你想要使用的语言功能已不再合理。大多数 JavaScript 开发工作流都依赖于编译代码以在最低限度的环境中工作,同时让你在开发中使用最新功能。Meteor 开箱即用地支持一些最流行的工具。
ES2015+(推荐)
ecmascript
包(默认安装到所有新的应用和包中,但可以移除)允许支持许多 ES2015 功能。我们建议使用它。你可以在 代码风格 文章中了解更多信息。
Babel
Babeljs 是一种可配置的转换器,它允许你使用最新版本的 JavaScript 编写代码,即使你支持的环境不支持某些功能。Babel 会将这些功能编译成支持的版本。
Meteor 为每个环境(Node 8、现代浏览器和传统浏览器)以及 React 提供了一组合适的核心插件,以支持大多数现代 Javascript 代码实践。此外,Meteor(从 1.3.3 版本开始)支持自定义的 .babelrc 文件,允许开发者进一步自定义他们的 Babel 配置以满足他们的需求(例如,Stage 0 提案)。
鼓励开发者避免添加大型预设(例如 babel-preset-env 和 babel-preset-react)以及根据需要添加特定插件(即使它看起来可以工作)。这样可以避免不必要的 Babel 编译,并且不太可能遇到插件排序问题。
CoffeeScript
虽然我们建议使用带有 ecmascript
包的 ES2015 作为 Meteor 最佳的开发体验,但平台中的所有内容都与 CoffeeScript 完全兼容,并且 Meteor 社区中的许多人都更喜欢它。
使用 CoffeeScript 只需要添加正确的 Meteor 包即可
meteor add coffeescript
所有用 CoffeeScript 编写的代码都在后台编译成 JavaScript,并且与其他包中用 JS 或 ES2015 编写的任何代码完全兼容。
TypeScript
TypeScript 是带有可选类型等的现代 JavaScript。
添加类型将使你的代码更具可读性,并减少运行时错误。
可以使用以下命令安装 TypeScript
meteor add typescript
需要使用 tsconfig.json
文件配置 TypeScript 编译器。以下是 meteor create --typescript
生成的文件
{
"compilerOptions": {
/* Basic Options */
"target": "es2018",
"module": "esNext",
"lib": ["esnext", "dom"],
"allowJs": true,
"checkJs": false,
"jsx": "preserve",
"incremental": true,
"noEmit": true,
/* Strict Type-Checking Options */
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
/* Additional Checks */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": false,
"noFallthroughCasesInSwitch": false,
/* Module Resolution Options */
"baseUrl": ".",
"paths": {
/* Support absolute /imports/* with a leading '/' */
"/*": ["*"]
},
"moduleResolution": "node",
"resolveJsonModule": true,
"types": ["node", "mocha"],
"esModuleInterop": true,
"preserveSymlinks": true
},
"exclude": [
"./.meteor/**",
"./packages/**"
]
}
如果想从项目创建开始添加 TypeScript,从 Meteor 1.8.2 开始,可以使用 –typescript 标志运行创建命令
meteor create --typescript name-of-my-new-typescript-app
条件导入
TypeScript 不支持嵌套的 import
语句,因此条件导入模块需要使用 require
语句(请参阅 使用 require
)。
为了保持类型安全,你可以利用 TypeScript 的导入省略并使用 typeof
关键字引用类型。有关详细信息,请参阅 TypeScript 手册文章 或 这篇博文 以获取具体的 Meteor 示例。
模板和 HTML
由于 Meteor 使用客户端渲染来呈现应用的 UI,因此所有 HTML 代码、UI 组件和模板都需要编译成 JavaScript。你可以使用一些选项来编写 UI 代码。
Blaze HTML 模板
每个新的 Meteor 应用默认都附带的恰如其分命名的 blaze-html-templates
包将使用 Spacebars 编写的 .html
文件编译成与 Blaze 兼容的 JavaScript 代码。你也可以将 blaze-html-templates
添加到任何包中以编译位于该包中的模板文件。
阅读 Blaze 文章以了解如何使用 Blaze 和 Spacebars。
Blaze Jade 模板
如果你不喜欢 Meteor 默认使用的 Spacebars 语法,并且想要更简洁的东西,可以尝试使用 pacreach:jade
。此包将编译应用中所有扩展名为 .jade
的文件,使其与 Blaze 兼容,并且可以与 blaze-html-templates
并排使用,如果你想让部分代码使用 Spacebars,部分代码使用 Jade。
React 的 JSX
如果你使用 React 构建应用的 UI,目前编写 UI 组件最流行的方式是使用 JSX,这是一种 JavaScript 扩展,允许你键入转换为 React DOM 元素的 HTML 标签。JSX 代码由 ecmascript
包自动处理。
React 的其他选项
如果你想使用 React 但不想处理 JSX 并且更喜欢类似 HTML 的语法,有一些社区选项可用。其中一个特别突出的选项是 Blaze-React,它使用 React 作为渲染引擎模拟整个 Blaze API。
CSS 处理
所有 CSS 样式文件都将使用 Meteor 的默认文件加载顺序规则以及任何导入语句进行处理,并连接到一个样式表 merged-stylesheets.css
中。在生产环境构建中,此文件也会被压缩。默认情况下,此单个样式表会注入到应用 HTML <head />
部分的开头。
但是,这对于使用第三方 UI 框架(例如从 CDN 加载的 Bootstrap)的一些应用来说可能是一个问题。这可能导致 Bootstrap 的 CSS 位于你的 CSS 之后,并覆盖你用户定义的样式。
为了解决这个问题,Meteor 支持使用一个伪标签<meteor-bundled-css />
,如果将其放置在应用程序的<head />
部分中的任何位置,则该标签将被替换为指向此连接的 CSS 文件的链接。如果未使用此伪标签,则 CSS 文件将像以前一样放置在部分的开头。
CSS 预处理器
众所周知,编写纯 CSS 常常很麻烦,因为没有办法在不同的选择器之间共享通用的 CSS 代码,或者在不同的元素之间保持一致的配色方案。CSS 编译器或预处理器通过在 CSS 语言之上添加额外的功能(如变量、mixin、数学运算等)来解决这些问题,在某些情况下,还会显著改变 CSS 的语法,使其更易于阅读和编写。
以下是 Meteor 支持的三个 CSS 预处理器示例
它们都有各自的优缺点,不同的人有不同的偏好,就像 JavaScript 编译语言一样。使用 SCSS 语法的 Sass 非常流行,因为像 Bootstrap 4 这样的 CSS 框架已经切换到 Sass,并且 C++ LibSass 实现似乎比其他一些可用的编译器更快。
选择预处理器时,CSS 框架兼容性应该是一个主要关注点,因为用 Less 编写的框架与用 Sass 编写的框架不兼容。
源文件与导入文件
所有可用的 CSS 预处理器都共享一个重要的功能,即能够导入文件。这使您可以将 CSS 分成更小的部分,并提供与 JavaScript 模块相同的许多好处。
- 您可以通过导入来编码依赖关系来控制文件的加载顺序,因为 CSS 的加载顺序很重要。
- 您可以创建可重用的 CSS“模块”,这些模块只包含变量和 mixin,并且不会实际生成任何 CSS。
在 Meteor 中,您的每个.scss
、.less
或.styl
源文件将属于以下两种类型之一:“源文件”或“导入文件”。
“源文件”会被急切地评估,并立即将其编译后的形式添加到应用程序的 CSS 中。
“导入文件”仅在从其他文件中导入时才会被评估,并且可用于在应用程序中的不同 CSS 文件之间共享通用的 mixin 和变量。
阅读下面列出的每个包的文档,了解如何指示哪些文件是源文件,哪些文件是导入文件。
导入样式
在所有三个 Meteor 支持的 CSS 预处理器中,您都可以从应用程序中的相对路径和绝对路径以及 npm 和 Meteor Atmosphere 包中导入其他样式文件。
@import '../stylesheets/colors.less'; // a relative path
@import '{}/imports/ui/stylesheets/button.less'; // absolute path with `{}` syntax
如果您安装了ecmascript
包,您还可以从 JavaScript 文件中导入 CSS。
import '../stylesheets/styles.css';
从 JavaScript 文件导入 CSS 时,该 CSS 不会与 Meteor 构建工具处理的其他 CSS 捆绑在一起,而是放在应用程序的
<head>
标签中的<style>...</style>
内,位于主要连接的 CSS 文件之后。
使用{}
包名称语法从 Atmosphere 包导入样式
@import '{my-package:pretty-buttons}/buttons/styles.import.less';
Atmosphere 包中的 CSS 文件是使用
api.addFiles
声明的,因此将被急切地评估,并自动与应用程序中的所有其他 CSS 捆绑在一起。
使用{}
语法从 npm 包导入样式
@import '{}/node_modules/npm-package-name/button.less';
import 'npm-package-name/stylesheets/styles.css';
有关导入样式和使用包中的@imports
的更多示例和详细信息,请参阅使用包文章。
Sass
Meteor 最好的 Sass 构建插件是fourseven:scss
。
Less
Less 作为名为less
的 Meteor 核心包维护。
Stylus
Meteor 最好的 Stylus 构建插件是coagmano:stylus
PostCSS 和 Autoprefixer
除了 Sass、Less 和 Stylus 等 CSS 预处理器之外,现在还有一个 CSS 后处理器的生态系统。无论您使用哪种 CSS 预处理器,后处理器都可以为您提供其他好处,例如跨浏览器兼容性。
目前最流行的 CSS 后处理器是PostCSS,它支持各种插件。Autoprefixer可能是最有用的插件,Autoprefixer 有一个在线版本,允许您输入未添加前缀的 CSS 并为您提供添加了前缀的 CSS,因为它使您可以停止担心浏览器前缀和兼容性,并编写符合标准的 CSS。您无需每次想要 CSS 渐变时都复制 5 个不同的语句 - 您可以编写一个没有任何前缀的标准渐变,Autoprefixer 会为您处理。
配置后,Meteor 会自动为您运行 PostCSS。在standard-minifier-css的文档中了解有关启用它的更多信息。
热模块替换
在 Meteor 应用程序中,javascript、typescript、css 文件以及动态导入的许多其他类型的文件在构建过程中会被转换为 javascript 模块。Meteor 能够更新已修改的运行应用程序中的 javascript 模块,而不是在重新构建后重新加载客户端。这通过允许您更快地查看和测试更改来减少开发过程中的反馈周期。
可以通过将hot-module-replacement包添加到您的应用程序中来启用热模块替换 (HMR)。
meteor add hot-module-replacement
许多类型的 javascript 模块无法使用 HMR 更新,因此必须配置 HMR 以了解哪些模块可以替换以及如何替换它们。大多数应用程序永远不需要手动执行此操作。相反,您可以使用为您配置 HMR 的集成。
- React 组件使用React Fast Refresh自动更新。此集成已为所有使用 HMR 和受支持的 React 版本的 Meteor 应用程序启用。
- Blaze 模板的集成处于测试阶段。
- 通过使用zodern:melte编译器包,可以自动使用 HMR 更新 Svelte 文件。
- akryum:vue-component使用其自己的 HMR 实现来更新 Vue 组件。
- 某些包能够帮助自动处理模块的旧版本。例如,zodern:pure-admin删除了模块旧版本中添加的菜单项和页面,因此当运行模块的新版本时,您不会遇到重复或过时的项。
要进一步控制 HMR 如何在您的应用程序中应用更新,您可以使用hot API。这可用于接受其他类型的文件的更新、帮助处理模块以便旧版本不再影响应用程序(例如停止 Tracker.autorun 计算)或创建您与其他视图层或库的集成。
如果对应用程序进行了无法使用 HMR 应用的更改,它将使用热代码推送重新加载页面,就像未启用 HMR 时一样。它目前仅支持现代客户端架构中的应用程序代码。Meteor 的未来版本将添加对包和其他架构的支持。
构建插件
Meteor 构建系统最强大的功能是能够定义自定义构建插件。如果您发现自己正在编写将一种类型的文件转换为另一种文件、合并多个文件或执行其他操作的脚本,则这些脚本很可能更适合作为构建插件来实现。ecmascript
、templating
和coffeescript
包都是作为构建插件实现的,因此如果您想替换它们,可以使用您自己的版本!
构建插件的类型
今天 Meteor 支持三种类型的构建插件。
- 编译器插件 - 将源文件(LESS、CoffeeScript)编译成构建输出(JS、CSS、资产文件和 HTML)。只有一个编译器插件可以处理单个文件扩展名。
- 压缩器插件 - 将大量构建的 CSS 或 JS 文件编译成一个或多个压缩文件,例如
standard-minifiers
。只有一个压缩器可以处理js
和css
中的每一个。 - Lint 插件 - 处理任意数量的文件,并可以打印 lint 错误。多个 Lint 插件可以处理相同的文件。
编写您自己的构建插件
编写构建插件是一项非常高级的任务,只有最先进的 Meteor 用户才能参与。最好的起点是复制与您尝试执行的操作最相似的其他插件。例如,如果您想制作一个新的 CSS 编译器插件,您可以复制less
包;如果您想制作自己的 JS 编译器,您可以复制ecmascript
。jshint
包是一个很好的 Lint 插件示例,对于压缩器,您可以查看standard-minifiers-js
和standard-minifiers-css
。
缓存
使构建插件快速运行的最佳方法是在任何可以缓存的地方使用缓存 - 节省时间的最佳方法是减少工作量!查看有关 CachingCompiler 的文档以了解更多信息。它在所有上述示例中都使用过,因此您可以通过查看它们来了解如何使用它。