webpack进阶(五)

十七、资源模块

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

在 webpack 5 之前,通常使用:

  • raw-loader 将文件导入为字符串
  • url-loader 将文件作为 data URI 内联到 bundle 中
  • file-loader 将文件发送到输出目录

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 'javascript/auto' 来解决。

webpack.config.js

module.exports = {module: {rules: [{test: /\.(png|jpg|gif)$/i,use: [{loader: 'url-loader',options: {limit: 8192,}},],
+       type: 'javascript/auto'},]},
}

如需从 asset loader 中排除来自新 URL 处理的 asset,请添加 dependency: { not: ['url'] } 到 loader 配置中。

webpack.config.js

module.exports = {module: {rules: [{test: /\.(png|jpg|gif)$/i,
+       dependency: { not: ['url'] },use: [{loader: 'url-loader',options: {limit: 8192,},},],},],}
}

1、Resource 资源

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist')},
+ module: {
+   rules: [
+     {
+       test: /\.png/,
+       type: 'asset/resource'
+     }
+   ]
+ },
};

src/index.js

import mainImage from './images/main.png';img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'

所有 .png 文件都将被发送到输出目录,并且其路径将被注入到 bundle 中。

(1) 自定义输出文件名

默认情况下,asset/resource 模块以 [hash][ext][query] 文件名发送到输出目录。

可以通过在 webpack 配置中设置 output.assetModuleFilename 来修改此模板字符串:

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist'),
+   assetModuleFilename: 'images/[hash][ext][query]'},module: {rules: [{test: /\.png/,type: 'asset/resource'}]},
};

另一种自定义输出文件名的方式是,将某些资源发送到指定目录:

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist'),
+   assetModuleFilename: 'images/[hash][ext][query]'},module: {rules: [{test: /\.png/,type: 'asset/resource'
-     }
+     },
+     {
+       test: /\.html/,
+       type: 'asset/resource',
+       generator: {
+         filename: 'static/[hash][ext][query]'
+       }
+     }]},
};

使用此配置,所有 html 文件都将被发送到输出目录中的 static 目录中。

Rule.generator.filenameoutput.assetModuleFilename 相同,并且仅适用于 assetasset/resource 模块类型。

2、inline 资源(inlining asset)

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist'),
-   assetModuleFilename: 'images/[hash][ext][query]'},module: {rules: [{
-       test: /\.png/,
-       type: 'asset/resource'
+       test: /\.svg/,
+       type: 'asset/inline'
-     },
+     }
-     {
-       test: /\.html/,
-       type: 'asset/resource',
-       generator: {
-         filename: 'static/[hash][ext][query]'
-       }
-     }]}
};

src/index.js

- import mainImage from './images/main.png';
+ import metroMap from './images/metro.svg';- img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'
+ block.style.background = `url(${metroMap})`; // url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo=)

所有 .svg 文件都将作为 data URI 注入到 bundle 中。

(1) 自定义 data URI 生成器

webpack 输出的 data URI,默认是呈现为使用 Base64 算法编码的文件内容。

如果要使用自定义编码算法,则可以指定一个自定义函数来编码文件内容:

webpack.config.js

const path = require('path');
+ const svgToMiniDataURI = require('mini-svg-data-uri');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist')},module: {rules: [{test: /\.svg/,type: 'asset/inline',
+       generator: {
+         dataUrl: content => {
+           content = content.toString();
+           return svgToMiniDataURI(content);
+         }
+       }}]},
};

现在,所有 .svg 文件都将通过 mini-svg-data-uri 包进行编码。

3、source 资源(source asset)

webpack.config.js

const path = require('path');
- const svgToMiniDataURI = require('mini-svg-data-uri');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist')},module: {rules: [{
-       test: /\.svg/,
-       type: 'asset/inline',
-       generator: {
-         dataUrl: content => {
-           content = content.toString();
-           return svgToMiniDataURI(content);
-         }
-       }
+       test: /\.txt/,
+       type: 'asset/source',}]},
};

