Webpack相关优化总结

在使用webpack时提供了各种配置,这里结合在业务中常用的配置汇总一下可以进行的一系列的webpack优化

缩小文件搜索范围

其原理是在构建时,会以用户配置的Entry为开始依次递归遍历每个Module,在遍历每个Module时会调用相应合适的Loader对原模块代码进行“翻译”。

优化Loader配置

Loader对文件的转换是比较耗时的,我们可以在loader中通过 test、include、exclude三个配置规则更加精确的命中目标文件,减少文件搜索的范围,举个例子,如果我们以ES6开发的文件为例子在配置Loader时可以这样

module.exports = {module: {rules: [{// 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能test: /\.js$/,// babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启use: [{loader: 'babel-loader',options: {cacheDirectory: path.resolve(__dirname, '.cache/babel')}}],// 只对项目根目录下的 src 目录中的文件采用 babel-loaderinclude: path.resolve(__dirname, 'src'),},]},
};

上面cacheDirectory可以将 babel 编译的结果缓存到文件系统,下次编译时,如果文件没有变化,直接使用缓存可以显著提升构建速度,一般可以在开发环境中使用,可以提高构建效率,在生产环境关闭,保障获得最新的构建结果

优化resolve.modules 配置

其默认值是[‘node_module’],含义是先去当前目录下的./node_module目录下找对应的模块,如果没有就去找上一级的./node_modules以此类推,这和Node.js的模块寻找很相似。如果当前安装的第三方目录都在当前项目的根目录下就没有必要一层层找,可以直接指明第三方模块的绝对路径,以减少寻找,配置如下:

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

优化resolveLoader

同理resolveLoader的机制也是一样,指定对应的Loader的安装位置

优化 resolve.mainFields 配置

resolve.mainFields 用于配置第三方模块使用哪个入口文件。在我们使用第三方模块的时候,在第三方模块中的package.json描述这个模块的属性,其中有一些字段用于描述这个模块的入口文件在哪里,而很多三方模块支持多环境的调用,比如axios或者isomorphic-fetch支持浏览器环境和node环境的调用,针对不同的环境就需要调用不同的代码,以 isomorphic-fetch 为例,它是 fetch API 的一个实现,但可同时用于浏览器和 Node.js 环境。 它的 package.json 中就有2个入口文件描述字段:

{"browser": "fetch-npm-browserify.js","main": "fetch-npm-node.js"
}

点我查看isomorphic-fetch配置文件

因为在不同的环境就需要掉不同的代码来执行。而resolve.mainFields 用于配置采用哪个字段作为入口文件的描述。所以我们为了减少搜索的步骤,当我们明确知道第三方模块的描述字段时,可以设置的尽量少,这样速度就会更快,一般而言三方模块都会采用main字段,所以可以这样配置

module.exports = {resolve: {// 只采用 main 字段作为入口文件描述字段,以减少搜索步骤mainFields: ['main'],},
};

优化resolve.extensions配置

在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在。 resolve.extensions 用于配置在尝试过程中用到的后缀列表,默认是:

extensions: ['.js', '.json']

举一个例子,比如在构建时遇到require(‘./dataList’)时webpack会先去寻找./dataList.js如果没有该文件就会去找./dataList.json文件。如果还是找不到,那就回报错。
如果这个列表越长,或者正确的后缀越靠后,那么寻找的次数就会越多,从而影响构建时的性能。在配置resolve.extensions 时需要遵守以下几点,以做到尽可能的优化构建性能:

  1. 后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中
  2. 频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程
  3. 在源码中写导入语句时,要尽可能的带上后缀

对应的配置如下:

module.exports = {resolve: {// 尽可能的减少后缀尝试的可能性extensions: ['tsx','ts', 'json'],},
};

优化 module.noParse 配置

该配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析处理,这样做的好处是能提高构建性能。 原因是一些库,例如 jQuery 、ChartJS, 它们庞大又没有采用模块化标准,让 Webpack 去解析这些文件耗时又没有意义。

const path = require('path');module.exports = {module: {noParse: [/echart/],},
};

使用DllPlugin

DllPlugin 是 Webpack 5 中的一个插件,用于优化构建速度,尤其是在大型项目中。它允许将一些常用的第三方库(如 React, Lodash 等)预构建成动态链接库(DLL),然后在实际的项目构建中进行引用,从而避免每次构建时都重新打包这些常用库,提高构建效率。

作用

  1. 提高构建速度:将一些不常改变的库单独打包成 DLL 文件,之后每次构建时只需要引用这个 DLL 文件,不需要重新构建这些依赖。
  2. 优化缓存:通过分离常用库和项目代码,Webpack 可以更好地利用缓存机制,避免不必要的重复构建。
  3. 代码拆分:DllPlugin 可以帮助更好地拆分代码,减少每次打包的负担。

如何使用

创建一个 DLL 配置文件

在项目根目录下创建一个新的 webpack.dll.js 配置文件,这个文件将用于专门打包第三方库。

// webpack.dll.js
const path = require('path');
const webpack = require('webpack');module.exports = {entry: {vendor: ['react', 'react-dom', 'lodash']  // 列出你想预构建的库},output: {path: path.resolve(__dirname, 'dist'),filename: '[name].dll.js',library: '[name]_library'  // 这会指定 DLL 文件的暴露全局变量名},plugins: [new webpack.DllPlugin({name: '[name]_library',path: path.resolve(__dirname, 'dist', '[name]-manifest.json')  // 指定 manifest 文件的路径})]
};

在上面的配置中:

entry 指定了要打包的库(vendor),你可以根据需求添加其他常用的第三方库。
output.library 定义了 DLL 文件暴露的全局变量,[name] 会被替换为 vendor。
DllPlugin 插件的 path 配置会生成一个 vendor-manifest.json 文件,Webpack 在主构建时会根据这个 manifest 文件引用 DLL 文件。

使用 DLL 文件

在主 webpack.config.js 文件中,通过 DllReferencePlugin 引用之前生成的 DLL 文件。

// webpack.config.js
const path = require('path');
const webpack = require('webpack');module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'bundle.js'},plugins: [// 引用 DllPlugin 生成的 DLL 文件new webpack.DllReferencePlugin({manifest: path.resolve(__dirname, 'dist', 'vendor-manifest.json')})]
};

这里 DllReferencePlugin 会确保你的主项目构建过程中引用 DLL 文件,而不需要重新构建这些库。

运行构建
  1. 执行 webpack --config webpack.dll.js 来构建 DLL 文件,这将会生成 vendor.dll.js 和 vendor-manifest.json。
  2. 执行主项目构建:webpack --config webpack.config.js,Webpack 会使用 DLL 文件来加速构建。

使用ParallelUglifyPlugin

当我们代码开发结束上线时,都会有代码压缩这里流程,最常见的代码压缩工具就是uglifyJS,webpack也已经内置了这个工具。当我们在上线时构建代码需要先将代码解析成AST语法树,在去应用各种规则分析和处理AST,这个过程计算量巨大,非常的耗费时间。我们可以使用ParallelUglifyPlugin 多线程并行的去做这些事,这样就能加快构建速度。ParallelUglifyPlugin 会开启多个子进程,把对多个文件的压缩工作分配给多个子进程完成,这样就能更快的完成压缩工作。
使用 ParallelUglifyPlugin 也非常简单,把原来 Webpack 配置文件中内置的 UglifyJsPlugin 去掉后,再替换成 ParallelUglifyPlugin,相关代码如下

const path = require('path');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');module.exports = {plugins: [// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码new ParallelUglifyPlugin({// 传递给 UglifyJS 的参数uglifyJS: {output: {// 最紧凑的输出beautify: false,// 删除所有的注释comments: false,},compress: {// 在UglifyJs删除没有用到的代码时不输出警告warnings: false,// 删除所有的 `console` 语句,可以兼容ie浏览器drop_console: true,// 内嵌定义了但是只用到一次的变量collapse_vars: true,// 提取出出现多次但是没有定义成变量去引用的静态值reduce_vars: true,}},}),],
};

压缩代码

压缩代码 浏览器从服务器访问网页时获取的 JavaScript、CSS 资源都是文本形式的,文件越大网页加载时间越长。 为了提升网页加速速度和减少网络传输流量,可以对这些资源进行压缩。 压缩的方法除了可以通过 GZIP 算法对文件压缩外,还可以对文本本身进行压缩

压缩ES6

虽然当前大多数 JavaScript 引擎还不完全支持 ES6 中的新特性,但在一些特定的运行环境下已经可以直接执行 ES6 代码了,例如最新版的 Chrome、ReactNative 的引擎 JavaScriptCore
运行 ES6 的代码相比于转换后的 ES5 代码有如下优点:

  • 一样的逻辑用 ES6 实现的代码量比 ES5 更少;
  • JavaScript 引擎对 ES6 中的语法做了性能优化,例如针对 const 申明的变量有更快的读取速度;

压缩ES6需要使用UglifyES而不是UglifyJS(压缩ES5)

压缩CSS

CSS 代码也可以像 JavaScript 那样被压缩,以达到提升加载速度和代码混淆的作用。 目前比较成熟可靠的 CSS 压缩工具是 cssnano,基于 PostCSS
cssnano 能理解 CSS 代码的含义,而不仅仅是删掉空格,例如:

  • margin: 10px 20px 10px 20px 被压缩成 margin: 10px 20px;
  • color: #ff0000 被压缩成 color:red

Tree shaking

Tree shaking 可以用来剔除js中没有使用到的代码,他依赖ES6的模块化语法,比如通过import和export导出,最早Tree shaking是在Rollup中出现,后来在webpack2.0中引入。
举个例子,比如我们有一个util.js的文件,里面有两个函数

export function funcA() {}export function funcB() {}

在我们的index.js文件中会导入util.jsindex.js代码如下

import { funcA } from  './util.js
funcA()

经过Tree shaking之后的util的代码如下

export function funcA() {}

因为我们只用到了funcA这一段函数代码,没有用到的funcB代码就会被剔除
需要注意的是要让 Tree Shaking 正常工作的前提是交给 Webpack 的 JavaScript 代码必须是采用 ES6 模块化语法的, 因为 ES6 模块化语法是静态的(导入导出语句中的路径必须是静态的字符串,而且不能放入其它代码块中),这让 Webpack 可以简单的分析出哪些 export 的被 import 过了。 如果你采用 ES5 中的模块化,例如 module.export={…}、require(x+y)、if(x){require(‘./util’)},Webpack 无法分析出哪些代码可以剔除
目前的 Tree Shaking 还有些的局限性,经实验发现:

  1. 不会对entry入口文件做 Tree Shaking;
  2. 不会对按序加载出去的代码做 Tree Shaking

使用TreeShaking

webpack5中如果是在生产模式下会自动调用Scope Hoisting

开启 Scope Hoisting

Scope Hoisting 可以让 Webpack 打包出来的代码文件更小、运行的更快, 它又译作 “作用域提升”,是在 Webpack3 中新推出的功能。

什么是 Scope Hoisting

比如有两个文件分别是util.jsindex.js,其中代码分别如下

// util.jsexport default 'Hello, Scope hoisting'
//index.js
import str from './util.js'
console.log(str)

以上代码打包之后如下

[(function (module, __webpack_exports__, __webpack_require__) {var __WEBPACK_IMPORTED_MODULE_0__util_js__ = __webpack_require__(1);console.log(__WEBPACK_IMPORTED_MODULE_0__util_js__["a"]);}),(function (module, __webpack_exports__, __webpack_require__) {__webpack_exports__["a"] = ('Hello,Webpack');})
]

开启了Scope hoisting 之后打包的代码如下

[(function (module, __webpack_exports__, __webpack_require__) {var util = ('Hello,Webpack');console.log(util);})
]

可以看到开启 Scope hoisting 之后,函数申明由两个直接变成了一个,util.js中的定义内容直接被注入到了index.js模块中,这样的好处是:

  • 代码体积更小,因为函数申明语句会产生大量代码;
  • 代码在运行时因为创建的函数作用域更少了,内存开销也随之变小

Scope Hoisting 的基本原理是分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余,所以只有那些被引用了一次的模块才能被合并。
Tree shaking一样,使用Scope Hoisting需要分析出模块之间的依赖关系,所以源代码必须使用ES6模块化语句。不然无法生效

配置Scope Hoisting

webpack5中如果是在生产模式下会自动调用Scope Hoisting

提取公共代码

在日常开发中一个站点往往是由很多页面组成的,这些页面一般都是采用相同的技术栈和同一套代码样式,并且我们在开发时也会抽离很多可复用的代码。
如果每个页面都把这些公共的代码打包进去就会造成下面的问题:

  1. 相同的资源被重复加载,浪费用户的流量和服务器的成本
  2. 每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验

针对上面的问题我们可以把公共的代码抽离成单独的文件,就可以优化上面的问题,原因是如果用户访问了网站中的某个页面,那么访问这个站点下的其他页面的概率也非常大。用户在第一次访问之后这些公共代码就被缓存起来,这样用户切换到其他页面时,缓存的代码文件就不会被重复加载。可以直接从缓存中获取,这样就有以下好处:

  • 减少网络传输流量,降低服务器成本;
  • 虽然用户第一次打开网站的速度得不到优化,但之后访问其它页面的速度将大大提升;
    在webpack5中可以使用optimization.splitChunks 提取公共代码一个简单的示例如下:
 optimization: {moduleIds: 'deterministic',usedExports: true,splitChunks: {chunks: 'all',minSize: 20000,minChunks: 1,maxAsyncRequests: 30,maxInitialRequests: 30,enforceSizeThreshold: 50000,cacheGroups: {// React相关库react: {test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,name: 'react',priority: 0},// UI库antd: {test: /[\\/]node_modules[\\/]antd[\\/]/,name: 'antd',priority: -1},// 其他第三方库vendors: {test: /[\\/]node_modules[\\/]/,name: 'vendors',priority: -10},// 分离公共组件commons: {name: 'commons',minChunks: 2,priority: -20}}}},

分割代码按需加载

为什么要分割代码按需加载

随着互联网的发展,一个网页需要承载的功能越来越多。 对于采用单页应用作为前端架构的网站来说,会面临着一个网页需要加载的代码量很大的问题,因为许多功能都集中的做到了一个 HTML 里。 这会导致网页加载缓慢、交互卡顿,用户体验将非常糟糕。
导致这个问题的根本原因在于一次性的加载所有功能对应的代码,但其实用户每一阶段只可能使用其中一部分功能。 所以解决以上问题的方法就是用户当前需要用什么功能就只加载这个功能对应的代码,也就是所谓的按需加载。

如何使用按需加载

在给单页应用做按需加载优化时,一般采用以下原则:

  • 把整个网站划分成一个个小功能,再按照每个功能的相关程度把它们分成几类;
  • 把每一类合并为一个 Chunk,按需加载对应的 Chunk;
  • 对于用户首次打开你的网站时需要看到的画面所对应的功能,不要对它们做按需加载,而是放到执行入口所在的 Chunk 中,以降低用户能感知的网页加载时间;
  • 对于个别依赖大量代码的功能点,例如依赖 Chart.js 去画图表、依赖 flv.js 去播放视频的功能点,可再对其进行按需加载;

被分割出去的代码的加载需要一定的时机去触发,也就是当用户操作到了或者即将操作到对应的功能时再去加载对应的代码。 被分割出去的代码的加载时机需要开发者自己去根据网页的需求去衡量和确定。
由于被分割出去进行按需加载的代码在加载的过程中也需要耗时,你可以预言用户接下来可能会进行的操作,并提前加载好对应的代码,从而让用户感知不到网络加载时间。

如何用 Webpack 实现按需加载

在 Webpack 5 中,按需加载(Lazy Loading) 是通过 动态导入(Dynamic Import) 来实现的,主要依靠 ES6 提供的 import() 语法。这样可以让 Webpack 在需要的时候才加载特定的模块,从而减少初始加载时间,提高应用的性能

Webpack 遇到 import() 语法时,会自动将导入的模块拆分成一个单独的 chunk,并在运行时动态加载它。

比如现在首页有一个按钮,只有点击这个按钮的时候才会去加载对应的工具文件去调用里面的计算方法。代码大体如下:

const loadDemo = async () => {try {// 使用 webpack 的动态导入语法const { sum, multiply } = await import(/* webpackChunkName: "demo" */ './demo').then(module => module);console.log('Dynamic import result:', sum(2, 3));console.log('Dynamic import result:', multiply(2, 3));} catch (error) {console.error('Failed to load demo module:', error);}
};// 创建一个按钮来触发动态加载
const button = document.createElement('button');
button.textContent = 'Load Demo Module';
button.onclick = loadDemo;
document.body.appendChild(button);
//demo.ts
export const sum = (a: number, b: number): number => {console.log('sum function is loaded dynamically');return a + b;
};export const multiply = (a: number, b: number): number => {console.log('multiply function is loaded dynamically');return a * b;
};

import(‘./demo.js’) 会告诉 Webpack 将 demo.js 单独打包为一个 chunk(如 demo.bundle.js)。
当 btn 按钮被点击时,才会请求加载 demo.bundle.js,这样就实现了按需加载。

webpack输出分析

我们需要对输出结果做分析,以决定下一步的优化方向。
但由于 Webpack 输出的代码可读性非常差而且文件非常大,这会让你非常头疼。 为了更简单直观的分析输出结果,社区中出现了许多可视化的分析工具。这些工具以图形的方式把结果更加直观的展示出来,可以帮助我们快速看到问题所在。 接下来看如何使用这些工具帮我们做优化
在启动 Webpack 时,支持两个参数,分别是:

  • –profile:记录下构建过程中的耗时信息;
  • –json:以 JSON 的格式输出构建结果,最后只输出一个 .json 文件,这个文件中包括所有构建相关的信息;
    在启动 Webpack 时带上以上两个参数,启动命令如下 webpack --profile --json > stats.json,你会发现项目中多出了一个 stats.json 文件。 这个 stats.json 文件是给后面介绍的可视化分析工具使用的。
    webpack --profile --json 会输出字符串形式的 JSON,> stats.json 是 UNIX/Linux 系统中的管道命令、含义是把 webpack --profile --json 输出的内容通过管道输出到 stats.json 文件中。

官方的可视化工具

Webpack 官方提供了一个可视化分析工具 Webpack Analyse,它是一个在线 Web 应用。
打开 Webpack Analyse 链接的网页后,你就会看到一个弹窗提示你上传 JSON 文件,这个就是上面生成的json文件,传上去之后会有这样的一个面板展示
在这里插入图片描述
可以看到有6个模块,当我们点击module中就可以看到当前各个模块的依赖关系:
在这里插入图片描述
点击 Hints,查看输出过程中的耗时分布,效果图如下:

webpack-bundle-analyzer

webpack-bundle-analyzer 是另一个可视化分析工具, 它虽然没有官方那样有那么多功能,但比官方的要更加直观。
先来看下它的效果图:
在这里插入图片描述

它能方便的让你知道:

  • 打包出的文件中都包含了什么;
  • 每个文件的尺寸在总体中的占比,一眼看出哪些文件尺寸大;
  • 模块之间的包含关系;
  • 每个文件的 Gzip 后的大小;
    接入 webpack-bundle-analyzer 的方法很简单,步骤如下:
  1. 安装 webpack-bundle-analyzer 到全局,执行命令 npm i -g webpack-bundle-analyzer;
  2. 按照上面提到的方法生成 stats.json 文件;
  3. 在项目根目录中执行 webpack-bundle-analyzer 后,浏览器会打开对应网页看到以上效果。

如何在webpack中使用

在配置文件中添加下面的配置,

// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;new BundleAnalyzerPlugin({analyzerMode: 'server',analyzerHost: '127.0.0.1',analyzerPort: 8888,reportFilename: 'report.html',defaultSizes: 'parsed',openAnalyzer: true,generateStatsFile: false,statsFilename: 'stats.json',statsOptions: null,logLevel: 'info'}),

在package.json中添加下面的命令

// package.json"analyze": "cross-env NODE_ENV=production webpack --profile --json > stats.json && webpack-bundle-analyzer stats.json"

直接运行即可对当前项目进行分析

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【操作系统】操作系统结构

内核 什么是内核? 内核作为应用程序连接硬件设备的桥梁,使得应用程序只需关心与内核交互,不用关心硬件细节。 内核有哪些能力呢? 内核是怎么工作的? Linux 的设计 MultiTask SMP ELF ELF 的意思是可执行文件链接格式…

【无线感知会议系列-22 】Vivisecting Mobility Management in 5G Cellular Networks

这篇是发表在SIGCOMM上的一篇paper 研究方向国内一些移动应用APP厂商:比如抖音,腾讯可以借鉴一下,和终端 厂商联合开发,提高其QOE。 摘要 随着5G技术对多种无线电频段和不同部署模式(例如独立组网(SA)与…

【RAG落地利器】Weaviate、Milvus、Qdrant 和 Chroma 向量数据库对比

什么是向量数据库? 向量数据库是一种将数据存储为高维向量的数据库,高维向量是特征或属性的数学表示。每个向量都有一定数量的维度,根据数据的复杂性和粒度,可以从数十到数千不等。 向量通常是通过对原始数据(如文本、图像、音频、视频等)…

算法18(力扣136)只出现一次的数字

1、问题 给你一个 非空 整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 2、示例 (1&…

【鸿蒙开发】第三十章 应用稳定性-检测、分析、优化、运维汇总

目录​​​​​​​ 1 概述 2 使用Asan检测内存错误 2.1 背景 2.2 原理概述 2.3 使用约束 2.4 配置参数 2.4.1 在app.json5中配置环境变量 2.4.2 在Run/Debug Configurations中配置环境变量 2.5 Asan使能 方式一 方式二 运行ASan 2.6 ASan异常检测类型 heap-buf…

20250214在ubuntu20.04下使用obs studio录制外挂的1080p的USB摄像头【下载安装】

20250214在ubuntu20.04下使用obs studio录制外挂的1080p的USB摄像头 2025/2/14 9:10 缘起:笔记本电脑在ubuntu20.04下使用Guvcview录制自带的摄像头,各种问题。 1、降帧率。WIN10/11自带的相机应用可以满速30fps,马上重启到ubuntu20.04&#…

phpipam1.7安装部署

0软件说明 phpipam是一个开源Web IP地址管理应用程序(IPAM) phpipam官网:https://www.phpipam.net/ 1安装环境 操作系统:Rocky Linux9.5x86_64 phpipam版本:1.7 php版本:8.0.30 数据库版本&#xff1a…

「vue3-element-admin」Vue3 + TypeScript 项目整合 Animate.css 动画效果实战指南

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …

LabVIEW用户界面(UI)和用户体验(UX)设计

作为一名 LabVIEW 开发者,满足功能需求、保障使用便捷与灵活只是基础要求。在如今这个用户体验至上的时代,为 LabVIEW 应用程序设计直观且具有美学感的界面,同样是不容忽视的关键任务。一个优秀的界面设计,不仅能提升用户对程序的…

AWTK-WEB 快速入门(4) - JS Http 应用程序

XMLHttpRequest 改变了 Web 应用程序与服务器交换数据的方式,fetch 是 XMLHttpRequest 继任者,具有更简洁的语法和更好的 Promise 集成。本文介绍一下如何使用 JS 语言开发 AWTK-WEB 应用程序,并用 fetch 访问远程数据。 用 AWTK Designer 新…

餐饮油烟在线监测仪,守护蓝天的隐形卫士

在城市化的快速发展中,餐饮业作为人们日常生活不可或缺的一部分,带来了便捷与美味的同时,也产生了大量餐饮油烟污染问题。据研究表明,长期暴露于高浓度油烟环境中不仅影响人体健康,还对空气质量造成严重破坏。为了有效…

从Sora到有言:3D视频生成技术的突破与应用

近年来,AIGC领域飞速发展,这个词也越来越高频地出现在了大家的生活中。AIGC 能完成的任务也越来越多,大模型的能力飞速增长 —— 从Deepseek生成文字,到StableDiffusion生成图像,再到Sora可以生成视频。 而现在&#x…

xiao单栏/网格布局typecho主题模板源码

源码介绍 xiao单栏/网格布局typecho主题模板源码 一款基于 bootstrap5.3.3 开发的 typecho 单栏主题 效果预览 源码获取 xiao单栏/网格布局typecho主题模板源码

如何运用边缘计算控制器提升智能工厂的竞争力?

制造业正经历一场深刻的变革。其中,边缘计算作为一项关键技术,在提升生产效率、降低成本以及实现智能制造方面发挥着至关重要的作用。本文将探讨边缘计算在智能工厂中的应用场景及其带来的价值。 边缘计算简介 边缘计算是一种分布式计算范式&#xff0…

今日学习总结

复习了dfs的相关内容&#xff0c;完成了一道dfs相关的题目。 P2371挑战算周长 #include <stdio.h> // 定义一个二维字符数组 map 用于存储地图信息&#xff0c;大小为 25x25 char map[25][25]; // 定义一个常量二维数组 d 作为方向增量数组&#xff0c;用于表示 8 个不同…

SpringMVC学习使用

一、SpringMVC简单理解 1.1 Spring与Web环境集成 1.1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的&#xff0c;但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(sp…

HCIA项目实践---OSPF的知识和原理总结

9.5 OSPF 9.5.1 从哪些角度评判一个动态路由协议的好坏&#xff1f; &#xff08;1&#xff09;选路佳&#xff08;是否会出环&#xff09; OSPF 协议采用链路状态算法&#xff0c;通过收集网络拓扑信息来计算最短路径&#xff0c;从根本上避免了路由环路的产生。 &#xff08…

算法题(67):最长连续序列

审题&#xff1a; 需要我们在O&#xff08;n&#xff09;的时间复杂度下找到最长的连续序列长度 思路&#xff1a; 我们可以用两层for循环&#xff1a; 第一层是依次对每个数据遍历&#xff0c;让他们当序列的首元素。 第二层是访问除了该元素的其他元素 但是此时时间复杂度来到…

2021年全国研究生数学建模竞赛华为杯E题信号干扰下的超宽带(UWB)精确定位问题求解全过程文档及程序

2021年全国研究生数学建模竞赛华为杯 E题 信号干扰下的超宽带(UWB)精确定位问题 原题再现&#xff1a; 一、背景   UWB&#xff08;Ultra-Wideband&#xff09;技术也被称之为“超宽带”&#xff0c;又称之为脉冲无线电技术。这是一种无需任何载波&#xff0c;通过发送纳秒…

Vue3折线图,柱状图,饼图,各种图表,适用于所有全平台

开发工具&#xff1a;HBuilderX编译器&#xff0c;uniapp&#xff0c;Vue3&#xff1b; 目标&#xff1a;全平台适用&#xff0c;Web端&#xff0c;小程序端&#xff0c;Android端&#xff0c;ios端&#xff0c;快应用等所有平台&#xff0c;鸿蒙app&#xff0c;前端&#xff…