パッカー

パッカープラグインは、バンドル内のすべてのアセットを組み合わせて出力ファイルにする役割を担います。また、URL参照の解決、バンドルのインライン化、ソースマップの生成も処理します。

#

この例では、バンドル内のすべてのアセットを連結するパッカーを示しています。BundleオブジェクトのtraverseAssetメソッドは、バンドル内のすべてのアセットを深さ優先順で走査します。各AssetgetCodeメソッドが呼び出され、その内容が取得されます。

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/utilsreplaceURLReferences関数を使用して行うことができます。

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/utilsreplaceInlineReferences関数を使用して行うことができます。

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>,
|}