目标

Parcel 可以同时以多种不同的方式编译您的源代码。这些被称为目标。例如,您可以有一个针对新浏览器的"现代"目标和一个针对旧浏览器的"传统"目标。

入口点

#

"入口点"是 Parcel 在构建源代码时开始的文件。它们可以在 CLI 上指定,或使用 package.json 中的 source 字段。

$ parcel <entries>

#

可以在任何 Parcel 命令中指定一个或多个入口文件。

$ parcel src/a.html src/b.html

入口点可以指定为 glob 以一次匹配多个文件。请确保将 glob 用单引号括起来,以确保 glob 不被您的 shell 解析,而是直接传递给 Parcel。这确保 Parcel 可以自动捕获匹配 glob 的新创建文件,而无需重新启动。

$ parcel './src/*.html'

入口点也可以是目录,在这种情况下,必须存在包含 source 字段的 package.json 文件。有关详细信息,请参见下文。

package.json#source

#

package.json 中的 source 字段可以指定一个或多个入口文件或 glob。

{
"source": "src/index.html"
}
{
"source": ["src/a.html", "src/b.html"]
}

package.json#targets.*.source

#

package.json 中任何声明的目标内的 source 字段可以指定特定于该目标的一个或多个入口文件。例如,您可以同时构建前端和后端,或桌面和移动应用。有关配置目标的详细信息,请参见下文。

{
"targets": {
"frontend": {
"source": "app/index.html"
},
"backend": {
"source": "api/index.js"
}
}
}

目标

#

Parcel 跟踪每个已解析入口点的依赖项,以为一个或多个目标构建您的源代码。目标指定输出目录或文件路径,以及关于如何编译代码的信息。

默认情况下,Parcel 包含一个隐式目标,输出到 dist 文件夹。这可以使用 --dist-dir CLI 选项覆盖。

$ parcel build src/index.html --dist-dir output

输出目录也可以在 package.json 中使用 targets 字段指定。这将覆盖 --dist-dir CLI 选项。

{
"targets": {
"default": {
"distDir": "./output"
}
}
}

环境

#

除了输出位置外,目标还指定了代码将运行的"环境"的信息。它们告诉 Parcel 要为哪种类型的环境构建(例如浏览器或 Node.js),以及支持每个引擎的版本。这会影响 Parcel 如何编译您的代码,包括要转译的语法。

package.json#browserslist

#

对于浏览器目标,package.json 中的 browserslist 字段可用于指定支持的浏览器。您可以按使用情况统计或特定浏览器的版本范围进行查询。有关更多信息,请参见 browserslist 文档

{
"browserslist": "> 0.5%, last 2 versions, not dead"
}

package.json#engines

#

对于 Node.js 和其他目标,package.json 中的 engines 字段可用于指定支持的版本。引擎使用语义化版本范围指定。

{
"engines": {
"node": ">= 12"
}
}

隐式环境

#

当一个文件依赖于另一个文件时,环境从其父文件继承。但是,依赖资源的方式可以改变环境的某些属性。例如,依赖服务工作线程时,环境会自动更改为服务工作线程上下文,以便适当地编译代码。

navigator.serviceWorker.register(new URL("service-worker.js", import.meta.url));

差异化打包

#

"差异化打包"是为不同目标提供代码的多个版本,并允许浏览器选择最优的版本下载的概念。当在 HTML 文件中使用 <script type="module"> 元素,且环境指定的某些浏览器不原生支持 ES 模块时,Parcel 将自动生成 <script nomodule> 回退。

<script type="module" src="app.js"></script>

编译为:

<script type="module" src="app.c9a6fe.js"></script>
<script nomodule src="app.f7d631.js"></script>

这允许支持 ES 模块的现代浏览器下载一个更小的捆绑包,同时仍然使用回退支持传统浏览器。通过避免转译类、箭头函数、async/await 等现代 JavaScript 语法,这可以显著减小捆绑包大小并改善加载时间。

这是基于您在 package.json 的 "browserslist" 字段中声明的浏览器目标自动发生的。如果未声明 browserslist,或所有浏览器目标都原生支持 ES 模块,则不会生成 nomodule 回退。

多个目标

#

您可能有多个目标,以同时为多个不同的环境构建源代码。例如,对于一个应用,您可以有"现代"和"传统"目标,或对于库,可以有 ES 模块和 CommonJS 目标(见下文)。

目标使用 package.json 中的 targets 字段配置。每个目标都有一个名称,在 targets 字段下指定为键,并有一个关联的配置对象。例如,每个目标中的 engines 字段可用于自定义其编译的环境。

{
"targets": {
"modern": {
"engines": {
"browsers": "Chrome 80"
}
},
"legacy": {
"engines": {
"browsers": "> 0.5%, last 2 versions, not dead"
}
}
}
}

指定多个目标时,默认情况下输出将写入 dist/${targetName}(例如上例中的 dist/moderndist/legacy)。这可以使用每个目标中的 distDir 字段自定义。另外,如果目标只有单个入口,则可以使用与目标名称对应的顶级 package.json 字段为输出指定确切的文件名。

