捆绑包内联

Parcel 提供了多种将一个捆绑包的编译内容内联到另一个捆绑包中的方法。

将捆绑包作为文本内联

#

bundle-text: 方案可用于将捆绑包的内容作为纯文本内联。Parcel 将正常编译已解析的文件,包括捆绑所有依赖项,然后将结果作为字符串内联到父捆绑包中。

这可以用于多种场景。例如,您可以内联编译后的 CSS 捆绑包,并使用结果在运行时注入样式标签。这在需要控制样式标签插入位置的情况下可能很有用,例如插入到 Shadow DOM 根节点。

import cssText from "bundle-text:./test.css";

// 注入 <style> 标签
let style = document.createElement("style");
style.textContent = cssText;
shadowRoot.appendChild(style);

作为数据 URL 内联

#

data-url: 方案允许将捆绑包作为数据 URL 内联。已解析的文件将被编译(包括所有依赖项),并转换为数据 URL。如果文件是二进制格式,它将被 base64 编码,否则将作为 URI 编码。

一个可能有用的示例是在 CSS 文件中内联小图像。

.foo {
background: url(data-url:./background.png);
}

底层实现

#

bundle-text:data-url: 是使用命名管道在默认 Parcel 配置中实现的。@parcel/transformer-inline-string 转换器插件将编译后的资源标记为内联,这告诉 Parcel 不要将捆绑包写入磁盘,而是将其内联到父捆绑包中。为了实现数据 URL,使用 @parcel/optimizer-data-url 优化器插件将编译后的捆绑包转换为数据 URL。

在 Parcel 配置中,它看起来像下面这样。每个管道中的 "..." 告诉 Parcel 首先运行匹配文件的正常转换器,然后运行 @parcel/transformer-inline-string

@parcel/config-default:
{
"transformers": {
"bundle-text:*": ["...", "@parcel/transformer-inline-string"],
"data-url:*": ["...", "@parcel/transformer-inline-string"]
},
"optimizers": {
"data-url:*": ["...", "@parcel/optimizer-data-url"]
}
}

您可以创建自己的命名管道,以任何您想要的方式自定义内联,重用上述插件或创建自定义插件。有关更多详细信息,请参见 Parcel 配置

另一个可能有用的 Parcel 插件是 @parcel/transformer-inline。与 @parcel/transformer-inline-string 类似,它将资源标记为内联,但结果不会编码为字符串。这意味着如果内联的捆绑包包含代码,它将在父捆绑包中执行,而不是向用户返回字符串。如果您有一个需要在运行时解码捆绑包的自定义插件,这可能很有用。

例如,您可能想将文件内联为 ArrayBuffer,或某种其他自定义编码。这可以使用自定义优化器插件实现,该插件对捆绑包的输出进行后处理。

import { Optimizer } from "@parcel/plugin";
import { blobToBuffer } from "@parcel/utils";

export default new Optimizer({
async optimize({ contents }) {
let buffer = await blobToBuffer(contents);
return {
contents: `new Uint8Array(${JSON.stringify(Array.from(buffer))}).buffer`,
};
},
});

现在,您可以使用新插件定义一个命名管道,并将编译后的文件导入为数组缓冲区。

有关编写自定义插件的更多详细信息,请参见插件系统文档,有关命名管道的更多信息,请参见 Parcel 配置文档。

作为 Blob URL 内联

#

您可能希望将捆绑包的内容作为 Blob URL 内联,这可以传递给浏览器中的许多 Web API。可以使用 @parcel/optimizer-blob-url 插件结合 @parcel/transformer-inline 来实现这一点。默认情况下不包含这些的命名管道,因此您需要在 .parcelrc 中创建一个。

.parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"blob-url:*": ["...", "@parcel/transformer-inline"]
},
"optimizers": {
"blob-url:*": ["...", "@parcel/optimizer-blob-url"]
}
}

不经过转换直接内联

#

在 JavaScript 中,可以在不通过 Parcel 转换器的情况下内联文件的内容。这可以通过 Parcel 静态分析的 fs Node 模块完成。可以以多种不同的编码作为字符串内联,或作为 Buffer。有关更多详细信息,请参见 Node 模拟文档。

import fs from "fs";

const sourceCode = fs.readFileSync(__dirname + "/foo.js", "utf8");

在上面的示例中,sourceCode 变量将是 foo.js 的内容,不经过编译,即原始源代码而不是捆绑结果。

与其他工具集成

#

由于捆绑包内联是 Parcel 特定的功能,您需要配置 TypeScript 或 Flow 等其他工具以支持它。有关如何执行此操作的详细信息,请参见依赖解析文档中的配置其他工具部分。