插件

Parcel 可以在许多项目中开箱即用,无需任何配置。但是,如果您想要更多控制,或者需要扩展或覆盖 Parcel 的默认值,您可以在项目中创建一个 .parcelrc 文件。

Parcel 的设计非常模块化。Parcel 核心本身几乎不特定于构建 JavaScript 或网页 - 所有行为都是通过插件指定的。每个构建阶段都有特定的插件类型,因此您可以自定义几乎所有内容。

.parcelrc

#

Parcel 配置在 .parcelrc 文件中指定。它使用 JSON5 编写,它类似于 JSON,但支持注释、未引用的键、尾随逗号和其他功能。

扩展配置

#

Parcel 的默认配置在 @parcel/config-default 中指定。大多数情况下,您需要在自己的 Parcel 配置中扩展它。为此,请在您的 .parcelrc 中使用 extends 字段。

.parcelrc
{
"extends": "@parcel/config-default"
}

您还可以通过传递数组来扩展多个配置。配置按指定的顺序合并。

.parcelrc
{
"extends": ["@parcel/config-default", "@company/parcel-config"]
}

您也可以使用相对路径引用项目中的另一个配置。

.parcelrc
{
"extends": "../.parcelrc"
}

扩展的配置也可以扩展其他配置,形成一个配置链。

Glob 映射

#

.parcelrc 中的许多字段(如 transformerspackagers)使用对象作为 glob 到插件名称的映射。这使您可以通过文件扩展名、文件路径甚至特定文件名来配置 Parcel 的行为。Glob 相对于包含 .parcelrc 的目录进行匹配。

Glob 映射中字段的顺序定义了在将文件名与它们进行测试时的优先级。这使您可以为项目中的某些文件(例如特定目录中的文件)配置不同的行为。

.parcelrc
{
"transformers": {
"icons/*.svg": ["highest-priority"],
"*.svg": ["lowest-priority"]
}
}