{
"modern": "dist/modern.js",
"legacy": "dist/legacy.js",
"targets": {
"modern": {
"engines": {
"browsers": "Chrome 80"
}
},
"legacy": {
"engines": {
"browsers": "> 0.5%, last 2 versions, not dead"
}
}
}
}

库目标

#

Parcel 包含一些用于构建库的内置目标。这些包括 mainmodulebrowsertypes 字段。

{
"name": "my-library",
"version": "1.0.0",
"source": "src/index.js",
"main": "dist/main.js",
"module": "dist/module.js",
"types": "dist/types.d.ts"
}

库目标默认不捆绑 node_modules 中的依赖项。此外,默认情况下禁用压缩。这些可以使用 targets 字段中的适当选项覆盖(见下文)。库目标不能禁用作用域提升。

库目标根据目标自动输出原生 ES 模块或 CommonJS。

如果有可用的 browser 目标,或指定了 engines.node 且未指定浏览器目标,则 mainmodule 默认为 Node 环境编译。否则,默认为浏览器环境编译。这可以使用目标配置中的 context 选项覆盖(见下文)。

要让 Parcel 忽略这些字段之一,请在 targets 字段中指定 false

{
"main": "unrelated.js",
"targets": {
"main": false
}
}

请参阅使用 Parcel 构建库,了解使用 Parcel 构建库的入门指南。

目标选项

#

context

#
"node" |
"browser" |
"web-worker" |
"service-worker" |
"worklet" |
"electron-main" |
"electron-renderer";

context 属性定义要为哪种类型的环境构建。这告诉 Parcel 有哪些环境特定的 API 可用,例如 DOM、Node 文件系统 API 等。

对于内置库目标(例如 mainmodule),context 会自动推断。有关更多详细信息,请参见上面的库目标

engines

#

覆盖在顶级 package.json#enginesbrowserslist 字段中为此目标定义的引擎。目标中的 engines.browsers 字段可以像 browserslist 一样使用。有关更多信息,请参见上面的环境多个目标

outputFormat

#
"global" | "esmodule" | "commonjs";

定义要输出的模块类型。

对于内置库目标(例如 mainmodule),outputFormat 会自动推断。在目标的顶级 package.json 字段中定义的文件扩展名也可能影响输出格式。有关更多详细信息,请参见上面的库目标

scopeHoist

#

启用或禁用作用域提升。默认情况下,作用域提升在生产构建中启用。可以在运行 parcel build 时使用 --no-scope-hoist CLI 标志来禁用作用域提升。也可以通过在目标配置中设置 scopeHoist 选项来禁用作用域提升。

isLibrary

#

当设置为 true 时,目标被视为将发布到 npm 并由另一个工具使用,而不是直接在浏览器或其他目标环境中使用。当为 true 时,outputFormat 选项必须是 esmodulecommonjs,且 scopeHoist 不能设置为 false

对于内置库目标(例如 mainmodule),这会自动设置为 true。有关更多详细信息,请参见上面的库目标

optimize

#

启用或禁用优化(例如压缩)。具体行为由插件决定。默认情况下,优化在生产构建(parcel build)中启用,但库目标除外。可以使用 --no-optimize CLI 标志或目标配置中的 optimize 选项覆盖此设置。

includeNodeModules

#

确定是捆绑 node_modules 还是将其视为外部依赖。默认情况下,浏览器目标为 true,库目标为 false。可能的值包括:

sourceMap

#

启用或禁用源映射,并设置源映射选项。默认情况下,源映射是启用的。可以使用 --no-source-maps CLI 标志覆盖,或通过在目标配置中将 sourceMap 选项设置为 false

sourceMap 选项还接受一个具有以下选项的对象。

source

#

覆盖 package.json 中的顶级 source 字段,用于目标。这允许每个目标有不同的入口。有关更多详细信息,请参见 package.json#targets.*.source

distDir

#

设置将在此目标中编译的捆绑包的写入位置。默认情况下,如果只给出单个目标,则为 dist,对于多个目标,则为 dist/${targetName}。有关更多详细信息,请参见目标

publicUrl

#

设置在运行时加载此捆绑包的基本 URL。捆绑包从 distDir 的相对路径将自动附加。publicUrl 可以是完全限定的 URL(例如 https://some-cdn.com/)或绝对路径(例如 /public),如果捆绑包从与您的网站相同的域加载。

默认情况下,publicUrl/。如果您的 HTML 文件和其他资源部署到相同的位置,这是一个很好的默认值。如果您将资源部署到不同的位置,您可能需要设置 publicUrl。公共 URL 也可以使用 --public-url CLI 选项设置。

在大多数情况下,捆绑包是使用父捆绑包到子捆绑包的相对路径加载的。这允许部署移动到新位置而无需重新构建(例如,将暂存构建提升到生产)。当无法使用相对路径时(例如在 HTML 中),使用 publicUrl