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

聊一聊 webpack5性能优化有哪些?

介绍

此文章基于webpack5来阐述

webpack性能优化较多,可以对其进行分类

  1. 优化打包速度,开发或者构建时优化打包速度(比如exclude、catch等)
  2. 优化打包后的结果,上线时的优化(比如分包处理、减小包体积、CDN服务等)

大多数情况下,我们会更侧重于优化打包后的结果,这对于线上产品的影响更大。

优化构建速度

对于 优化构建速度 会从 定向查找减少执行构建的模块合理使用缓存并行构建以提升总体速度并行压缩提高构建效率几个方面入手。

定向查找

resolve.modules

webpackresolve.modules 配置用于指定 webpack 去哪些目录下寻找第三方模块。其默认值是 ['node_modules']webpack 在寻找的时候,会先去当前目录的 ./node_modules 下去查找,没有找到就会再去上一级目录 ../node_modules 中去找,直到找到为止。

所以如果我们项目的第三方依赖模块放置的位置没有变更的话,可以使用绝对路径减少查找的时间,配置如下:

module.export = {resolve: {// 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤// __dirname 表示当前工作目录,也就是项目根目录modules: [path.resolve(__dirname, 'node_modules')]}
}

resolve.extensions

extensions 是我们常用的一个配置,适用于指定在导入语句没有带文件后缀时,可以按照配置的列表,自动补上后缀。我们应该根据我们项目中文件的实际使用情况设置后缀列表,将使用频率高的放在前面、同时后缀列表也要尽可能的少,减少没有必要的匹配。同时,我们在源码中写导入语句的时候,尽量带上后缀,避免查找匹配浪费时间。

同时,我们在源码中写导入语句的时候,尽量带上后缀,避免查找过程。

module.export = {resolve: {extensions: ['.js', '.jsx', '.ts', '.tsx'],}
}

extensions的默认值是['.js', '.json', '.wasm'],所以不写文件后缀的话,它会依次匹配'.js', '.json', '.wasm',如果都没匹配上的话才会报错。

减少执行构建的模块

合理配置 loader 的 include、exclude

loader 对文件的转换是个耗时的操作,并且 loader 的配置会批量命中多个文件,所以需要根据自己的项目尽可能的精准命中哪些文件是需要被 loader 处理的。

webpack 提供了 test、include、exclude 三个配置项来命中 loader 。

比如,我们只想对根目录 src 下的 js 文件使用 babel-loader 进行处理可以这样设置:

const path = require('path');
module.exports = {//...module: {rules: [{test: /.jsx?$/,use: ['babel-loader'],include: [path.resolve(__dirname, 'src')]}]},
}

或者我们想排除node_modules目录下的js使用 babel-loader 进行处理可以这样设置:

const path = require('path');
module.exports = {//...module: {rules: [{test: /.jsx?$/,use: ['babel-loader'],exclude: /node_modules/, //排除 node_modules 目录}]},
}

合理使用缓存

在优化的方案中,缓存也是其中重要的一环。在构建过程中,可以通过使用缓存提升二次打包速度。

babel-loader 开启缓存

cacheDirectory 的默认值为 false。当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程。

module.exports = {module: {rules: [{test: /.jsx?$/,use: [{loader: 'babel-loader',options: {cacheDirectory: true,},}]}]}
}

cache-loader

没有缓存配置的loader该怎么使用缓存呢?那就得借助 cache-loader

其使用如下:

module.exports = {module: {rules: [{test: /.jsx?$/,use: ['cache-loader', //需要安装"babel-loader"],}]}
}

webpack5 配置 cache.type

webpack5新增的cache属性,可以开启磁盘缓存,默认将编译结果缓存在 node_modules/.cache/webpack目录下。

cache 会在开发 模式被设置成 type: 'memory' 而且在 生产 模式中被禁用。 cache: truecache: { type: 'memory' } 配置作用一致。 传入 false 会禁用缓存。

经过配置,再次构建可以看到.cache/webpack 下生成了缓存文件

当然缓存也是不能盲目使用,也是需要斟酌,因为保存和读取这些缓存文件也会有一些时间开销,所以建议只对性能开销较大的 loader 采用改缓存优化。

并行构建以提升总体速度

默认情况下,webpack 是单线程模型,一次只能处理一个任务,在文件过多时会导致构建速度变慢。所以在减少了需要执行构建的模块和降低了单个模块的构建速度之外,我们还可以并行构建,让 webpack 同时处理多个任务,发挥多核 CPU 的优势。

Thread-loader

Thread-loader ,会创建多个 worker 池进行并发执行构建任务,但是使用起来更为简单。只要将这个 loader 放置在其他 loader之前, 放置在这个 Thread-loader 之后的 loader 就会在一个单独的 worker 池(worker pool) 中运行。

其使用如下:

module.exports = {module: {rules: [{test: /.jsx?$/,use: [// 开启多进程打包。 {loader: 'thread-loader', // 需要安装options: {workers: 3 // 进程3个}},{loader: 'babel-loader',}]}]}
}

在 webpack 官网 中也有提示,每个 worker 都是一个单独的有 600ms 限制的 node.js 进程。同时跨进程的数据交换也会被限制。所以建议仅在耗时的 loader 上使用。

只有在代码量很多的时候开启多进程构建才会有明显的提升,如果项目很简单,代码量少可能会适得其反。所以使用前需要斟酌,不要为了优化而优化。

并行压缩提高构建效率

前面说了并行构建,下面来说说并行压缩。

TerserWebpackPlugin 开启 paralle

module.exports = {optimization: {minimizer: [new TerserPlugin({ parallel: true }), // 默认已经开启,其实无需设置],},
};

优化构建结果

对于 优化构建结果 我们可以从 压缩代码按需加载预加载Code SplittingTree ShakingGzip作用提升几个方面入手。

压缩代码

压缩 html

压缩 html 使用的还是 html-webpack-plugin 插件。该插件支持配置一个 minify 对象,用来配置压缩 html

module.export = {plugins: [new HtmlWebpackPlugin({// 动态生成 html 文件template: "./index.html",minify: {// 压缩HTMLremoveComments: true, // 移除HTML中的注释collapseWhitespace: true, // 删除空⽩符与换⾏符minifyCSS: true // 压缩内联css},})]
}

压缩 css

webpack5中推荐使用的是 css-minimizer-webpack-plugin。

首先我们在入口文件里面引入test.css文件

import "./test.css";

test.css文件内容如下

.box {background-color: red;
}.item {color: black;
}

配置方式:

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");optimization: {// 是否需要压缩minimize: true, // 需要开启// 配置压缩工具minimizer: [// 添加 css 压缩配置new CssMinimizerPlugin({}), // 需要安装],
},

重新构建,会单独生成了 main.css 文件,并对css进行了压缩。

压缩 js

目前的主流还是terser-webpack-plugin,在webpack5生产环境中(mode=production),已默认开启。

如果你不想使用terser-webpack-plugin插件的默认配置,想自定义,也是支持的,可以直接引入terser-webpack-plugin进行自定义配置即可。

const TerserPlugin = require("terser-webpack-plugin"); // webpack5内置,不需要再单独安装optimization: {// 是否需要压缩minimize: true,// 配置压缩工具minimizer: [new TerserPlugin({// 在这里自定义配置}),],
},

按需加载

很多时候不需要一次性加载所有的JS文件,而应该在不同阶段去加载所需要的代码。webpack内置了强大的分割代码的功能可以实现按需加载。

比如,我们在点击了某个按钮之后,才需要使用使用对应的JS文件中的代码,我们可以使用 import() 语法按需引入

// index.jsdocument.getElementById('btn1').onclick = function() {import('./impModule.js').then(fn => fn.default());
}

impModule.js

export default () => {console.log("我是懒加载模块");
};

我们打包之后,动态加载的模块会单独生成一个js文件。

在这里插入图片描述

页面首次加载的时候并不会加载该js文件,而是当我们需要使用到的时候才会进行加载。我们在页面上看看效果。

在默认情况下打包出来的文件名是路径的组合,比如上面的src_impModule.js,如果你不想使用这个名字,想通俗易懂可以在import里面配置 webpackChunkName魔法注释。

比如上面的例子,我们配置ebpackChunkName: "btnChunk"

// index.jsdocument.getElementById('btn1').onclick = function() {import(/* webpackChunkName: "btnChunk" */ './impModule.js').then(fn => fn.default());
}

再次构建可以看到,构建出来的文件名就是我们事先定义好的名称

在这里插入图片描述

预加载(prefetch 和 preload)

上面说的代码懒加载在使用的时候才去加载是会提升页面性能,但是如果懒加载的模块比较大,当点击的时候再去加载的话无疑会让用户等待时间加长。

可以利用浏览器空闲时候去加载这些切分出来的模块,那就是prefetch 和 preload

prefetch和preload的概念

prefetch(预取):将来可能需要一些模块资源,在核心代码加载完成之后浏览器空闲的时候再去加载需要用到的模块代码。

preload(预加载):当前核心代码加载期间可能需要模块资源,其是和核心代码文件一起去加载的。

prefetch

我们将上面的例子稍微改下,加个注释/* webpackPrefetch: true */

// index.jsdocument.getElementById("btn1").onclick = async () => {const imp = await import(/* webpackPrefetch: true */ "./impModule.js");imp.default();
};

上面的代码的意思是当我们主要的核心代码加载完成,浏览器有空闲的时候,浏览器就会帮我们自动的去下载impModule.js

head里面,懒加载模块会被直接引入了,并且会添加rel='prefetch'

在这里插入图片描述

preload

prefetch 与 preload 的区别

  1. preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
  2. preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
  3. preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
  4. 浏览器支持程度不同,需要注意。

Code Splitting (代码分割)

要理解webpack的提出的几个概念,module、chunk和bundle。

module:每个import引入的文件就是一个模块

chunk:当module源文件传到webpack进行打包时,webpack会根据文件引用关系生成chunk

bundle:是对chunk进行压缩、分割等处理后的产物

在这里插入图片描述

SplitChunksPlugin

可以阅读我的另外一篇文章,里面讲述了一些拆包策略 SplitChunksPlugin

MiniCssExtractPlugin

可以利用 mini-css-extract-plugin 插件,将我们的css代码分离出来。

接下来我们实操下。

创建样式文件

// index.less
.a {background-color: aqua;
}.b {font-size: 18px;
}

配置mini-css-extract-plugin插件

//webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");// ...
{test: /.less?$/,use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],exclude: /node_modules/, //排除 node_modules 目录
},plugins: [// ...new MiniCssExtractPlugin(),}),
],

css代码的分离优化原理其实和js是一样的。第一就是拆出来利用浏览器并发请求特性进行快速加载,其次就是多页面如果用到了相同样式能进行复用。

注意,此插件为每个包含 cssjs 文件创建一个单独的 css 文件

这句话的意思就是,css代码的分割不是以引入了多少个css文件构建后就有多少个css文件,而是根据你的js包来的,如果构建后你的js包只有一个那么css包也只会有一个,而不管你源代码里引入了多少个css文件。

Tree Shaking

利用 ES Module 静态分析的特点来检测模块内容的导出、导入以及被使用的情况,保留被使用的代码,消除不会被执行和没有副作用(Side Effect) 的 死代码。

Tree Shaking 最先出现在rollup中,rollup 是在编译打包过程中分析程序流,得益于 ES6 静态模块(exports 和 imports 不能在运行时修改),我们在打包时就可以确定哪些代码是我们需要的。

webpack 本身在打包时只能标记未使用的代码而不移除,而识别代码未使用标记并完成 tree-shaking 的 其实是 UglifyJS、terser 这类压缩代码的工具。简单来说,就是压缩工具读取 webpack 打包结果,在压缩之前移除 bundle 中未使用的代码

webpack 中的 sideEffects 表示是否要开启识别 package.json 中 sideEffects 标记的功能,而 package.json 中的 sideEffects 是为了告知打包工具该模块是否包含副作用或者包含哪些副作用。

Gzip

前端除了在打包的时候将无用的代码或者 console、注释剔除之外。还可以使用 Gzip 对资源进行进一步压缩。

  1. 当用户访问 web 站点的时候,会在 request header 中设置 accept-encoding: gzip,表明浏览器是否支持 Gzip
  2. 服务器在收到请求后,判断如果需要返回 Gzip 压缩后的文件那么服务器就会先将我们的 JS\CSS 等其他资源文件进行 Gzip 压缩后再传输到客户端,同时将 response headers 设置 content-encoding:gzip。反之,则返回源文件。
  3. 浏览器在接收到服务器返回的文件后,判断服务端返回的内容是否为压缩过的内容,是的话则进行解压操作。
const CompressionWebpackPlugin = require("compression-webpack-plugin"); // 需要安装module.exports = {plugins: [new CompressionWebpackPlugin()]
}

配置好我们再来构建,会生成资源的.gz文件

当然在Nginx上也可以在配置文件中启用 gzip 压缩

作用提升 (Scope Hoisting)

Scope Hoisting 作用域提升,在 JavaScript 中,也有类似的概念,“变量提升”、“函数提升”,JavaScript 会把函数和变量声明提升到当前作用域的顶部,Scope Hoisting 也是类似。webpack 会把引入的 js 文件“提升”顶部。

在没有使用 Scope Hoisting 的时候,webpack 的打包文件会将各个模块分开使用 __webpack_require__ 导入,在使用了 Scope Hoisting 之后,就会把需要导入的文件直接移入使用模块的顶部。这样做的好处有

  • 代码中函数声明和引用语句减少,减少代码体积
  • 不用多次使用 __webpack_require__ 调用模块,运行速度会的得以提升。

所以,Scope Hoisting 可以让 webpack 打包出来的代码文件体积更小,运行更快。

因为 Scope Hoisting 需要分析模块之间的依赖关系,所以源码必须采用 ES6 模块化语法。也就是说如果你使用非 ES6 模块或者使用 import() 动态导入的话,则不会有 Scope Hoisting

Scope Hoistingwebpack 内置功能,只需要在plugins里面使用即可

module.exports = {plugins: [// 开启 Scope Hoisting 功能new webpack.optimize.ModuleConcatenationPlugin()]
}

不过生产环境下 Scope Hoisting 功能是默认开启的,不用再额外处理。

常用分析工具

时间分析工具 speed-measure-webpack-plugin

speed-measure-webpack-plugin 这个插件分析整个打包的总耗时,以及每一个loader 和每一个 plugins 构建所耗费的时间,从而帮助我们快速定位到可以优化 Webpack 的配置。

在这里插入图片描述

使用如下

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); // 需要安装
const smp = new SpeedMeasurePlugin();module.exports = () => smp.wrap(config); // 使用smp包裹webpack的配置

构建结果分析工具 webpack-bundle-analyze

webpack-bundle-analyzer 能可视化的反映

  1. 打包出的文件中都包含了什么;
  2. 每个文件的尺寸在总体中的占比,哪些文件尺寸大;
  3. 模块之间的包含关系;
  4. 是否有重复的依赖项,是否存在一个库在多个文件中重复? 或者包中是否具有同一库的多个版本?
  5. 每个文件的压缩后的大小。

使用如下:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; // 需要安装module.exports = {plugins: [new BundleAnalyzerPlugin()]
}

相关文章:

聊一聊 webpack5性能优化有哪些?

介绍 此文章基于webpack5来阐述 webpack性能优化较多,可以对其进行分类 优化打包速度,开发或者构建时优化打包速度(比如exclude、catch等)优化打包后的结果,上线时的优化(比如分包处理、减小包体积、CDN…...

公布一批神马爬虫IP地址,真实采集数据

一、数据来源: 1、这批神马爬虫IP来源于尚贤达猎头公司网站采集数据; 2、数据采集时间段:2023年10月-2024年1月; 3、判断标准:主要根据用户代理是否包含“YisouSpider”,具体IP没做核实。 二、神马爬虫主…...

uni-app全局文件与常用API

文章目录 rpx响应式单位import导入css样式及scss变量用法与static目录import导入css样式uni.scss变量用法 pages.json页面路由globalStyle的属性pages设置页面路径及窗口表现tabBar设置底部菜单选项及iconfont图标 vite.config中安装插件unplugin-auto-import自动导入vue和unia…...

连接器表面缺陷检测方案

连接器是一种用于连接电子设备或电路中不同部件之间的组件,通常用于传输电力、信号或数据。连接器的设计和类型各不相同,以适应不同设备和应用的需求。连接器用于连接电子设备之间的电线、电缆或电路板,实现信号传输和电力供应。连接器设计应…...

React项目动态设置index.html中的<title>标签内容

1. 安装react-helmet-async npm install react-helmet-async -S2. 如下修改App.tsx即可 import { ConfigProvider } from "antd"; import { RouterProvider } from "react-router-dom"; import { router } from "//router"; import { Helmet, …...

大龄程序员转型攻略:拥抱人工智能,开启新征程

前言 随着科技的飞速发展,人工智能浪潮席卷全球,相关岗位炙手可热。在这个背景下,许多大龄程序员开始思考如何转型,以适应时代的变化。结合自身编程基础,大龄程序员可以学习机器学习、深度学习算法,投身于…...

Jenkins保姆笔记(1)——基于Java8的Jenkins安装部署

前言 记录分享下Jenkins的相关干货知识。分2-3篇来介绍Jenkins的安装部署以及使用。还是和以前一样,文章不介绍较多概念和细节,多介绍实践过程,以战代练,来供大家学习和理解Jenkins 概念 Jenkins是一个开源的自动化服务器&…...

学习c语言第18天(字符串和内存函数)

1.函数介绍 1.1 strlen size_t(就是无符号整形) strlen(const char * str); 字符串已经\0作为结束标志,strlen函数返回的是在字符串中\0前面出现的字符个数(不包 含\0) 参数指向的字符串必须要以\0结束。 注意函数的返回值为size_t,…...

无心剑七绝《潘展乐神》

七绝潘展乐神 潘江陆海忘情游 展志凌云筑玉楼 乐创全球新纪录 神姿英发舞金钩 2024年8月1日 平水韵十一尤平韵 潘展乐神,这四个字,如同四座矗立的丰碑,分别代表了潘展乐在游泳领域的卓越成就、豪情壮志、快乐创新和非凡风采。无心剑的这首…...

Linux C++ 开发1 - 搭建C++开发环境

1. 安装GCC/GDB 1.1. 安装1.2. 校验 2. 安装CMake 2.1. 安装2.2. 校验 3. 安装IDE 3.1. VSCode3.2. CLion 1. 安装GCC/GDB 1.1. 安装 # 更新软件源 sudo apt update # 通过以下命令安装编译器和调试器 sudo apt install build-essential gdb Ubuntu 默认情况下没有提供C/C…...

吴恩达老师机器学习-ex4

梯度检测没有实现。有借鉴网上的部分 导入相关库,读取数据 因为这次的数据是mat文件,需要使用scipy库中的loadmat进行读取数据。 通过对数据类型的分析,发现是字典类型,查看该字典的键,可以发现又X,y等关…...

C语言-函数例题

函数经典例题 1、编写一个函数实现该功能&#xff1a;从键盘输入一个字串符&#xff0c; 再输入两个正整数 m 和 n, 输出字符串中从 m 开始&#xff0c; 连续 n 个字符。例如&#xff0c; 输入 abcdefg,2,3,输出 bcd. #include <stdio.h> /*作者: zcy日期:功能描述:编写…...

鸿蒙应用框架开发【多HAP】程序框架

多HAP 介绍 本示例展示多HAP开发&#xff0c;简单介绍了多HAP的使用场景&#xff0c;应用包含了一个entry HAP和两个feature HAP&#xff0c;两个feature HAP分别提供了音频和视频播放组件&#xff0c;entry中使用了音频和视频播放组件。 三个模块需要安装三个hap包&#xff…...

PG如何实现跨大版本升级

数据库进行升级&#xff0c;是一个再正常不过的功能&#xff0c;比如功能的需要&#xff0c;遇到BUG&#xff0c;安全漏洞等等&#xff0c;具体升级包含子版本升级&#xff0c;主版本升级。如果用过ORACLE的朋友&#xff0c;一定知道&#xff0c;在ORACLE中&#xff0c;如果要实…...

JDK 8 升级 17 及 springboot 2.x 升级 3.x 指南

JDK 8 升级 17 简介 从 JDK 8 升级到 JDK 17 的过程中&#xff0c;有几个主要的变化&#xff0c;特别是 Java Platform Module System (JPMS) 的引入&#xff0c;以及一些包路径的调整。以下是与 JDK 17 相关的一些重要变化&#xff1a; Java Platform Module System (JPMS) …...

基于java的人居环境整治管理系统(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝20W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…...

深入了解Pip:Python包管理器的详细指南

目录 Pip简介Pip的安装与升级Pip的基本使用 安装包卸载包列出已安装的包查看包的信息 管理依赖 使用requirements.txt冻结当前环境的包 Pip进阶用法 安装特定版本的包使用代理安装包从本地文件安装包 创建和发布Python包 创建一个Python包编写setup.py文件发布到PyPI 常见问题…...

Corsearch 用 ClickHouse 替换 MySQL 进行内容和品牌保护

本文字数&#xff1a;3357&#xff1b;估计阅读时间&#xff1a;9 分钟 作者&#xff1a;ClickHouse Team 本文在公众号【ClickHouseInc】首发 Chase Richards 自 2011 年在初创公司 Marketly 担任工程负责人&#xff0c;直到 2020 年公司被收购。他现在是品牌保护公司 Corsear…...

常见的应急救援设备有哪些_鼎跃安全

在我们的生活中&#xff0c;应急事件的发生常常是突如其来的&#xff0c;它们对人民的生命财产安全构成重大威胁&#xff0c;同时也对社会稳定提出严峻挑战。在这样的紧急情况下&#xff0c;迅速开展有效的救援工作显得尤为重要。而在整个救援过程中&#xff0c;应急设备的使用…...

Vue 项目部署后首页白屏问题排查与解决

引言 在部署 Vue.js 项目时&#xff0c;有时会遇到首页加载后出现白屏的情况&#xff0c;这可能是由于多种原因造成的。本文将介绍一些常见的排查方法和解决方案&#xff0c;帮助开发者快速定位问题并解决。 1. 常见原因分析 首页白屏的问题可能由以下几个方面的原因导致&am…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...

EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势

一、WebRTC与智能硬件整合趋势​ 随着物联网和实时通信需求的爆发式增长&#xff0c;WebRTC作为开源实时通信技术&#xff0c;为浏览器与移动应用提供免插件的音视频通信能力&#xff0c;在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能&#xff0c;对实时…...