这里,如果我们尝试为文件 icons/home.svg 查找转换器,我们将一直向下遍历 glob,直到找到匹配项,即 icons/*.svg。我们永远不会到达 *.svg

一旦检查了当前配置中的所有 glob,Parcel 就会回退到任何扩展配置中定义的 glob。

管道

#

.parcelrc 中的许多字段(如 transformersoptimizersreporters)接受一个按顺序运行的插件数组。这些被称为 **管道**。

如果您想定义一个优先级更高的管道来扩展优先级较低的管道而不是覆盖它,您可以使用特殊的 "..." 语法来实现。将它添加到管道中以将下一个优先级管道嵌入其中。您可以将其插入管道开头、结尾甚至中间,这使您可以完全控制管道扩展的方式。

.parcelrc
{
"transformers": {
"icons/*.svg": ["@company/parcel-transformer-svg-icons", "..."],
"*.svg": ["@parcel/transformer-svg"]
}
}

在上面的示例中,当处理 icons/home.svg 时,我们首先运行 @company/parcel-transformer-svg-icons,然后运行 @parcel/transformer-svg

这也适用于已扩展的配置。如果使用了 "..." 并且当前配置中没有定义优先级较低的管道,Parcel 将回退到扩展配置中定义的管道。

由于 @parcel/transformer-svg 包含在默认配置中,因此上面的示例可以改写为:

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"icons/*.svg": ["@company/parcel-transformer-svg-icons", "..."]
}
}

命名管道

#

除了基于 glob 的管道之外,Parcel 还支持 **命名管道**,它使您能够以多种方式导入同一个文件。命名管道在 .parcelrc 中定义,就像普通管道一样,但在 glob 的开头包含一个 URL 方案。

例如,默认情况下,导入图像通常会返回指向外部文件的 URL,但您可以使用默认 Parcel 配置中定义的 data-url: 命名管道将其内联为数据 URL。有关详细信息,请参阅 包内联

src/example.css
.logo {
background: url(data-url:./logo.png);
}

您也可以定义自己的命名管道。例如,您可以定义一个 arraybuffer: 命名管道,它允许您将文件导入为 ArrayBuffer* glob 在此示例中匹配任何文件,但您也可以使用更具体的 glob。"..." 语法用于允许 Parcel 按预期方式处理文件,然后运行 parcel-transformer-arraybuffer 插件将其转换为 ArrayBuffer。

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"arraybuffer:*": ["...", "parcel-transformer-arraybuffer"]
}
}
src/example.js
import buffer from 'arraybuffer:./file.png';

命名管道支持转换器和优化器管道。对于转换器,管道在引用资产的依赖项中指定。对于优化器,它从包的入口资产继承。

插件

#

Parcel 支持许多不同类型的插件,它们在构建过程中执行特定任务。插件在您的 .parcelrc 中使用其 NPM 包名称进行引用。

转换器

#

查找转换器插件

转换器 插件转换单个资产以编译它、发现依赖项或将其转换为不同的格式。它们使用 .parcelrc 中的 glob 映射 进行配置。多个转换器可以使用 管道 按顺序在同一个资产上运行,并且支持 命名管道 以允许在同一个项目中以多种不同方式编译同一个文件。"..." 语法可用于扩展文件的默认转换器。

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.svg": ["...", "@parcel/transformer-svg-react"]
}
}

编译资产时,其文件类型可能会发生变化。例如,编译 TypeScript 时,资产的类型从 tstsx 更改为 js。发生这种情况时,Parcel 会重新评估如何进一步处理资产,并将其通过 .js 文件的匹配管道运行。

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
}
}

一旦转换器更改了资产类型,使其不再与当前管道匹配,资产将被放入不同的管道。如果新资产类型没有匹配的管道,则转换将完成。当前管道中定义的后续转换器将不会运行。

解析器

#

查找解析器插件

解析器 插件负责将依赖项说明符转换为将由转换器处理的完整文件路径。有关此工作原理的详细信息,请参阅 依赖关系解析。解析器使用 .parcelrc 中的插件名称数组进行配置。解析过程将一直进行,直到其中一个插件返回结果。

"..." 语法可用于扩展默认解析器。这使您可以覆盖某些依赖项的解析,但对其他依赖项回退到默认值。通常,您需要在运行默认解析器之前添加自定义解析器。

.parcelrc
{
"extends": "@parcel/config-default",
"resolvers": ["@company/parcel-resolver", "..."]
}

如果省略了 "...",则您的解析器必须能够处理所有依赖项,否则解析将失败。

捆绑器(实验性)

#

查找捆绑器插件

捆绑器 插件负责将资产分组到包中。捆绑器可以通过在 .parcelrc 中指定插件名称来配置。

.parcelrc
{
"extends": "@parcel/config-default",
"bundler": "@company/parcel-bundler"
}

注意:捆绑器插件是实验性的,可能会发生变化,即使是在次要更新之间。

运行时(实验性)

#

查找运行时插件

运行时 插件允许您将资产注入包中。它们可以使用 .parcelrc 中的插件名称数组进行配置。此列表中的所有运行时插件都将在每个包上运行。"..." 语法可用于扩展默认运行时。

.parcelrc
{
"extends": "@parcel/config-default",
"runtimes": ["@company/parcel-runtime", "..."]
}

如果省略了 "...",则不会运行默认运行时。这可能会导致问题,因为许多 Parcel 功能依赖于默认运行时。

注意:运行时插件是实验性的,可能会发生变化,即使是在次要更新之间。

命名器

#

查找命名器插件

命名器 插件确定包的输出文件名。它们使用 .parcelrc 中的插件名称数组进行配置。命名过程将一直进行,直到其中一个命名器返回结果。

"..." 语法可用于扩展默认命名器。这使您可以覆盖某些包的命名,但对其他包回退到默认值。通常,您需要在运行默认命名器之前添加自定义命名器。

.parcelrc
{
"extends": "@parcel/config-default",
"namers": ["@company/parcel-namer", "..."]
}

如果省略了 "...",则您的命名器必须能够处理所有包的命名,否则构建将失败。

打包器

#

查找打包器插件

打包器 插件负责将包中的所有资产组合到一个输出文件中。它们使用 .parcelrc 中的 glob 映射 进行配置。Glob 与包的输出文件名进行匹配。可以配置单个打包器插件以每个包运行。

.parcelrc
{
"extends": "@parcel/config-default",
"packagers": {
"*.{jpg,png}": "@company/parcel-packager-image-sprite"
}
}

优化器

#

查找优化器插件

优化器 插件类似于转换器,但它们接受一个包而不是单个资产。它们使用 .parcelrc 中的 glob 映射 进行配置。多个优化器可以使用 管道 按顺序在同一个包上运行,并且支持 命名管道 以允许在同一个项目中以多种不同方式编译同一个包。"..." 语法可用于扩展包的默认优化器。

.parcelrc
{
"extends": "@parcel/config-default",
"optimizers": {
"*.js": ["@parcel/optimizer-esbuild"]
}
}

压缩器

#

查找压缩器插件

压缩器 插件在将最终捆绑包写入磁盘时使用,并且可能会以某种方式压缩或编码它(例如 Gzip)。它们使用 .parcelrc 中的 通配符映射 进行配置。多个压缩器可以使用 管道 在同一个捆绑包上运行。每个压缩器插件都会生成一个额外的文件,该文件将并行写入,例如 bundle.jsbundle.js.gzbundle.js.br"..." 语法可用于扩展捆绑包的默认压缩器。

.parcelrc
{
"extends": "@parcel/config-default",
"compressors": {
"*.{js,html,css}": [
"...",
"@parcel/compressor-gzip",
"@parcel/compressor-brotli"
]
}
}

报告器

#

查找报告器插件

报告器 插件在整个构建过程中接收来自 Parcel 的事件。例如,报告器可能会将状态信息写入标准输出,运行开发服务器,或在构建结束时生成捆绑包分析报告。报告器使用 .parcelrc 中的包名称数组进行配置。此列表中的所有报告器都会针对每个构建事件运行。"..." 语法可用于扩展默认报告器。

.parcelrc
{
"extends": "@parcel/config-default",
"reporters": ["...", "@parcel/reporter-bundle-analyzer"]
}

您不经常使用的报告器也可以在 CLI 上使用 --reporter 选项指定,或通过 API 使用 additionalReporters 选项指定。在 .parcelrc 中指定的报告器始终运行。

本地插件

#

大多数 Parcel 插件都是 NPM 包。这意味着它们具有一个 package.json,该文件声明了它们与之兼容的 Parcel 版本,以及它们可能具有的任何依赖项。它们还必须遵循命名系统以确保清晰度。

通常,Parcel 插件发布到 NPM 注册表,或发布到内部公司注册表(例如 Artifactory)。这鼓励插件在社区或公司内的项目之间共享,以避免重复。

但是,在开发插件时,直接在项目中运行它而无需先发布它可能很有用。有几种方法可以做到这一点。

相对文件路径

#

插件可以作为使用它们的 .parcelrc 配置文件的相对路径引用。这些可能是 CommonJS 或 ESM 模块,使用 .mjs.cjs 扩展名确定,或使用最近的 package.json 中的 "type": "module" 字段确定(Node 加载模块的方式相同)。

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.js": ["./my-local-plugin.mjs", "..."]
}
}

Yarn 和 NPM 工作区

#

使用本地插件的另一种方法是通过 Yarn 工作区NPM 工作区 使用单仓库设置。这允许您像依赖已发布的包一样依赖存储库中的其他包。为此,请设置如下项目结构

project
├── .parcelrc
├── package.json
└── packages
    ├── app
    │   └── package.json
    └── parcel-transformer-foo
        ├── package.json
        └── src
            └── FooTransformer.js

在您的根 package.json 中,使用 workspaces 字段引用您的包。

package.json
{
"name": "my-project",
"private": true,
"workspaces": ["packages/*"]
}

然后,在您的 .parcelrc 中,您可以像引用已发布的包一样引用 parcel-transformer-foo。每当您更新插件的代码时,Parcel 都会重建您的项目。

您也可以选择将您的应用程序保留在根目录中(例如,在 src 文件夹中),而不是在 packages/app 中。

link: 协议

#

Yarn 支持使用 link: 协议定义依赖项,以将本地目录引用为包。例如,您可以设置如下项目结构

project
├── .parcelrc
├── package.json
├── src
│   └── index.html
└── parcel-transformer-foo
    ├── package.json
    └── src
        └── FooTransformer.js

在您的根 package.json 中,您可以使用 link: 协议定义对 parcel-transformer-foo 包的依赖项。

package.json
{
"name": "my-project",
"dependencies": {
"parcel": "^2.0.0",
"parcel-transformer-foo": "link:./parcel-transformer-foo"
}
}

然后,在您的 .parcelrc 中,您可以像引用已发布的包一样引用 parcel-transformer-foo。每当您更新插件的代码时,Parcel 都会重建您的项目。