优化器

优化器插件类似于转换器,但它们接受一个打包而不是单个资源。优化器通常用于实现压缩、树摇/死代码消除以及需要完整打包才能有效的其他大小缩减技术。然而,优化器也可用于任何类型的打包转换,例如添加许可头、将内联打包转换为 base 64 等。

示例

#

optimize 方法接收打包的内容和其源映射,并应返回这些内容的转换版本。多个优化器插件可以串行运行,每个优化器的结果都传递给下一个。有关源映射的更多信息,请参见下文

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

export default new Optimizer({
async optimize({ contents, map }) {
let { code, sourceMap } = optimize(contents, map);
return {
contents: code,
map: sourceMap,
};
},
});

加载配置

#

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

note:使用 Parcel 的配置加载机制以便正确使缓存失效非常重要。避免直接从文件系统读取文件。

条件优化

#

即使在开发中或指定了 --no-optimize 选项时,Parcel 也始终运行 Optimizer 插件。这是因为优化器可用于任何类型的打包转换,而不仅仅是压缩。如果您的优化器插件正在执行压缩或通常应仅在生产构建中运行,则应检查打包环境的 shouldOptimize 属性,并在其为 false 时返回原始内容。

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

export default new Optimizer({
async optimize({contents, map, bundle}) {
// 如果 shouldOptimize 为 false,则不要压缩。
if (!bundle.env.shouldOptimize) {
return {contents, map};
}

let {code, sourceMap} = minify(contents, map);
return {
contents: code,
map: sourceMap
};
}
});

二进制内容

#

传递给优化器的输入内容可能是字符串、BufferReadableStream。通常,源代码将是字符串,二进制内容将是 Buffer 或流,但您不应假设如此。@parcel/utils 包包含一些帮助在它们之间转换的函数:blobToStringblobToBuffer。优化器可以返回这些表示中的任何一种。

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

export default new Optimizer({
async optimize({contents}) {
let buffer = await blobToBuffer(contents);
let optimized = optimize(buffer);
return {contents: optimized};
}
});

源映射

#

源映射帮助开发者在浏览器中调试编译和打包的代码,方法是将编译后的代码中的位置映射回原始源代码。优化器插件应转换提供的源映射,同时还要转换打包的内容。

Parcel 使用 @parcel/source-map 库进行源映射操作。有关如何使用它的更多详细信息,请参见源映射。您可能需要在传递给其他工具的源映射之间进行转换。

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

import { Optimizer } from "@parcel/plugin";
import SourceMap from "@parcel/source-map";

export default new Optimizer({
async optimize({ contents, map, getSourceMapReference }) {
// 将输入源映射转换为 JSON。
let result = optimize(contents, map.toVLQ());

// 将返回的 JSON 源映射转换为 Parcel SourceMap。
let sourceMap = new SourceMap(options.projectRoot);
sourceMap.addVLQMap(result.map);

// 将源映射引用添加到编译后的代码
let url = await getSourceMapReference(sourceMap);
result.code += `\n//# sourceMappingURL=${url}\n`;

return {
contents: result.code,
sourceMap,
};
},
});

相关 API

#

Optimizer parcel/packages/core/types/index.js:1680

type Optimizer<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>,
  optimize({|
    bundle: NamedBundle,
    bundleGraph: BundleGraph<NamedBundle>,
    contents: Blob,
    map: ?SourceMap,
    options: PluginOptions,
    logger: PluginLogger,
    config: ConfigType,
    bundleConfig: BundleConfigType,
    getSourceMapReference: (map: ?SourceMap) => Async<?string>,
  |}): Async<BundleResult>,
|}