ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Webpack 5 Asset 模块类型实战:零 Loader 处理静态资源,一文读懂 asset 的四种形态与底层实现

Webpack 5 Asset 模块类型实战:零 Loader 处理静态资源,一文读懂 asset 的四种形态与底层实现 Webpack 5 Asset 模块类型实战零 Loader 处理静态资源一文读懂 asset 的四种形态与底层实现【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through loaders, modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack本文基于 webpack 官方示例examples/asset展开完整讲解 webpack 5 内置的 asset module typeasset、asset/inline、asset/resource、asset/source、asset/bytes如何在不依赖任何 loader 的前提下导入图片、文本与二进制文件涵盖普通import、import ... with { type: text | bytes }导入属性以及new URL(./file, import.meta.url)三种开箱即用的写法并结合lib/asset/源码解析 8096 字节内联阈值、dataUrlCondition判断逻辑与产物哈希命名的底层机制读完即可在自己的项目中正确配置type: asset相关规则并理解其生成代码。示例定位为什么 asset 模块类型值得单独掌握在 webpack 5 之前处理图片、字体等静态资源必须引入file-loader输出为独立文件、url-loader小文件内联为 Data URL、raw-loader读取为字符串等多个第三方 loader规则冗长且彼此耦合。webpack 5 将这一能力内置为asset module type官方示例 examples/asset/template.md 对此的表述是This is a very simple example that shows the the usage of the asset module type. Files can be imported like other modules without file-loader.也就是说静态资源从此像普通模块一样参与打包流程由module.rules中的type字段决定其处理方式。当前仓库webpack 5.110.3见 package.json中examples/asset/目录完整给出了入口源码、构建配置与实际构建产物是研究该特性的最佳一手材料。三种开箱即用的资源导入方式示例入口 examples/asset/example.js 演示了 asset 模块的三种典型用法它们都不需要额外配置即可工作方式 1 需要 rules 声明type: asset// There are different ways to use files: // 1. Using import something from ./file.ext; // return URLs or Data URL, depends on your configuration import png from ./images/file.png; import jpg from ./images/file.jpg; import svg from ./images/file.svg; // 2. Using import something from ./file.ext; with { type: text } or import something from ./file.ext; with { type: bytes } // You dont need extra options in your configuration for these imports, they work out of the box // returns the content as text import text from ./content/file.text with { type: text }; // returns the content as Uint8Array import bytes from ./content/bytes.svg with { type: bytes }; // 3. Using new URL(./file.ext, import.meta.url); // You dont need extra options in your configuration for new URL(...) construction, they work out of the box const url new URL(./images/url.svg, import.meta.url);三种方式对应的行为分别是写法返回内容对应模块类型等价的历史 loaderimport png from ./images/file.pngURL 或 Data URL取决于配置与文件大小assetfile-loaderurl-loaderimport text from ./file.text with { type: text }文件内容字符串asset/sourceraw-loaderimport bytes from ./file.svg with { type: bytes }Uint8Arrayasset/bytes无直接对应二进制读取new URL(./file.svg, import.meta.url)资源 URLasset/resourcefile-loader其中with { type: ... }是 ECMAScript Import Attributes 语法webpack 在 lib/javascript/JavascriptParser.js 中解析import声明的with/assert属性对象将type值传递给模块工厂从而在不写任何 rules 的情况下把文件按 source/bytes 处理。而new URL(..., import.meta.url)则由 lib/dependencies/URLDependency.js 识别把 URL 构造表达式转成对资源模块的依赖。示例的后半部分只是把这几类导入结果渲染到页面createImageElement用img.src展示 URL/Data URLcreateTextElement直接输出文本createBlobElement则把Uint8Array包成Blob并用URL.createObjectURL生成对象 URL图片加载完成后URL.revokeObjectURL释放完整源码见 examples/asset/example.js。构建配置output.assetModuleFilename 与 module.rules 中的 type: asset示例的构建配置 examples/asset/webpack.config.js 极为精简只有两个关键点use strict; /** type {import(webpack).Configuration} */ const config { output: { assetModuleFilename: images/[hash][ext] }, module: { rules: [ { test: /file\.(png|jpg|svg)$/, type: asset } ] } }; module.exports config;output.assetModuleFilename: images/[hash][ext]指定asset/resource形态即需要落盘的资源的输出文件名模板。[hash]是资源内容哈希对应产物中的89a353e9c515885abd8e.png[ext]保留原始扩展名因此资源统一落在dist/images/目录下。该字段在类型声明中为assetModuleFilename?: AssetModuleFilenamedeclarations/WebpackOptions.d.ts。module.rules[0]仅用正则test: /file\.(png|jpg|svg)$/匹配示例图片并声明type: asset。注意这里没有设置parser与generator选项——这正是要点asset类型自带默认行为即按文件大小自动选择内联或落盘。type: asset的完整取值家族在 lib/ModuleTypeConstants.js 中有明确注释/** * type {Readonlyasset} * This is the module type used for automatically choosing between asset/inline, asset/resource based on asset size limit (8096). */ const ASSET_MODULE_TYPE asset; // asset/inline: 内联为 data URI等价于 url-loader // asset/resource: 拷贝到输出目录等价于 file-loader // asset/source: 以源码文本导入等价于 raw-loader // asset/bytes: 以 Uint8Array 导入即五种类型asset自动切换、asset/inline强制内联、asset/resource强制落盘、asset/source字符串、asset/bytesUint8Array。产物分析同一份配置下 png 落盘、jpg/svg 内联的真相构建产物 dist/output.js模板中引用为js/output.js清晰展示了type: asset的自动切换效果。对同一组规则命中的三个文件/* 1 */ module.exports __webpack_require__.p images/89a353e9c515885abd8e.png; // file.png14.6 KiB 8096 字节→ 独立文件 publicPath 拼接 /* 2 */ module.exports data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAA...4CD/9M//Z; // file.jpg → Data URL 内联 /* 3 */ module.exports data:image/svgxml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo; // file.svg → Data URL 内联file.png体积较大超过默认阈值因此被发射为images/89a353e9c515885abd8e.png模块导出值为__webpack_require__.ppublicPath此处为dist/与文件名的拼接file.jpg、file.svg未超阈值内容以 base64 Data URL 直接内联进 JS运行时零额外请求new URL(./images/url.svg, import.meta.url)产物是__webpack_require__(/* asset import */ 4)对应模块导出__webpack_require__.p images/afc10c70ed4ce2b33593.svg入口中被改写为new URL(资产URL, __webpack_require__.b)其中__webpack_require__.b是基准 URIdocument.baseURI || self.location.href保证了相对路径解析与浏览器行为一致with { type: bytes }导入的bytes.svg产物是__webpack_require__.tb(PHN2Zy...)运行时内置了一个to binaryhelper__webpack_require__.tb用 128 项查表法把 base64 字面量解码成Uint8Array并冻结底层ArrayBuffer使其不可变toImmutableBytes避免运行期意外改写共享二进制。webpack 的构建输出stats也印证了这一点asset output.js 19.5 KiB [emitted] (name: main) asset images/89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main) asset images/afc10c70ed4ce2b33593.svg 656 bytes [emitted] [immutable] [from: images/url.svg] (auxiliary name: main) chunk (runtime: main) output.js (main) 12.4 KiB (javascript) 15.2 KiB (asset) 1.53 KiB (runtime) [entry] [rendered] webpack X.X.X compiled successfully注意 png 只有file.png一个文件被真正发射jpg/svg 已内联资源被标记为[immutable]——因为文件名含内容哈希适合强缓存。源码纵深8096 字节阈值与 dataUrlCondition 的判定链自动切换行为的核心在 lib/asset/AssetModulesPlugin.js 与 lib/asset/AssetParser.js。插件注册AssetModulesPlugin.apply()通过normalModuleFactory.hooks.createModuleClass为五种 asset 类型统一挂上AssetModule类lib/asset/AssetModule.js它是NormalModule的子类仅附加 asset 专属的buildInfo形状并分别为各类型注册 parser/generator// lib/asset/AssetModulesPlugin.js let dataUrlCondition parserOptions.dataUrlCondition; if (!dataUrlCondition || typeof dataUrlCondition object) { dataUrlCondition { maxSize: 8096, ...dataUrlCondition }; } return new AssetParser(dataUrlCondition);这里就是关键默认值asset类型未显式配置parser.dataUrlCondition时maxSize默认为 8096 字节asset/inline直接构造new AssetParser(true)永远内联asset/resource构造new AssetParser(false)永远落盘。判定逻辑AssetParser.parse()对文件字节长度与阈值做比较lib/asset/AssetParser.jsif (typeof this.dataUrlCondition function) { buildInfo.dataUrl this.dataUrlCondition(source, { filename, module }); } else if (typeof this.dataUrlCondition boolean) { buildInfo.dataUrl this.dataUrlCondition; } else if (this.dataUrlCondition typeof this.dataUrlCondition object) { buildInfo.dataUrl Buffer.byteLength(source) this.dataUrlCondition.maxSize; }支持三种形态函数完全自定义可拿到源内容与模块上下文、布尔常量、{ maxSize }对象。buildInfo.dataUrl决定了生成阶段走 Data URL 分支还是走“发射文件 拼接 URL”分支生成器 lib/asset/AssetGenerator.js 负责按generator.filename/output.assetModuleFilename模板计算文件名并输出模块代码。此外generator.emit: falselib/asset/AssetModulesPlugin.js 中generatorOptions.emit ! false可以只生成 URL 而不落盘配合generator.dataUrl.encoding/mimetype可控制 Data URL 的编码与 MIME类型见 declarations/WebpackOptions.d.ts。发射阶段compilation.hooks.renderManifest中插件按 chunk 遍历ASSET_MODULE_TYPE源类型的模块把每个资源以auxiliary: true辅助产物推入渲染清单identifier形如assetModulemoduleId——这解释了 stats 中[from: images/file.png] (auxiliary name: main)的标注方式。小结从示例到生产的配置心智模型图片等二进制资源{ test: /\.(png|jpg|svg|...)$/, type: asset }让 webpack 按 8096 字节自动选择内联/落盘需要控制时用parser: { dataUrlCondition: { maxSize } }或函数覆盖阈值。强制策略asset/inline对应url-loaderasset/resource对应file-loaderasset/source对应raw-loaderasset/bytes产出Uint8Array。文本/二进制内容用with { type: text | bytes }导入属性无需任何 rulesnew URL(..., import.meta.url)则永远走 resource 语义。输出路径统一由output.assetModuleFilename模板控制[hash]提供内容级强缓存能力。完整可复现的演示位于 examples/asset 目录入口、配置、HTML 页面与生成产物俱全仓库内另有更细粒度的 Data URL 内联演示 examples/asset-svg-data-uri可作为延伸阅读。【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through loaders, modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表