优化器

优化器插件类似于转换器,但它们接受一个包而不是单个资源。优化器通常用于实现缩小、摇树/死代码消除和其他需要完整包才能有效的尺寸缩减技术。但是,优化器也可以用于任何类型的包转换,例如添加许可证头、将内联包转换为 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 方法中完成。有关如何执行此操作的详细信息,请参阅加载配置

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

条件优化

#

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

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

export default new Optimizer({
async optimize({contents, map, bundle}) {
// Don't minify if shouldOptimize is 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}) {
// Convert the input source map to JSON.
let result = optimize(contents, map.toVLQ());

// Convert returned JSON source map to a Parcel SourceMap.
let sourceMap = new SourceMap(options.projectRoot);
sourceMap.addVLQMap(result.map);

// Add source map reference to compiled code
let url = await getSourceMapReference(sourceMap);
result.code += `\n//# sourceMappingURL=${url}\n`

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

相关 API

#

优化器 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>,
|}