目标
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/modern
和 dist/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 包含一些用于构建库的内置目标。这些包括 main
、module
、browser
和 types
字段。
{
"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。
main
– 默认输出 CommonJS。如果使用.mjs
扩展名,或指定了"type": "module"
字段,则输出 ES 模块。module
– 输出 ES 模块。browser
–main
字段的浏览器特定覆盖。输出 CommonJS。
如果有可用的 browser
目标,或指定了 engines.node
且未指定浏览器目标,则 main
和 module
默认为 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 等。
对于内置库目标(例如 main
和 module
),context
会自动推断。有关更多详细信息,请参见上面的库目标。
engines
#覆盖在顶级 package.json#engines
和 browserslist
字段中为此目标定义的引擎。目标中的 engines.browsers
字段可以像 browserslist
一样使用。有关更多信息,请参见上面的环境和多个目标。
outputFormat
#"global" | "esmodule" | "commonjs";
定义要输出的模块类型。
global
– 一个经典脚本,可以在浏览器的<script>
标签中加载。不支持库目标。esmodule
– 使用import
和export
语句的 ES 模块。可以在浏览器的<script type="module">
标签中加载,或由 Node.js 或其他打包工具加载。commonjs
– 使用require
和module.exports
的 CommonJS 模块。可以由 Node.js 或其他打包工具加载。
对于内置库目标(例如 main
和 module
),outputFormat
会自动推断。在目标的顶级 package.json 字段中定义的文件扩展名也可能影响输出格式。有关更多详细信息,请参见上面的库目标。
scopeHoist
#启用或禁用作用域提升。默认情况下,作用域提升在生产构建中启用。可以在运行 parcel build
时使用 --no-scope-hoist
CLI 标志来禁用作用域提升。也可以通过在目标配置中设置 scopeHoist
选项来禁用作用域提升。
isLibrary
#当设置为 true
时,目标被视为将发布到 npm 并由另一个工具使用,而不是直接在浏览器或其他目标环境中使用。当为 true
时,outputFormat
选项必须是 esmodule
或 commonjs
,且 scopeHoist
不能设置为 false
。
对于内置库目标(例如 main
和 module
),这会自动设置为 true
。有关更多详细信息,请参见上面的库目标。
optimize
#启用或禁用优化(例如压缩)。具体行为由插件决定。默认情况下,优化在生产构建(parcel build
)中启用,但库目标除外。可以使用 --no-optimize
CLI 标志或目标配置中的 optimize
选项覆盖此设置。
includeNodeModules
#确定是捆绑 node_modules
还是将其视为外部依赖。默认情况下,浏览器目标为 true
,库目标为 false
。可能的值包括:
-
false
– 不包含node_modules
中的任何文件。 -
数组 – 要包含的包名列表。在下面的示例中,仅
react
被捆绑。所有其他node_modules
中的文件都被排除。{
"targets": {
"main": {
"includeNodeModules": ["react"]
}
}
} -
对象 – 包名到布尔值的映射。如果未列出包,则包含该包。在下面的示例中,除了 react 之外的所有
node_modules
都被捆绑。{
"targets": {
"main": {
"includeNodeModules": {
"react": false
}
}
}
}
sourceMap
#启用或禁用源映射,并设置源映射选项。默认情况下,源映射是启用的。可以使用 --no-source-maps
CLI 标志覆盖,或通过在目标配置中将 sourceMap
选项设置为 false
。
sourceMap
选项还接受一个具有以下选项的对象。
inline
– 是否将源映射作为数据 URL 内联到捆绑包中,而不是链接到单独的输出文件。inlineSources
– 是否将原始源代码内联到源映射中,而不是从sourceRoot
加载。在为生产构建浏览器目标时,默认设置为true
。sourceRoot
– 加载原始源代码的 URL。在使用内置 Parcel 开发服务器时,这在开发中自动设置。否则,默认为从项目根目录到捆绑包的相对路径。
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
。