打包器

打包器插件负责将捆绑包中的所有资产组合到一个输出文件中。它们还处理解析 URL 引用、捆绑包内联和生成源映射。

示例

#

此示例展示了一个将捆绑包中的所有资产连接在一起的打包器。Bundle 对象的 traverseAsset 方法以深度优先顺序遍历捆绑包中的所有资产。getCode 方法在每个 Asset 上调用以检索其内容。

import {Packager} from '@parcel/plugin';

export default new Packager({
async package({bundle}) {
let promises = [];
bundle.traverseAssets(asset => {
promises.push(asset.getCode());
});

let contents = await Promise.all(promises);
return {
contents: contents.join('\n')
};
}
});

加载配置

#

从用户项目加载配置应该在打包器插件的 loadConfig 方法中完成。有关如何执行此操作的详细信息,请参阅 加载配置

注意:使用 Parcel 的配置加载机制很重要,这样才能正确地使缓存失效。避免直接从文件系统加载文件。

源映射

#

源映射在浏览器中调试编译和捆绑的代码时帮助开发人员,通过将编译代码中的位置映射回原始源代码。除了将代码组合到最终捆绑包中,打包器还负责将每个资产的源映射组合到捆绑包的源映射中。

Parcel 使用 @parcel/source-map 库进行源映射操作。有关如何使用它的更多详细信息,请参阅 源映射

传递给打包器插件的 getSourceMapReference 函数可用于在捆绑包内容中插入指向源映射的 URL。Parcel 在适当的时候负责生成内联源映射(例如,遵循目标配置中的 sourceMap 选项)。

import {Packager} from '@parcel/plugin';
import SourceMap from '@parcel/source-map';
import {countLines} from '@parcel/utils';

export default new Packager({
async package({bundle, options, getSourceMapReference}) {
let promises = [];
bundle.traverseAssets(asset => {
promises.push(Promise.all([
asset.getCode(),
asset.getMap()
]));
});

let assets = await Promise.all(promises);
let contents = '';
let map = new SourceMap(options.projectRoot);
let lineOffset = 0;

for (let [code, map] of assets) {
contents += code + '\n';
map.addSourceMap(map, lineOffset);
lineOffset += countLines(code) + 1;
}

contents += `\n//# sourceMappingURL=${await getSourceMapReference(map)}\n`;
return {contents, map};
}
});

URL 引用

#

转换器插件可能会在编译后的代码中保留对依赖项 ID 的引用(请参阅转换器文档中的 URL 依赖项)。打包器应该将这些引用替换为生成的捆绑包的 URL。这可以使用 @parcel/utils 中的 replaceURLReferences 函数完成。

import {Packager} from '@parcel/plugin';
import {replaceURLReferences} from '@parcel/utils';

export default new Packager({
async package({bundle, bundleGraph}) {
// ...

({contents, map} = replaceURLReferences({
bundle,
bundleGraph,
contents,
map
}));

return {contents, map};
}
});

捆绑包内联

#

Parcel 支持将一个捆绑包的内容内联到另一个捆绑包中。例如,CSS 捆绑包的编译内容可以作为字符串内联到 JavaScript 捆绑包中。有关详细信息,请参阅 捆绑包内联

捆绑包内联是在打包器插件中实现的。getInlineBundleContents 函数传递给打包器,可以调用它来检索内联捆绑包的内容。

转换器插件可能会在编译后的代码中保留对依赖项 ID 的引用(请参阅转换器文档中的 URL 依赖项)。如果这些最终引用了内联捆绑包,则应将其替换为该捆绑包的内容。这可以使用 @parcel/utils 中的 replaceInlineReferences 函数完成。

import {Packager} from '@parcel/plugin';
import {replaceInlineReferences} from '@parcel/utils';

export default new Packager({
async package({bundle, bundleGraph, getInlineBundleContents}) {
// ...

({contents, map} = replaceInlineReferences({
bundle,
bundleGraph,
contents,
map,
getInlineBundleContents,
getInlineReplacement: (dependency, inlineType, contents) => ({
from: dependency.id,
to: contents
})
}));

return {contents, map};
}
});

相关 API

#

SymbolResolution parcel/packages/core/types/index.js:1231

指定资产中的符号

type SymbolResolution = {|
  +asset: Asset,

导出符号的 Asset

  +exportSymbol: Symbol | string,

导出符号的名称。

  +symbol: void | null | false | Symbol,

可以引用符号的标识符。

  +loc: ?SourceLocation,

导致此结果的说明符的位置。

|}
被引用
BundleGraphExportSymbolResolution

ExportSymbolResolution parcel/packages/core/types/index.js:1245

type ExportSymbolResolution = {|
  ...SymbolResolution,
  +exportAs: Symbol | string,
|}
被引用
BundleGraph

Packager parcel/packages/core/types/index.js:1649

type Packager<ConfigType, BundleConfigType> = {|
  loadConfig?: ({|
    config: Config,
    options: PluginOptions,
    logger: PluginLogger,
  |}) => Async<ConfigType>,
  loadBundleConfig?: ({|
    bundle: NamedBundle,
    bundleGraph: BundleGraph<NamedBundle>,
    config: Config,
    options: PluginOptions,
    logger: PluginLogger,
  |}) => Async<BundleConfigType>,
  package({|
    bundle: NamedBundle,
    bundleGraph: BundleGraph<NamedBundle>,
    options: PluginOptions,
    logger: PluginLogger,
    config: ConfigType,
    bundleConfig: BundleConfigType,
    getInlineBundleContents: (Bundle, BundleGraph<NamedBundle>) => Async<{|
      contents: Blob
    |}>,
    getSourceMapReference: (map: ?SourceMap) => Async<?string>,
  |}): Async<BundleResult>,
|}