当前位置: 首页 > news >正文

indexDB入门到精通

前言
由于开发3D可视化项目经常用到模型,而一个模型通常是几m甚至是几十m的大小对于一般的服务器来讲加载速度真的十分的慢,为了解决这个加载速度的问题,我想到了几个本地存储的。

首先是cookie,cookie肯定是不行的,因为最多以只能存4k,

其次localStorage,最多能存5m(不是一个key的大小,是所有key的总大小最多加起来最多5m),相对于cookie已经打了很多了。但是当遇到大模型还是不够,实际开发中大部分模型都是10m-30m的。

经过网上的相关资料的搜索了解到了indexDB,indexD就正好合适了,因为我发现我常用的3d框架three.js他们也是使用indexDB去做存储,而且存储大小是250m以上(受计算机硬件和浏览器厂商的限制)。

一、直接上代码更看结果更直观

懒人直接看入门的全部代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><title>Title</title><link href="./favicon.png">
</head>
<body>
</body>
<script>let dbName = 'helloIndexDB', version = 1, storeName = 'helloStore'let indexedDB = window.indexedDBlet dbconst request = indexedDB.open(dbName, version)request.onsuccess = function(event) {db = event.target.result // 数据库对象console.log('数据库打开成功')}request.onerror = function(event) {console.log('数据库打开报错')}request.onupgradeneeded = function(event) {// 数据库创建或升级的时候会触发console.log('onupgradeneeded')db = event.target.result // 数据库对象let objectStoreif (!db.objectStoreNames.contains(storeName)) {objectStore = db.createObjectStore(storeName, { keyPath: 'id' }) // 创建表// objectStore.createIndex('name', 'name', { unique: true }) // 创建索引 可以让你搜索任意字段}}// 添加数据function addData(db, storeName, data) {let request = db.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式("只读"或"读写").objectStore(storeName) // 仓库对象.add(data)request.onsuccess = function(event) {console.log('数据写入成功')}request.onerror = function(event) {console.log('数据写入失败')throw new Error(event.target.error)}}// 根据id获取数据function getDataByKey(db, storeName, key) {let transaction = db.transaction([storeName]) // 事务let objectStore = transaction.objectStore(storeName) // 仓库对象let request = objectStore.get(key)request.onerror = function(event) {console.log('事务失败')}request.onsuccess = function(event) {console.log('主键查询结果: ', request.result)}}// 根据id修改数function updateDB(db, storeName, data) {let request = db.transaction([storeName], 'readwrite') // 事务对象.objectStore(storeName) // 仓库对象.put(data)request.onsuccess = function() {console.log('数据更新成功')}request.onerror = function() {console.log('数据更新失败')}}// 根据id删除数据function deleteDB(db, storeName, id) {let request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(id)request.onsuccess = function() {console.log('数据删除成功')}request.onerror = function() {console.log('数据删除失败')}}// 由于打开indexDB是异步的加个定时器避免 db对象还没获取到值导致 报错setTimeout(() => {addData(db, storeName, {id: new Date().getTime(), // 必须且值唯一name: '张三',age: 18,desc: 'helloWord'})getDataByKey(db, storeName, 1638160036008)updateDB(db, storeName, {id: 1638164880484, desc: '修改的内容'})deleteDB(db, storeName, 1638164870439)}, 1000)</script>
</html>

第一步:准备环境和基本的html页面

 基本的html代码

​<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><title>Title</title>
</head>
<body>
</body>
<script></script>
</html>

第二步:打开数据库(如果没有自动创建)

  let dbName = 'helloIndexDB', version = 1, storeName = 'helloStore'let indexedDB = window.indexedDBlet dbconst request = indexedDB.open(dbName, version)request.onsuccess = function(event) {db = event.target.result // 数据库对象console.log('数据库打开成功')}request.onerror = function(event) {console.log('数据库打开报错')}request.onupgradeneeded = function(event) {// 数据库创建或升级的时候会触发console.log('onupgradeneeded')db = event.target.result // 数据库对象let objectStoreif (!db.objectStoreNames.contains(storeName)) {objectStore = db.createObjectStore(storeName, { keyPath: 'id' }) // 创建表// objectStore.createIndex('name', 'name', { unique: true }) // 创建索引 可以让你搜索任意字段}}

运行如上面的代码后打开控制台可以看到如下效果,数据库已经创建完成了,此时什么数据都没有

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5reL6Zuo5LiA55u06LWwfg==,size_19,color_FFFFFF,t_70,g_se,x_16

第三步:存入一个helloWorld 

  // 添加数据function addData(db, storeName, data) {let request = db.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式("只读"或"读写").objectStore(storeName) // 仓库对象.add(data)request.onsuccess = function(event) {console.log('数据写入成功')}request.onerror = function(event) {console.log('数据写入失败')throw new Error(event.target.error)}}// 由于打开indexDB是异步的加个定时器避免 db对象还没获取到值导致 报错setTimeout(() => {addData(db, storeName, {id: new Date().getTime(), // 必须且值唯一name: '张三',age: 18,desc: 'helloWord'})}, 1000)

刷新页面后可以看到如下结果,此时我这里已经存进去了,(我刷新了两次所以有两条数据)

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5reL6Zuo5LiA55u06LWwfg==,size_20,color_FFFFFF,t_70,g_se,x_16

 第四步:封装删除,查询,修改方法并分别执行查看结果

 // 根据id获取数据function getDataByKey(db, storeName, key) {let transaction = db.transaction([storeName]) // 事务let objectStore = transaction.objectStore(storeName) // 仓库对象let request = objectStore.get(key)request.onerror = function(event) {console.log('事务失败')}request.onsuccess = function(event) {console.log('主键查询结果: ', request.result)}}// 根据id修改数function updateDB(db, storeName, data) {let request = db.transaction([storeName], 'readwrite') // 事务对象.objectStore(storeName) // 仓库对象.put(data)request.onsuccess = function() {console.log('数据更新成功')}request.onerror = function() {console.log('数据更新失败')}}// 根据id删除数据function deleteDB(db, storeName, id) {let request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(id)request.onsuccess = function() {console.log('数据删除成功')}request.onerror = function() {console.log('数据删除失败')}}// 由于打开indexDB是异步的加个定时器避免 db对象还没获取到值导致 报错setTimeout(() => {// addData(db, storeName, {//   id: new Date().getTime(), // 必须且值唯一//   name: '张三',//   age: 18,//   desc: 'helloWord'// })getDataByKey(db, storeName, 1638160036008)updateDB(db, storeName, {id: 1638164880484, desc: '修改的内容'})deleteDB(db, storeName, 1638164870439)}, 1000)

执行上面的代码后结果后,我这边的结果如下,

watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5reL6Zuo5LiA55u06LWwfg==,size_20,color_FFFFFF,t_70,g_se,x_16

 二、封装indexDB库,

第一步:封装类库

/*** 封装的方法以及用法* 打开数据库*/
export function openDB(dbName, storeName, version = 1) {return new Promise((resolve, reject) => {let indexedDB = window.indexedDBlet dbconst request = indexedDB.open(dbName, version)request.onsuccess = function(event) {db = event.target.result // 数据库对象resolve(db)}request.onerror = function(event) {reject(event)}request.onupgradeneeded = function(event) {// 数据库创建或升级的时候会触发console.log('onupgradeneeded')db = event.target.result // 数据库对象let objectStoreif (!db.objectStoreNames.contains(storeName)) {objectStore = db.createObjectStore(storeName, { keyPath: 'id' }) // 创建表// objectStore.createIndex('name', 'name', { unique: true }) // 创建索引 可以让你搜索任意字段}}})
}/*** 新增数据*/
export function addData(db, storeName, data) {return new Promise((resolve, reject) => {let request = db.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式("只读"或"读写").objectStore(storeName) // 仓库对象.add(data)request.onsuccess = function(event) {resolve(event)}request.onerror = function(event) {throw new Error(event.target.error)reject(event)}})
}/*** 通过主键读取数据*/
export function getDataByKey(db, storeName, key) {return new Promise((resolve, reject) => {let transaction = db.transaction([storeName]) // 事务let objectStore = transaction.objectStore(storeName) // 仓库对象let request = objectStore.get(key)request.onerror = function(event) {reject(event)}request.onsuccess = function(event) {resolve(request.result)}})
}/*** 通过游标读取数据*/
export function cursorGetData(db, storeName) {let list = []let store = db.transaction(storeName, 'readwrite') // 事务.objectStore(storeName) // 仓库对象let request = store.openCursor() // 指针对象return new Promise((resolve, reject) => {request.onsuccess = function(e) {let cursor = e.target.resultif (cursor) {// 必须要检查list.push(cursor.value)cursor.continue() // 遍历了存储对象中的所有内容} else {resolve(list)}}request.onerror = function(e) {reject(e)}})
}/*** 通过索引读取数据*/
export function getDataByIndex(db, storeName, indexName, indexValue) {let store = db.transaction(storeName, 'readwrite').objectStore(storeName)let request = store.index(indexName).get(indexValue)return new Promise((resolve, reject) => {request.onerror = function(e) {reject(e)}request.onsuccess = function(e) {resolve(e.target.result)}})
}/*** 通过索引和游标查询记录*/
export function cursorGetDataByIndex(db, storeName, indexName, indexValue) {let list = []let store = db.transaction(storeName, 'readwrite').objectStore(storeName) // 仓库对象let request = store.index(indexName) // 索引对象.openCursor(IDBKeyRange.only(indexValue)) // 指针对象return new Promise((resolve, reject) => {request.onsuccess = function(e) {let cursor = e.target.resultif (cursor) {list.push(cursor.value)cursor.continue() // 遍历了存储对象中的所有内容} else {resolve(list)}}request.onerror = function(ev) {reject(ev)}})
}/*** 更新数据*/
export function updateDB(db, storeName, data) {let request = db.transaction([storeName], 'readwrite') // 事务对象.objectStore(storeName) // 仓库对象.put(data)return new Promise((resolve, reject) => {request.onsuccess = function(ev) {resolve(ev)}request.onerror = function(ev) {resolve(ev)}})
}/*** 删除数据*/
export function deleteDB(db, storeName, id) {let request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(id)return new Promise((resolve, reject) => {request.onsuccess = function(ev) {resolve(ev)}request.onerror = function(ev) {resolve(ev)}})
}/*** 删除数据库*/
export function deleteDBAll(dbName) {console.log(dbName)let deleteRequest = window.indexedDB.deleteDatabase(dbName)return new Promise((resolve, reject) => {deleteRequest.onerror = function(event) {console.log('删除失败')}deleteRequest.onsuccess = function(event) {console.log('删除成功')}})
}/*** 关闭数据库*/
export function closeDB(db) {db.close()console.log('数据库已关闭')
}export default {openDB,addData,getDataByKey,cursorGetData,getDataByIndex,cursorGetDataByIndex,updateDB,deleteDB,deleteDBAll,closeDB
}

第二步:使用类库,该库的使用方法如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><title>Title</title><link href="./favicon.png">
</head>
<body>
</body>注意要加 type="module"
<script type="module">
-->
<script type="module">import IndexDB from './IndexDB.js'(async function() {const dbName = 'myDB', storeName = 'db_1'const db = await IndexDB.openDB(dbName, storeName, 1)var data = await IndexDB.addData(db, storeName, {id: 111, // 必须且值唯一name: '张三',age: 18,desc: 'helloWord'})console.log(data)var data = await IndexDB.getDataByKey(db, storeName, 111)console.log(data)var data = await IndexDB.updateDB(db, storeName, { id: 111, desc: '修改的内容' })console.log(data)var data = await IndexDB.deleteDB(db, storeName, 111)console.log(data)})()
</script>
</html>

三、使用indexdb第三方类库indexdbwrapper(这种方式需要懂得使用打包工具开发不懂跳过)

/* 下载cnpm install --save indexdbwrapper
*/
// 引入
import IndexDBWrapper from 'indexdbwrapper'
// 使用
async function dbTest() {const dbName = 'dbName', storeName = 'storeName', version = 1const db = new IndexDBWrapper(dbName, version, {onupgradeneeded(event) {const db = event.target.result // 数据库对象let objectStoreif (!db.objectStoreNames.contains(storeName)) {objectStore = db.createObjectStore(storeName, { keyPath: 'id' }) // 创建表// objectStore.createIndex('createTime', 'createTime', { unique: false }) // 创建索引 可以让你搜索任意字段}}})await db.open()await db.add(storeName, { id: new Date().getTime(), updateTime: new Date().getTime() })console.log(await db.get(storeName, 1639015754840))console.log(await db.put(storeName, { id: 1639015754840, put: 'put2' }))console.log(await db.get(storeName, 1639015754840))console.log(await db.delete(storeName, 1639015754840))// console.log(await db.clear(storeName))
}
dbTest()

相关文章:

indexDB入门到精通

前言 由于开发3D可视化项目经常用到模型&#xff0c;而一个模型通常是几m甚至是几十m的大小对于一般的服务器来讲加载速度真的十分的慢&#xff0c;为了解决这个加载速度的问题&#xff0c;我想到了几个本地存储的。 首先是cookie,cookie肯定是不行的&#xff0c;因为最多以只…...

Ubuntu 20.04配置静态ip

ip配置文件 cd /etc/netplan配置 根据需求增加 # Let NetworkManager manage all devices on this system network:version: 2renderer: NetworkManager # 管理 不是必须ethernets:enp4s0: #网卡名dhcp4: no #关闭ipv4动态分配ip地址dhcp6: no #关闭ipv6动态分配…...

Tushare入门小册

Tushare入门小册 一、Tushare平台介绍 Pro版数据更稳定质量更好了&#xff0c;我们提供的不再是直接从互联网抓取&#xff0c;而是通过社区的采集和整理存入数据库经过质量控制后再提供给用户。但Pro依然是个开放的&#xff0c;免费的平台&#xff0c;不带任何商业性质和目的…...

<c++开发>通信工具 -之-SOME/IP移植部署 第一篇文章

&#xff1c;c开发&#xff1e;通信工具 -之-SOME/IP移植ubuntu部署 第一篇文章 一 前言 SOME/IP (Scalable service-Oriented MiddlewarE over IP) 是一种通信协议&#xff0c;主要用于嵌入式系统和车载网络中的服务导向通信。SOME/IP是AUTOSAR&#xff08;AUTomotive Open …...

权威的软件测试服务供应商分享,怎么获得软件安全检测报告?

我们深知在如今的数字化时代&#xff0c;软件安全对于企业和个人来说具有极其重要的意义。然而&#xff0c;许多用户对于软件安全测试报告的概念还不够清晰&#xff0c;也不知道如何获得这样的报告。在本文中&#xff0c;小编将为您简析什么是安全测试报告以及如何获取这样的报…...

管理类联考——逻辑——真题篇——按知识分类——汇总篇——二、论证逻辑——假设——第二节——搭桥假设

文章目录 第二节 假设-分类1-搭桥假设-当题干推理存在明显断点,常见形式比如:“因为A→B,C→D,所以A→D”,则正确选项为“B→C”真题(2014-39)-假设-分类1-题干推理存在明显断点-搭桥假设-建模搭桥-“因为A→B,所以A→C”,搭桥假设为“B→C”真题(2019-44)-假设-分…...

百度云BOS云存储的图片如何在访问时,同时进行格式转换、缩放等处理

前言 之前做了一个图片格式转换和压缩的服务&#xff0c;结果太占内存。后来查到在访问图片链接时&#xff0c;支持进行图片压缩和格式转换&#xff0c;本来想着先格式转换、压缩图片再上传到BOS&#xff0c;现在变成了上传后&#xff0c;访问时进行压缩和格式转换。想了想&am…...

go生成文件md5、sha1摘要简单示例

备注 go官方文档 https://pkg.go.dev/crypto/md5 已经给出如何使用该package生成文件或者字节数组的摘要值&#xff0c; 参照即可。 摘要值不是对文内容的加密&#xff0c;它主要用来进行checksum&#xff0c;就是验证两个文件内容是否一致&#xff0c;是否被篡改或者变化了。…...

Docker容器:docker数据管理、镜像的创建及dockerfile案例

文章目录 一、docker数据管理1.为何需要docker数据管理2.数据管理类型3.数据卷4.数据卷容器5.容器的互联 二.docker镜像的三种创建方法1.基于现有镜像创建1.1 启动镜像1.2 生成新镜像 2.基于本地模板创建2.1 OPENVZ 下载模板2.2 导入容器生成镜像 3.基于dockerfile创建3.1 dock…...

Ajax fetch Axios 的区别

AJAX&#xff1a;一种创建交互式网页应用的网页执行交互技术 通过在后台与服务器进行少量数据交换&#xff0c;Ajax可以使网页实现异步更新。意味着&#xff1a;在不重新加载整个网页 的情况下&#xff0c;对网页某部分进行更新。 缺点&#xff1a; 针对MVC编程&#xff0c;…...

数据库结构差异对比工具

简介 前几年写了一个数据库对比工具&#xff0c;但是由于实现方式的原因&#xff0c;数据库支持有限&#xff0c;所以重新设计了一下&#xff0c;便于支持多种数据库&#xff0c;并且更新了UI。 新版地址&#xff1a;https://gitee.com/xgpxg/db-diff 旧版地址&#xff1a;h…...

Shell编程学习之breakcontinuereturn的应用

Shell编程中的break关键字&#xff1a;break关键字&#xff1a;退出最近的循环&#xff0c;后续循环不再执行&#xff1b;break关键字用法&#xff1a; break #结束本层循环 break 数字n #结束n层循环测试代码1&#xff1a; #!/bin/bashfor((i1;i<6;i)) dofor((…...

有趣的数学 数学建模入门二 一些理论基础

一、什么是数学建模? 现实世界中混乱的问题可以用数学来解决&#xff0c;从而产生一系列可能的解决方案来帮助指导决策。大多数人对数学建模的概念感到不舒服&#xff0c;因为它是如此开放。如此多的未知信息似乎令人望而却步。哪些因素最相关&#xff1f;但正是现实世界问题的…...

Spring复习:(55)ApplicationContext中BeanFactoryPostProcessor是怎么添加到容器的?

容器创建时会调用AbstractApplicationContext的refresh方法&#xff0c;其中会调用invokeBeanFactoryPostProcessor方法&#xff0c;如下图 invokeBeanFactoryPostProcessors代码如下&#xff1a; 其中调用的PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcess…...

给wordpress添加关键词与描述

Wordpress网站的关键字及网页描述关系网站对搜索引擎的友好程度&#xff0c;如果自己手动加显然太折腾了&#xff0c;那如何让WordPress博客自动为每篇文章自动关键字及网页描述。每篇文章的内容不同&#xff0c;我们该如何让wordpress自动添加文章描述和关键词呢&#xff1f;下…...

Verilog 入门

Verilog 入门 本内容来自 牛客网Verilog入门特别版 1、一个没有输入和一个输出常数1的输出的电路&#xff0c;输出信号为one module top_module(one);output wire one;assign one 1b1; endmodule2、创建一个具有一个输入和一个输出的模块&#xff0c;其行为类似于电路上的连…...

shell 简单且常用的几种

目录 一、配置环境的shell脚本 二、系统资源脚本 一、要求 二、脚本内容 三、脚本解析 四、赋权并验证 三、查看当前内存的总大小、实际使用大小、剩余大小、显示使用率百分比的脚本 一、第一种方法 二、验证 三、第二种方法 四、验证 四、查看网卡实时流量脚本 一…...

redis基本介绍以及在node中使用

文章目录 引言一、什么是redis1. redis简介2. redis的特点3. redis的应用场景 二、redis在windows下安装1. 下载安装2.验证是否安装成功3. 配置环境变量 三、redis-cli常用命令介绍1. redis-cli2. keys *3. set key value4. get key5. exists key6. del key7. info8. flushdb9.…...

React Native 文本输入基础知识

在 React Native 中提供了一个文本输入组件TextInput。此组件主要是监听键盘输入事件&#xff0c;并把对应的输入值显示在组件中&#xff0c;此组件还提供了很多功能配置参数&#xff0c;例如自动更正、自动大写、占位符文本和不同的键盘类型&#xff08;例如数字键盘&#xff…...

qt显示图片并转换成灰度图及伪彩图

写了个程序&#xff0c;可在途图片&#xff0c;并切换成灰度图及伪彩图显示&#xff0c;主要代码如下&#xff1a; #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainW…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...