src/example.txt

Hello world

src/index.js

- import metroMap from './images/metro.svg';
+ import exampleText from './example.txt';- block.style.background = `url(${metroMap}); // url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo=)
+ block.textContent = exampleText; // 'Hello world'

所有 .txt 文件将原样注入到 bundle 中。

4、URL 资源

当使用 new URL('./path/to/asset', import.meta.url),webpack 也会创建资源模块。

src/index.js

const logo = new URL('./logo.svg', import.meta.url);

根据你配置中 target 的不同,webpack 会将上述代码编译成不同结果:

// target: web
new URL(__webpack_public_path__ + 'logo.svg',document.baseURI || self.location.href
);// target: webworker
new URL(__webpack_public_path__ + 'logo.svg', self.location);// target: node, node-webkit, nwjs, electron-main, electron-renderer, electron-preload, async-node
new URL(__webpack_public_path__ + 'logo.svg',require('url').pathToFileUrl(__filename)
);

5、通用资源类型

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist')},module: {rules: [{
+       test: /\.txt/,
+       type: 'asset',}]},
};

现在,webpack 将按照默认条件,自动地在 resourceinline 之间进行选择:小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。

可以通过在 webpack 配置的 module rule 层级中,设置 Rule.parser.dataUrlCondition.maxSize 选项来修改此条件:

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'main.js',path: path.resolve(__dirname, 'dist')},module: {rules: [{test: /\.txt/,type: 'asset',
+       parser: {
+         dataUrlCondition: {
+           maxSize: 4 * 1024 // 4kb
+         }
+       }}]},
};

还可以 指定一个函数 来决定是否 inline 模块。

6、变更内联 loader 的语法

在 asset 模块和 webpack 5 之前,可以使用内联语法与上述传统的 loader 结合使用。

现在建议去掉所有的 loader 的语法,使用资源查询条件来魔法内联语法的功能。

示例,将 raw-loader 替换为 asset/source 类型:

- import myModule from 'raw-loader!my-module';
+ import myModule from 'my-module?raw';

webpack 相关配置:

module: {rules: [// ...
+     {
+       resouceQuery: /raw/
+       type: 'asset/source'
+     }]},

如果你想把原始资源排除在其他 loader 的解析范围以外,请使用取反的符合:

module: {rules: [// ...
+     {
+       test: /\.m?js$/,
+       resourceQuery: /^(?!raw$).*/,
+     },{resouceQuery: /raw/type: 'asset/source'}]},

十八、entry 高级用法

1、每个入口使用多种文件类型

在不使用 import 样式文件的应用程序中(预单页应用程序或其他原因),使用一个值数组结构的 entry,并且在其中传入不同类型的文件,可以实现将 CSS 和 JavaScript(和其他)文件分离在不同的 bundle。

举个例子。我们有一个具有两种页面类型的 PHP 应用程序:home(首页) 和 account(帐户)。home 与应用程序其余部分(account 页面)具有不同的布局和不可共享的 JavaScript。我们想要从应用程序文件中输出 home 页面的 home.jshome.css,为 account 页面输出 account.jsaccount.css

home.js

console.log('home page type');

home.scss

// home page individual styles

account.js

console.log('account page type');

account.scss

// account page individual styles

我们将在 production(生产) 模式中使用 MiniCssExtractPlugin 作为 CSS 的一个最佳实践。

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = {mode: process.env.NODE_ENV,entry: {home: ['./home.js', './home.scss'],account: ['./account.js', './account.scss'],},output: {filename: '[name].js',},module: {rules: [{test: /\.scss$/,use: [// fallback to style-loader in developmentprocess.env.NODE_ENV !== 'production'? 'style-loader': MiniCssExtractPlugin.loader,'css-loader','sass-loader',],},],},plugins: [new MiniCssExtractPlugin({filename: '[name].css',}),],
};

由于我们未指定其他输出路径,因此使用以上配置运行 webpack 将输出到 ./dist./dist 目录下现在包含四个文件:

  • home.js
  • home.css
  • account.js
  • account.css

十九、TypeScript

TypeScript 是 JavaScript 的超集,为其增加了类型系统,可以编译为普通 JavaScript 代码。这篇指南里我们将会学习是如何将 webpack 和 TypeScript 进行集成。

1、基础配置

首先,执行以下命令安装 TypeScript compiler 和 loader:

npm install --save-dev typescript ts-loader

现在,我们将修改目录结构和配置文件:

project

  webpack-demo|- package.json
+ |- tsconfig.json|- webpack.config.js|- /dist|- bundle.js|- index.html|- /src|- index.js
+   |- index.ts|- /node_modules

tsconfig.json

这里我们设置一个基本的配置,来支持 JSX,并将 TypeScript 编译到 ES5……

{"compilerOptions": {"outDir": "./dist/","noImplicitAny": true,"module": "es6","target": "es5","jsx": "react","allowJs": true}
}

查看 TypeScript 官方文档 了解更多关于 tsconfig.json 的配置选项。

想要了解 webpack 配置的更多信息,请查看 配置 概念。

现在,配置 webpack 处理 TypeScript:

webpack.config.js

const path = require('path');module.exports = {entry: './src/index.ts',module: {rules: [{test: /\.tsx?$/,use: 'ts-loader',exclude: /node_modules/,},],},resolve: {extensions: ['.tsx', '.ts', '.js'],},output: {filename: 'bundle.js',path: path.resolve(__dirname, 'dist'),},
};

这会让 webpack 直接从 ./index.ts 进入,然后通过 ts-loader _加载_所有的 .ts.tsx 文件,并且在当前目录_输出_一个 bundle.js 文件。

现在让我们改变 lodash./index.ts 文件中的引入, 因为在 lodash 的定义中没有默认(default)的导出。

./index.ts

- import _ from 'lodash';
+ import * as _ from 'lodash';function component() {const element = document.createElement('div');element.innerHTML = _.join(['Hello', 'webpack'], ' ');return element;}document.body.appendChild(component());

Tip
如果想在 TypeScript 中保留如import _ from 'lodash';的语法被让它作为一种默认的导入方式,需要在文件 tsconfig.json 中设置 "allowSyntheticDefaultImports" : true"esModuleInterop" : true 。这个是与 TypeScript 相关的配置,在本文档中提及仅供参考。

2、Loader

ts-loader

在本指南中,我们使用 ts-loader,因为它能够很方便地启用额外的 webpack 功能,例如将其他 web 资源导入到项目中。

Warning
ts-loader使用tscTypeScript编译器,并取决于您的tsconfig.json配置。确保避免设置module为“ CommonJS”,否则webpack将无法摇晃您的代码。

请注意,如果您已经在使用babel-loader代码转译,则可以使用@babel/preset-typescriptBabel并让其处理JavaScript和TypeScript文件,而无需使用其他加载器。请记住,与相反ts-loader,底层@babel/plugin-transform-typescript插件不执行任何类型检查。

3、Source Maps

想要了解 source map 的更多信息,请查看 开发 指南。

想要启用 source map,我们必须配置 TypeScript,以将内联的 source map 输出到编译后的 JavaScript 文件中。必须在 TypeScript 配置中添加下面这行:

tsconfig.json

  {"compilerOptions": {"outDir": "./dist/",
+     "sourceMap": true,"noImplicitAny": true,"module": "commonjs","target": "es5","jsx": "react","allowJs": true}}

现在,我们需要告诉 webpack 提取这些 source map,并内联到最终的 bundle 中。

webpack.config.js

  const path = require('path');module.exports = {entry: './src/index.ts',
+   devtool: 'inline-source-map',module: {rules: [{test: /\.tsx?$/,use: 'ts-loader',exclude: /node_modules/,},],},resolve: {extensions: [ '.tsx', '.ts', '.js' ],},output: {filename: 'bundle.js',path: path.resolve(__dirname, 'dist'),},};

查看 devtool 文档以了解更多信息。

4、使用第三方类库

在从 npm 安装 third party library(第三方库) 时,一定要记得同时安装此 library 的类型声明文件(typing definition)。你可以从 TypeSearch 中找到并安装这些第三方库的类型声明文件。

举个例子,如果想安装 lodash 类型声明文件,我们可以运行下面的命令:

npm install --save-dev @types/lodash

想了解更多,可以查看 这篇文章。

5、导入其他资源

想要在 TypeScript 中使用非代码资源(non-code asset),我们需要告诉 TypeScript 推断导入资源的类型。在项目里创建一个 custom.d.ts 文件,这个文件用来表示项目中 TypeScript 的自定义类型声明。我们为 .svg 文件设置一个声明:

custom.d.ts

declare module '*.svg' {const content: any;export default content;
}

H这里,我们通过指定任何以 .svg 结尾的导入(import),将 SVG 声明(declare) 为一个新的模块(module),并将模块的 content 定义为 any。我们可以通过将类型定义为字符串,来更加显式地将它声明为一个 url。同样的概念适用于其他资源,包括 CSS, SCSS, JSON 等。

6、构建性能

Warning
这可能会降低构建性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/20196.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】redis缓存击穿,缓存雪崩,缓存穿透

一、什么是缓存? 缓存就是与数据交互中的缓冲区,它一般存储在内存中且读写效率高,提高响应时间提高并发性能,如果访问数据的话可以先访问缓存,避免数据查询直接操作数据库,造成后端压力过大。 但是可能会面…

统⼀数据返回格式快速⼊⻔

为什么会有统⼀数据返回? 其实统一数据返回是运用了AOP(对某一类事情的集中处理)的思维。 优点: 1.⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。 2.降低前端程序员和后端程序员的沟通成本,因为所有接⼝都…

第7章硬件测试-7.6 量产可靠性测试

7.6 量产可靠性测试 7.6.1 生产小批量测试7.6.2 装备测试7.6.3 器件一致性测试7.6.4 工艺规程和单板维修技术说明 产品量产阶段需要通过可靠性测试来保障产品的可靠性。 7.6.1 生产小批量测试 生产小批量测试是发货之前的批量压力测试,有两个目的:一是…

可编辑的 SALV 模型(克服 SALV 模型的限制)

我们都知道 ABAP Object 比传统的 ABAP 非常强大。在这里,我想分享我使用 ABAP 对象克服 SALV mdoel 限制的最佳实验之一。 起源 最初,我在 SCN 上发布了这篇文章 – ABAP 对象的强大功能:克服 SALV 模型的限制,它也受到了很多批…

通过shell脚本分析部署nginx网络服务(详细易懂)

通过shell脚本分析部署nginx网络服务 要求: 接收用户部署的服务名称判断服务是否安装 已安装;自定义网站配置路径为/www;并创建共享目录和网页文件;重启服务 没有安装;安装对应的软件包测试: 判断服务是否…

H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解

随着技术的不断进步和5G网络的推广,中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长,并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁,推动数字媒体产业的创新和发展。 EasyPla…

【 LVGL】用外部FLASH存储字库并显示

LVGL–用外部FLASH存储字库并显示 应用场景 由于使用的芯片内部FLASH空间有限,如果仅使用英文字库并用不了多少空间,但是项目需要支持中英文字库,中文字库添加2w字左右,10px大小就要1M多了,内部空间根本不够用&#…

含284个数据集,覆盖18项临床任务,上海AI Lab等发布多模态医疗基准GMAI-MMBench

「有这样一台智能医疗设备,患者只需躺在智能医疗设备上便可完成从扫描、诊断、治疗、修复的全过程,实现健康的重启」。这是 2013 年上映的科幻电影「极乐空间」中的一个情节。 电影《极乐空间》场景 如今,随着人工智能技术的飞速发展&#xf…

Java-04

目录 Redis如何实现延时队列 延时队列的组成 生产消息 消费消息 实现细节 Redis集群 Integer.compare(a[1], b[1]))与a[1] - b[1]) 设计模式​编辑 算法 Redis如何实现延时队列 使用 sortedset ,拿时间戳作为 score ,消息内容作为 key 调用 zad…

【C++】— 掌握STL vector 类:“Vector简介:动态数组的高效应用”

文章目录 1.vector的介绍和使用1.1vector的介绍1.2 vector的特点1.3vector的使用1.3.1vector的定义1.3.2vector iterator的使用1.3.3vector 的空间增长问题1.3.4 vector 的增删查改1.3.5vector 迭代器失效问题 1.vector的介绍和使用 1.1vector的介绍 vector是一个顺序容器&am…

CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow

简介: 1.伸缩盒模型简介 2.伸缩容器、伸缩项目 3-4.主轴方向 5.主轴换行方式 6.复合属性flex-flow 7.主轴的对齐方式

互联网数字化商品管理浪潮思考:从信息化到精准运营

目录 一、商品数字化转型面临的现状分析 (一)运营方向分析 (二)商品归类分析 二、商品数字化管理建设分析 三、基础建设——商品信息数字化 (一)商品信息质量数字化的目的 (二&#xff0…

STL关联式容器之RB-tree(红黑树)

AVL-tree之外,另一个颇具历史并被广泛运用的平衡二叉搜索树是RB-tree(红黑树)。所谓RB-tree,不仅是一颗二叉搜索树,而且必须满足一下规则: 1:每个节点不是红色就是黑色 2:根节点为…

电脑系统重装小白教程

​对于很多电脑用户来说,系统出现故障或者需要清理时,重装系统是一项不可避免的操作。但是,对于没有技术基础的小白用户而言,重装系统可能会显得复杂且困难。本文将为您提供一份简洁易懂的电脑系统重装教程,帮助您顺利…

使用Ollama和Open WebUI管理本地开源大模型

Open WebUI和Ollama介绍 Open WebUI 是一个功能丰富且用户友好的自托管 Web 用户界面(WebUI),它被设计用于与大型语言模型(LLMs)进行交互,特别是那些由 Ollama 或与 OpenAI API 兼容的服务所支持的模型。O…

Nmap识别MongoDB 6.0指纹

Nmap识别MongoDB 6.0指纹 朋友反馈一个问题,说使用Nmap扫描MongoDB服务时对于6.0以上的版本默认无法识别到服务版本信息。 如上图所示,对应的VERSION信息是空的,在提示信息中可以看到,官方推荐将指纹信息上传以帮助更新服务指纹&…

向量搜索工具之 Milvus vs. Elastic

在当今数据驱动的世界中,向量数据库因其在处理大规模非结构化数据方面的卓越能力而变得越来越重要。随着数据量的爆炸性增长,如何确保这些数据库在存储和检索数十亿数据点时仍能保持高性能,成为了一个关键挑战。 Milvus和Elasticsearch都是管…

Java中日志采集框架-JUL、Slf4j、Log4j、Logstash

1. 日志采集 日志采集是指在软件系统、网络设备、服务器或其他IT基础设施中自动收集日志文件和事件信息的过程。这些日志通常包含了时间戳、事件类型、源和目标信息、错误代码、用户操作记录等关键数据。日志采集的目的是为了监控系统运行状态、分析系统性能、审计用户行为、故…

每日学习记录003:(C++)unique_ptr和shared_ptr

每日学习记录003:(C)unique_ptr和shared_ptr 在C中,unique_ptr和shared_ptr都是智能指针,它们为动态内存管理提供了更安全、更方便的方式。 一、unique_ptr的特点 (一)独占所有权 unique_pt…

免费实用的图片加水印工具

高度自定义的图片加水印工具 因工作需要和朋友的需求,我基于canvas开发了这款图片加水印工具。 地址:https://potatotools.top/toolsEntrance/pic/ImageWatermark.vue.html 功能亮点 尺寸定制 ,轻松调整水印宽高,精准适配每张图…