Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR
简版
核心流程图
根据,Webpack的构建流程分为
初始化、编译和输出三个阶段
。初始化阶段读取配置
、加载插件
、实例化Compiler
。编译阶段(构建依赖关系
)涉及Compiler类的运行,生成Compilation对象
,处理模块依赖
。输出阶段通过seal方法生成最终文件
。则把流程分为四个阶段:初始化、编译、生成和输出。
生成阶段组装assets,输出阶段写入文件系统
。而分为输入、处理、输出和模块热替换(可选)四个阶段。但模块热替换属于开发时的优化,可能不是核心流程的一部分。
Webpack 的构建流程是一个多阶段的串行过程,主要分为初始化、编译、输出三个阶段,每个阶段包含多个关键步骤,并通过插件系统扩展功能。以下是详细解析:
1. 初始化阶段
- 读取与合并配置:从配置文件(如
webpack.config.js
)和命令行参数中读取配置,合并生成最终参数 。
形象化理解下面步骤:创建一个机器人(Compiler),它能指挥整个打包流程,还能触发各种工具(插件)帮忙
- 创建 Compiler 实例:Webpack 核心对象
Compiler
负责整个构建流程的调度,继承自Tapable
,具备事件发布订阅能力 。 - 加载插件:根据配置加载所有插件,调用插件的
apply
方法注册钩子监听 。 - 初始化模块规则:解析 module.rules,创建模块处理规则(如 .js 文件用 babel-loader)。
常用Loader与Plugin
Webpack中Loader和Plugin的基本概念。Loader用于处理文件,将不同类型的文件转换为Webpack可识别的模块
。而Plugin则用于执行更广泛的任务,如打包优化、资源管理和环境变量注入
等。
loader 运行在打包文件之前 plugins 在整个编译周期都起作用 在 Webpack 运行的生命周期中会广播出许多事件,
Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果 对于
loader,实质是一个转换器,将A文件进行编译形成B文件,操作的是文件,比如将 A.scss 或 A.less 转变为
B.css,单纯的文件转换过程
一、常用 Loader
Loader 用于处理文件转换,将非 JS 资源(如 CSS、图片)转换为 Webpack 可识别的模块。
1. JavaScript 处理
Loader | 作用 | 示例配置 |
---|---|---|
babel-loader | 将 ES6+/TypeScript 转译为 ES5 | { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } |
ts-loader | 编译 TypeScript 代码 | { test: /\.ts$/, use: 'ts-loader' } |
2. 样式处理
Loader | 作用 | 示例配置 |
---|---|---|
css-loader | 解析 CSS 文件中的 @import 和 url() | { test: /\.css$/, use: ['style-loader', 'css-loader'] } |
style-loader | 将 CSS 注入到 DOM 的 <style> 标签中 | (需与 css-loader 配合使用,见上例) |
sass-loader | 将 SCSS/SASS 编译为 CSS | { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] } |
postcss-loader | 自动添加 CSS 浏览器前缀 | { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] } |
3. 文件与静态资源
Loader | 作用 | 示例配置 |
---|---|---|
file-loader | 处理图片/字体等文件,输出到构建目录 | `{ test: /.(png |
url-loader | 小文件转为 Base64,大文件用 file-loader | `{ test: /.(png |
svg-sprite-loader | 将 SVG 合并为雪碧图 | { test: /\.svg$/, use: 'svg-sprite-loader' } |
4. 框架相关
Loader | 作用 | 示例配置 |
---|---|---|
vue-loader | 编译 Vue 单文件组件(.vue) | { test: /\.vue$/, use: 'vue-loader' } |
react-hot-loader | 支持 React 组件的热更新 | (需在 Babel 配置中配合使用) |
二、常用 Plugin
Plugin 用于扩展 Webpack 功能,处理更广泛的任务(如优化、资源管理)。
1. 核心工具
Plugin | 作用 | 示例配置 |
---|---|---|
html-webpack-plugin | 自动生成 HTML 并注入 JS/CSS 链接 | new HtmlWebpackPlugin({ template: './src/index.html' }) |
clean-webpack-plugin | 构建前清理输出目录 | new CleanWebpackPlugin() |
webpack.HotModuleReplacementPlugin | 启用模块热更新(HMR) | new webpack.HotModuleReplacementPlugin() (需配合 devServer.hot: true ) |
//ScriptExtHtmlWebpackPlugin 是 html-webpack-plugin 的功能扩展插件,
//专注于优化 HTML 文件中 <script> 标签的部署策略。
//它通过灵活的配置选项,赋予开发者对脚本加载行为的精细化控制,
//从而提升页面性能、适配现代浏览器特性并满足安全需求。config => {config.plugin('ScriptExtHtmlWebpackPlugin').after('html').use('script-ext-html-webpack-plugin', [{// `runtime` must same as runtimeChunk name. default is `runtime`inline: /runtime\..*\.js$/}]).end()
ScriptExtHtmlWebpackPlugin 核心作用与功能详解
2. 代码优化
Plugin | 作用 | 示例配置 |
---|---|---|
mini-css-extract-plugin | 将 CSS 提取为独立文件(替代 style-loader ) | new MiniCssExtractPlugin({ filename: '[name].css' }) |
compression-webpack-plugin | 生成 Gzip/Brotli 压缩文件 | `new CompressionPlugin({ test: /.(js |
terser-webpack-plugin | 压缩 JS 代码(Webpack 5 默认集成) | optimization: { minimizer: [new TerserPlugin()] } |
split-chunks-plugin | 代码分割(Webpack 4+ 内置) | optimization: { splitChunks: { chunks: 'all' } } |
//代码分割策略:
//chunk-libs:将 node_modules 中的第三方库打包成单独文件
//chunk-elementUI:单独打包 ElementUI 组件库(优先级更高)
//chunk-commons:将 src/components 中被引用3次以上的组件打包成公共 chunkconfig.optimization.splitChunks({chunks: 'all',cacheGroups: {libs: {name: 'chunk-libs',test: /[\\/]node_modules[\\/]/,priority: 10,chunks: 'initial' // only package third parties that are initially dependent},elementUI: {name: 'chunk-elementUI', // split elementUI into a single packagepriority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or apptest: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm},commons: {name: 'chunk-commons',test: resolve('src/components'), // can customize your rulesminChunks: 3, // minimum common numberpriority: 5,reuseExistingChunk: true}}})
3. 性能分析
Plugin | 作用 | 示例配置 |
---|---|---|
webpack-bundle-analyzer | 可视化分析打包体积 | new BundleAnalyzerPlugin({ analyzerMode: 'static' }) |
speed-measure-webpack-plugin | 测量各 Loader/Plugin 耗时 | const smp = new SpeedMeasurePlugin(); module.exports = smp.wrap(config) |
4. 环境与扩展
Plugin | 作用 | 示例配置 |
---|---|---|
dotenv-webpack | 注入 .env 环境变量 | new Dotenv({ path: './.env' }) |
copy-webpack-plugin | 复制静态文件到输出目录 | new CopyPlugin({ patterns: [{ from: 'public', to: 'assets' }] }) |
define-plugin | 定义全局常量(Webpack 内置) | new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true) }) |
三、开发与生产环境配置示例
1. 开发环境 (webpack.dev.js)
const { HotModuleReplacementPlugin } = require('webpack');module.exports = {plugins: [new HotModuleReplacementPlugin(),new HtmlWebpackPlugin({ template: './src/index.html' }),],module: {rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] },{ test: /\.js$/, use: ['babel-loader'] },]}
};
2. 生产环境 (webpack.prod.js)
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');module.exports = {plugins: [new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),new CompressionPlugin({ algorithm: 'gzip' }),],module: {rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'] },]},optimization: {minimizer: [new CssMinimizerPlugin(), '...'], // '...' 表示保留默认 Terser 配置splitChunks: { chunks: 'all' },},
};
四、最佳实践建议
-
开发环境:
- 使用
style-loader
+css-loader
快速加载样式。 - 启用
HMR
提升开发效率。
- 使用
-
生产环境:
- 用
mini-css-extract-plugin
分离 CSS。 - 开启代码压缩(
TerserPlugin
、CssMinimizerPlugin
)。 - 使用
split-chunks-plugin
分割公共代码。
- 用
-
通用优化:
- 通过
cache-loader
或babel-loader?cacheDirectory
缓存构建结果。 - 使用
thread-loader
并行处理耗时的 Loader。
- 通过
-
工具链扩展:
- 结合
eslint-loader
或husky
+lint-staged
实现代码规范检查。 - 利用
webpack-dev-server
配置代理解决跨域问题。
- 结合
掌握这些 Loader 和 Plugin,可高效应对 Webpack 的构建需求,优化项目性能与开发体验!
2. 编译阶段(构架依赖关系图)
- 启动构建:调用
Compiler.run()
方法,触发compile
钩子,创建Compilation
对象管理模块和依赖关系 。 - 解析入口文件:根据配置的
entry
确定所有入口文件,开始递归分析依赖 。 - 模块处理:
- 调用 Loader:对每个模块(如 JS、CSS、图片)调用匹配的 Loader 进行转译(例如 Babel 转换 ES6 代码) 。
- 生成 AST:使用解析器(如
acorn
)将模块内容转换为抽象语法树(AST),分析依赖关系 。 - 收集依赖:递归处理所有依赖模块,生成模块对象并存入
Compilation.modules
。
- 生成依赖图:构建完整的模块依赖关系图,为分块(Chunk)做准备 。
3. 输出阶段
- 生成 Chunk:根据入口和依赖关系,将模块组合成 Chunk(代码块)。一个入口通常对应一个 Chunk,动态导入的模块可能生成额外 Chunk 。
- 优化 Chunk:执行代码分割(Code Splitting)、合并重复代码等优化操作 。
- 生成 Assets:将 Chunk 转换为最终资源文件(如 JS、CSS),调用模板(如
MainTemplate
)生成运行时代码和模块信息 。 - 写入文件系统:
- 触发
emit
钩子,允许插件在输出前修改资源 。 - 创建输出目录,将文件写入磁盘 。
- 触发
- 完成构建:触发
done
钩子,输出构建统计信息(如耗时、资源大小) 。
关键对象与扩展机制
- Compiler:全局控制器,管理生命周期钩子(如
beforeRun
、compile
、emit
) 。 - Compilation:单次构建的上下文,存储模块、Chunk、资源等数据 。
- Loader:处理非 JS 模块的转换(如 CSS 转 JS 模块) 。
- Plugin:通过监听钩子干预构建流程(如
HtmlWebpackPlugin
生成 HTML 文件) 。
流程示例
初始化 → 启动 Compiler → 解析入口 → 调用 Loader → 生成 AST → 收集依赖 → 生成依赖图 → 分块优化 → 生成 Assets → 输出文件
通过这一流程,Webpack 将分散的模块打包成浏览器可执行的静态资源,同时支持通过配置和插件实现高度定制化 。
HMR热更新实现原理
HMR 中的协作流程
WebSocket 推送变更:服务端通过 WebSocket 通知客户端“代码已更新”。
JSONP 拉取更新:客户端根据通知,用 JSONP 请求具体的更新文件(如 [hash].hot-update.js)。
执行替换:新模块代码通过 JSONP 加载后,替换旧模块,完成热更新。
Vite式HMR与Webpack HMR对比详解
一、核心差异总结
维度 | Vite HMR | Webpack HMR |
---|---|---|
底层原理 | 基于浏览器原生ES模块(ESM)动态加载 | 基于打包后的Bundle文件与运行时注入逻辑 |
启动速度 | 毫秒级(无需打包) | 秒级(需构建完整依赖图) |
更新效率 | 仅编译修改的模块,速度与项目规模无关 | 需重新构建依赖链,大项目变慢 |
配置复杂度 | 默认开启,零配置 | 需手动启用插件和配置DevServer |
适用场景 | 中小项目、现代框架(Vue/React) | 超大型项目、需要深度定制构建流程 |
二、实现原理对比
1. Webpack HMR(传统方案)
-
运行流程:
- 监听文件变化:通过
webpack-dev-server
监听代码变更,触发增量构建。 - 生成差异文件:重新打包修改的模块及其依赖链,生成
.hot-update.js
文件。 - 通信机制:通过WebSocket推送更新消息到浏览器,客户端用JSONP拉取差异文件。
- 模块替换:运行时(Runtime)替换旧模块,执行
module.hot.accept
回调。
- 监听文件变化:通过
-
性能瓶颈:
- 冷启动慢:需构建完整依赖图,大项目可能耗时数分钟。
- 更新延迟:每次修改需重新分析依赖链,导致HMR响应速度随项目增长下降。
2. Vite HMR(现代方案)
-
运行流程:
- 按需编译:开发阶段不打包,直接通过ESM导入源码。
- 即时编译:浏览器请求模块时,Vite实时编译并返回(如转换SASS/JSX)。
- 精准更新:文件修改后,仅重新编译该模块并通过WebSocket推送更新信息。
- 浏览器处理:浏览器直接重新请求新模块,利用缓存减少重复传输。
-
核心技术:
- ESM动态加载:浏览器直接解析
import
语句,Vite仅转换语法糖(如TS)。 - HTTP/2优化:多路复用减少请求数,强缓存依赖模块。
- 依赖预构建:用
esbuild
将CommonJS模块转为ESM,提速10-100倍。
- ESM动态加载:浏览器直接解析
三、更新机制差异
Webpack的更新逻辑
文件修改 → 触发完整依赖链构建 → 生成差异文件 → 客户端替换模块
- 问题:修改一个模块可能导致整个依赖链重新构建,如修改
utils.js
会影响所有引用它的组件。
Vite的更新逻辑
文件修改 → 标记失效模块 → 浏览器重新请求该模块 → 局部更新
- 优势:通过
import.meta.hot
API精准控制更新范围,仅失效受影响模块链。
示例代码对比
// Webpack中手动声明HMR边界
if (module.hot) {module.hot.accept('./moduleA', () => {// 重新渲染模块A});
}// Vite中声明HMR边界
if (import.meta.hot) {import.meta.hot.accept('./moduleA', (newModule) => {// 直接使用新模块});
}
四、性能数据对比(实测场景)
指标 | Vite | Webpack | 差异原因 |
---|---|---|---|
冷启动时间 | 200ms-1s | 10s-3min | Vite无打包,Webpack需构建Bundle |
HMR响应时间 | 50-200ms | 500ms-5s | Vite按需编译,Webpack重构建依赖链 |
内存占用 | 200-500MB | 1-3GB | Webpack需维护完整依赖图 |
五、适用场景与局限性
Vite的优势场景
- 快速原型开发:如React/Vue新项目,需即时反馈。
- 模块化明确的项目:ESM规范的代码结构清晰。
- 现代框架支持:Vue单文件组件、React Fast Refresh深度集成。
Webpack的不可替代性
- 超大型应用:如企业级ERP系统,
需复杂代码分割和自定义Loader
。 - 遗留项目迁移:
大量CommonJS模块或Webpack插件依赖
。 - 深度定制需求:
如自定义Bundle优化、非标准资源处理
。
六、面试回答要点(精简版)
-
核心差异:
- Vite基于ESM动态加载,Webpack基于Bundle运行时替换。
- Vite冷启动快、HMR响应快,适合现代项目;Webpack生态强,适合复杂场景。
-
实现原理:
- Webpack通过重新打包依赖链,Vite通过浏览器按需加载+服务端实时编译。
-
性能对比:
- Vite的HMR速度与项目规模无关,Webpack随项目增大变慢。
-
选择建议:
- 新项目优先Vite,大型遗留项目用Webpack,两者可共存(如Vite为主,Webpack处理特殊模块)。
Dev-Server与Proxy
Webpack DevServer 与 Proxy 工作原理深度解析
一、Webpack DevServer 的核心定位
Webpack DevServer 是 Webpack 官方提供的本地开发服务器,专为开发环境设计,集成以下核心功能:
- 静态资源托管:基于 Express 框架托管编译后的资源,提供 HTTP 访问能力 。
- 实时编译与刷新:通过
webpack-dev-middleware
监听源码变化,触发增量编译,并支持 Live Reload(自动刷新)和 HMR(热模块替换)。 - 代理转发(Proxy) :解决浏览器同源策略导致的跨域问题,将 API 请求转发至目标服务器 。
- 开发友好功能:如错误覆盖层、路由重定向(
historyApiFallback
)等 。
二、DevServer 与 Proxy 的协作流程
1. 核心架构
- Express 服务器:DevServer 底层基于 Express,负责处理 HTTP 请求和静态资源响应。
- WebSocket 通道:用于
HMR 通信
,实现无刷新热更新。 - Proxy 中间件:通过
http-proxy-middleware
拦截并转发特定请求 。
2. 跨域问题的解决原理
- 浏览器限制:直接从前端页面(如
localhost:8080
)请求不同源的后端 API(如[http://api.example.com](http://api.example.com)
)会触发跨域错误。 - 代理中转:
- 前端代码中请求相对路径(如
/api/data
)。 - DevServer 通过
proxy
配置,将/api
前缀的请求转发至目标服务器(如[http://api.example.com](http://api.example.com)
)。 代理服务器(DevServer)与目标服务器通信不受浏览器同源策略限制,完成数据中转
。
- 前端代码中请求相对路径(如
示例配置:
// webpack.config.js
devServer: {proxy: {'/api': {target: 'http://api.example.com',pathRewrite: { '^/api': '' }, // 移除请求路径中的 /api 前缀changeOrigin: true, // 修改请求头中的 Host 为目标服务器地址secure: false // 允许转发到 HTTPS 服务器}}
}
3. 请求转发流程
- 浏览器发起请求:如
GET [http://localhost:8080/api/users](http://localhost:8080/api/users)
。 - DevServer 拦截:匹配到
/api
规则,触发代理逻辑。 - 请求重写:路径被改写为
[http://api.example.com/users](http://api.example.com/users)
,并添加必要的请求头(如Host
)。 - 转发与响应:DevServer 将请求发送至目标服务器,接收响应后返回给浏览器 。
三、关键技术点剖析
devServer: {host: '0.0.0.0',port: port,open: false,proxy: {[process.env.VUE_APP_BASE_API]: {target: `http://localhost:8080`,changeOrigin: true,pathRewrite: {['^' + process.env.VUE_APP_BASE_API]: ''}},// Tomcat上的资源+项目部署在Tomcat上则不存在跨域[process.env.VUE_APP_BASE_TOM]: {target: `http://localhost:8010`,changeOrigin: true,pathRewrite: {['^' + process.env.VUE_APP_BASE_TOM]: ''}},[process.env.VUE_APP_BASE_PY]:{target: `http://localhost:5010`,changeOrigin: true,pathRewrite: {['^' + process.env.VUE_APP_BASE_PY]: ''}}},disableHostCheck: true},
1. http-proxy-middleware
的作用
- 中间件集成:作为 Express 中间件,处理请求拦截、路径重写、头信息修改等逻辑。
- 灵活配置:支持多代理规则、正则匹配、自定义响应处理等 。
2. changeOrigin
参数的意义
- 默认行为:浏览器发送的请求头
Host
值为localhost:8080
(DevServer 地址)。 - 启用后:将
Host
修改为目标服务器地址(如api.example.com
),避免后端服务器因域名不符拒绝请求 。
3. 路径重写(pathRewrite
)
- 场景:后端 API 可能不需要
/api
前缀,通过正则表达式移除或替换路径部分。 - 示例:
pathRewrite: { '^/api': '/v2' }
将/api/users
转换为/v2/users
。
4. 安全性控制
secure: false
:允许代理到 HTTPS 服务器(默认验证证书,开发环境可关闭)。onProxyReq
钩子:可注入自定义逻辑(如添加鉴权头)。
四、开发环境与生产环境的差异
1. 开发环境
- 依赖 DevServer:所有 API 请求通过 DevServer 代理。
- 优势:无需后端配合修改 CORS 配置,快速联调 。
2. 生产环境
- 禁用 DevServer:使用 Nginx 或云服务商代理。
- 配置分离:通过环境变量动态切换 API 地址,避免硬编码 。
五、常见问题与调试技巧
1. 代理规则不生效
- 检查路径匹配:确认请求路径是否匹配
proxy
中的键(如/api
是否包含在 URL 中)。 - 日志输出:启用
logLevel: 'debug'
查看代理详细日志 。
2. HTTPS 证书问题
- 配置
secure: false
:临时绕过证书验证(仅限开发环境)。 - 自签名证书:通过
https: true
和cert
/key
配置加载本地证书 。
3. 请求头丢失
- 显式设置 Headers:通过
headers
参数添加必要头信息(如Authorization
)。 - 钩子函数:使用
onProxyReq
动态修改请求 。
六、性能优化与进阶用法
1. 多目标代理
proxy: [{context: ['/auth', '/api'],target: 'http://backend.example.com',changeOrigin: true},{context: '/static',target: 'http://cdn.example.com'}
]
2. 代理缓存
- 缓存策略:通过
http-proxy-middleware
的selfHandleResponse
拦截响应,实现缓存逻辑。 - 减少重复请求:对静态资源或低频变动的 API 启用缓存 。
3. 与 HMR 协同工作
- 独立端口:代理服务器与 HMR 的 WebSocket 使用不同端口,避免冲突。
- 优先级控制:确保代理规则不会误拦截 HMR 的 WebSocket 请求 。
七、总结
- DevServer 核心价值:提供一体化开发环境,整合编译、热更新、代理等能力。
- Proxy 本质:基于中间件的请求转发,突破浏览器同源策略限制。
- 适用场景:前后端分离开发、多服务联调、本地模拟生产环境。
通过合理配置 DevServer 和 Proxy,开发者可以在本地环境中无缝对接后端服务,提升开发效率的同时规避跨域问题。实际应用中需注意环境隔离、路径匹配精度和安全性控制,确保代理逻辑的可靠性与性能 。
网络攻击
Proxy代理可能引发的安全攻击问题及防御策略
XSS
一、路径遍历攻击(Path Traversal)
-
原理简述:
攻击者通过构造恶意路径(如/api/../../etc/passwd
),利用代理的pathRewrite
规则绕过安全限制,访问服务器敏感文件或目录。 -
防御方案:
// 安全配置示例:精确匹配路径,禁止动态篡改 proxy: {'/api/v1/': {target: 'https://safe-api.com',pathRewrite: { '^/api/v1/': '/secure/' }, // 固定路径重写规则} }
-
扩展思考:
避免使用通配符(如^/api
)覆盖过广的路径规则,结合正则表达式严格限制路径范围。
二、服务端请求伪造(SSRF)
-
原理简述:
若代理目标(target
)动态来源于用户输入,攻击者可篡改目标地址,访问内网服务(如[http://localhost:3306](http://localhost:3306)
)或第三方敏感接口。 -
防御方案:
// 禁止动态目标,仅允许白名单域名 const allowedTargets = ['https://trusted-api.com']; proxy: {'/api': {target: allowedTargets[0], // 固定目标changeOrigin: true,} }
-
扩展思考:
生产环境应通过反向代理(如 Nginx)替代前端代理,避免动态配置暴露风险。
三、敏感信息泄露
-
原理简述:
- 代理配置
secure: false
忽略 HTTPS 证书校验,导致中间人攻击(MITM)。 - 未过滤响应头暴露后端信息(如
Server: Apache/2.4.1
)。
- 代理配置
-
防御方案:
// 启用证书校验,过滤敏感头 proxy: {'/api': {target: 'https://safe-api.com',secure: true, // 强制校验 HTTPS 证书onProxyRes: (proxyRes) => {delete proxyRes.headers['x-powered-by']; // 删除危险响应头}} }
-
扩展思考:
开发环境临时使用secure: false
时,需确保不涉及敏感数据传输。
四、XSS 与 CSRF 攻击
-
原理简述:
- 代理未过滤响应内容,恶意脚本通过 API 响应注入页面。
- 未校验
Origin
头,允许跨域伪造请求(如诱导用户提交表单)。
-
防御方案:
// 启用 CORS 策略,校验请求来源 devServer: {headers: {'Access-Control-Allow-Origin': 'https://your-domain.com', // 白名单'Access-Control-Allow-Methods': 'GET,POST', // 限制请求方法} }
-
扩展思考:
结合内容安全策略(CSP)进一步防御 XSS,如设置Content-Security-Policy
头。
五、缓存投毒攻击(Cache Poisoning)
-
原理简述:
代理服务器缓存被恶意篡改的响应(如注入恶意脚本的 JS 文件),导致后续用户加载被污染资源。 -
防御方案:
// 开发环境禁用缓存 devServer: {hot: true, // 启用热更新inline: true, // 禁用缓存 }
-
扩展思考:
生产环境使用内容哈希(如[name].[contenthash].js
)确保文件唯一性,避免缓存冲突。
Webpack优化前端性能☆☆
涵盖了代码分割、懒加载、压缩、缓存优化、Tree Shaking、图片优化、CDN使用等多个方面
。接下来,我需要将这些信息有条理地组织起来,确保覆盖所有主要优化策略,同时引用对应的资料。
Webpack优化前端性能详解(2025综合实践版)
Webpack作为现代前端工程化的核心工具,其优化能力直接影响项目的首屏速度、交互流畅度和用户体验。以下从代码维度、资源维度、构建维度和网络维度四大方向,系统解析15+实战优化策略:
一、代码维度优化
1. 代码压缩与混淆
-
JS压缩:生产模式下默认集成
TerserPlugin
,可配置多进程并行压缩(parallel: true
)与深度混淆(mangle: true
)。optimization: {minimize: true,minimizer: [new TerserPlugin({parallel: 4, // 启用4线程加速terserOptions: { compress: { drop_console: true } } // 移除console})] }
-
CSS压缩:通过
css-minimizer-webpack-plugin
删除冗余空格、合并重复样式。 -
HTML压缩:
HtmlWebpackPlugin
的minify
选项可折叠空格、移除注释。
2. Tree Shaking(摇树优化)
- 原理:基于ESM静态分析,剔除未引用代码(Dead Code)。
- 配置要点:
- 使用ES6模块语法(
import/export
) - 设置
sideEffects: false
标记无副作用模块 - 生产模式自动启用(
mode: 'production'
)
- 使用ES6模块语法(
3. 作用域提升(Scope Hoisting)
- 原理:将模块合并到单一作用域,减少闭包数量,提升执行效率。
- 启用方式:
optimization.concatenateModules: true
二、资源加载优化
1. 代码分割(Code Splitting)
-
策略分类:
类型 适用场景 实现方式 入口分割 多页应用 配置多入口(entry) 动态导入 路由级懒加载 import()
语法公共代码提取 多入口共享库(React/lodash) SplitChunksPlugin
-
SplitChunks配置示例:
optimization: {splitChunks: {chunks: 'all',minSize: 20000, // 最小分割体积20KBcacheGroups: {vendors: {test: /[\\/]node_modules[\\/]/,priority: -10 // 优先级高于默认组}}} }
2. 懒加载(Lazy Loading)
- 实现方式:
- 路由级:React中
React.lazy
+Suspense
,Vue中异步组件。 - 组件级:动态
import()
配合Webpack的魔法注释(/* webpackPrefetch: true */
)预加载关键资源。
const LazyComponent = React.lazy(() => import(/* webpackChunkName: "lazy-comp" */ './LazyComponent' ));
- 路由级:React中
3. 图片与静态资源优化
- 压缩策略:
image-webpack-loader
:支持PNG/JPG渐进式加载与有损压缩。svg-sprite-loader
:合并SVG图标为雪碧图,减少HTTP请求。
- 格式转换:
responsive-loader
自动生成WebP/AVIF等现代格式,体积减少30%-70%。
三、构建速度与缓存优化
1. 构建加速
- 缓存策略:
- Loader缓存:
cache-loader
缓存Babel/TypeScript编译结果。 - 持久化缓存:
cache: { type: 'filesystem' }
(Webpack 5+)。
- Loader缓存:
- 并行处理:
- HappyPack:多进程执行Loader(适用于Webpack 4)。
- Thread-loader:将耗时的Loader(如Babel)移至Worker线程。
2. 长期缓存策略
-
哈希策略:
[contenthash]
:基于文件内容生成哈希,内容不变则哈希不变。[chunkhash]
:按Chunk生成哈希,适用于代码分割场景。
output: {filename: '[name].[contenthash:8].js',chunkFilename: '[name].[contenthash:8].chunk.js' }
-
CDN部署:
- 公共库外链:通过
externals
排除React/Vue等,使用CDN加速。 - 资源上传:
webpack-cdn-upload-plugin
自动上传资源至阿里云/腾讯云CDN。
- 公共库外链:通过
四、网络层深度优化
1. 压缩与传输优化
- Gzip/Brotli压缩:
- 构建时压缩:
compression-webpack-plugin
预生成.gz
/.br
文件。 - 服务端动态压缩:Nginx配置
gzip_static on
优先发送预压缩文件。
- 构建时压缩:
- HTTP/2优化:
- 多路复用:减少连接数,提升资源并行加载效率。
- Server Push:主动推送关键资源(需服务端配合)。
2. 预加载与预渲染
- Resource Hints:
<link rel="preload">
:提前加载关键字体/首屏图片。<link rel="prefetch">
:空闲时加载非关键路由资源。
- 预渲染(Prerender SPA) :对SEO敏感页面生成静态HTML,加速首屏渲染。
五、监控与持续优化
1. 性能分析工具
- Bundle分析:
webpack-bundle-analyzer
可视化分析模块体积。 - 构建耗时分析:
speed-measure-webpack-plugin
统计各阶段耗时。 - Lighthouse审计:集成到CI/CD流程,自动化性能评分。
2. 按需优化策略
指标 | 优化手段 | 预期收益 |
---|---|---|
首屏加载时间 >3s | 代码分割 + 懒加载 + 图片压缩 | 减少30%-50%资源体积 |
交互延迟 >100ms | 代码拆分 + Tree Shaking | 减少主包JS执行时间 |
FCP >2s | 预加载关键CSS + 服务端渲染(SSR) | 提升20%-40%首屏渲染速度 |
总结
Webpack性能优化需遵循渐进式优化原则,结合项目阶段选择合适策略:
- 开发阶段:启用Tree Shaking、模块热替换(HMR)。
- 构建阶段:代码分割、资源压缩、缓存优化。
- 部署阶段:CDN加速、HTTP/2、预加载。
- 监控阶段:持续分析性能指标,动态调整优化策略。
通过多维度协同优化,可将典型SPA应用的Lighthouse性能评分提升至90+,实现极致用户体验。
提升Webpack构建速度策略
优化方向可归纳为:减少处理量(精准配置)、并行化任务(多进程)、利用缓存(持久化)、代码精简(Tree Shaking)
。实际项目中需结合构建分析工具逐步调优,并根据 Webpack 版本选择最佳实践(如 Webpack 5 优先使用内置缓存而非第三方插件)
以下是提高 Webpack 构建速度的详细优化方案,按逻辑分层解析:
一、基础配置优化
-
缩小文件处理范围
- 使用
include
和exclude
精准限定 loader 的作用目录,避免处理无关文件(如node_modules
)。 - 通过
noParse
忽略无需解析的第三方库(如 jQuery),直接跳过 AST 解析 。
- 使用
-
优化模块解析规则
- 配置
resolve.alias
为常用路径设置别名,减少路径解析时间 。 - 精简
resolve.extensions
扩展名列表,优先高频后缀(如.js
,.ts
)以加速匹配 。 - 指定
resolve.modules
为绝对路径(如path.resolve(__dirname, 'node_modules')
),避免逐层目录搜索 。
- 配置
二、并行与多进程加速
-
多进程处理任务
- 使用
thread-loader
将高开销的 Loader(如 Babel)分配到子进程并行执行,充分利用 CPU 多核 。 - 生产环境可搭配
webpack-parallel-uglify-plugin
并行压缩代码 。
- 使用
-
预编译静态资源
- 通过
DllPlugin
将基础库(如 React、Lodash)提前打包为动态链接库(DLL),避免重复构建 。 - Webpack 5 推荐使用
Module Federation
实现微前端架构的模块共享,替代传统 DLL 方案 。
- 通过
三、缓存机制
-
持久化缓存
- Webpack 5 内置
cache: { type: 'filesystem' }
,将模块依赖关系缓存到磁盘,二次构建仅处理变更部分 。 - 对 Babel 配置
cacheDirectory: true
,缓存转换结果 。
- Webpack 5 内置
-
缓存工具兼容性
- Webpack 4 及以下版本可用
cache-loader
或hard-source-webpack-plugin
实现类似效果 。
- Webpack 4 及以下版本可用
四、代码优化策略
-
Tree Shaking
- 开启
optimization.usedExports: true
标记未使用代码,结合TerserPlugin
删除无用代码 。 - 注意避免副作用代码,确保 ESM 规范导入导出 。
- 开启
-
代码分割与按需加载
- 使用
SplitChunksPlugin
抽离公共模块(如工具函数库),减少重复打包 。 - 动态导入(
import()
)实现路由级按需加载,减少初始构建体积 。
- 使用
-
外部化依赖
- 配置
externals
将稳定第三方库(如 jQuery)通过 CDN 引入,不参与打包 。
- 配置
相关文章:
Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR
简版 核心流程图 根据,Webpack的构建流程分为初始化、编译和输出三个阶段。初始化阶段读取配置、加载插件、实例化Compiler。编译阶段(构建依赖关系)涉及Compiler类的运行,生成Compilation对象,处理模块依赖。输出阶…...
Python 实现的采集诸葛灵签
Python 实现的采集诸葛灵签 项目介绍 这是一个基于 Python 开发的诸葛灵签数据采集和展示项目。通过爬虫技术获取诸葛神签的签文和解签内容,并提供数据存储和查询功能。 项目结构 zhuge/├── zhuge_scraper.py # 爬虫主程序├── zhuge_pages/ # 数据存储目录…...
ESP-IDF ubuntu版本 V5.2
1.MobaXterm 这个软件方面粘贴,文件拷贝 MobaXterm 2.安装之前请确保你安装了Python 和 pip V5.2需要python3.8和pip mkdir esp32 cd esp32 git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git cd esp-gitee-tools ./jihu-mirror.sh set cd .. git clone …...
Opencv之掩码实现图片抠图
掩码实现图片抠图 目录 掩码实现图片抠图1 掩码1.1 概念1.2 创建掩码1.3抠图思路 2 代码测试 1 掩码 1.1 概念 掩码(Mask)是一种用于指定图像处理操作区域的工具。掩码通常是一个与图像尺寸相同的二值图像,其中像素值为0表示不处理ÿ…...
警惕!Ollama大模型工具的安全风险及应对策略
文章目录 **Ollama的安全隐患:不容忽视的风险****未授权访问:门户洞开的风险****数据泄露:敏感信息的外泄****漏洞利用:历史遗留的隐患** **安全加固:守护数据与服务的防线****限制监听范围:内网隔离的保护…...
MySQL -- 表的约束
概念引入:真正的约束表字段的是数据类型,但是数据类型的约束方式比较单一的,所以需要一些额外的一些约束,用于表示数据的合法性,在只有数据类型一种约束的情况下,我们比较难保证数据是百分百合法。通过添加…...
详解数据库范式
范式 1. 第一范式(1NF)2. 第二范式(2NF)3. 第三范式(3NF)4. BC范式(BCNF,Boyce-Codd Normal Form)5. 第四范式(4NF)6. 第五范式(5NF&a…...
Nginx + Keepalived 高可用集群
一、NginxKeepalived 原理 1.1.Nginx 负载均衡机制 Nginx 是一款轻量级且高性能的 Web 服务器和反向代理服务器,在负载均衡方面有着卓越的表现。其具备强大的七层流量管理能力,能够基于 URL、Cookie、HTTP 头信息等对请求进行精准路由。例如࿰…...
循环遍历 Java 集合中元素的方法总结
循环遍历 Java 集合中元素的方法 在 Java 中,有多种方法可以遍历集合中的元素。以下是几种常见的遍历方法及其优缺点: 1. for-each 循环 语法: for (ElementType element : collection) {// 处理 element }适用场景:所有集合类型…...
树莓派上的 TensorFlow Lite:从零开始的摄像头图像识别
**** 1. 引言 随着人工智能(AI)和机器学习(ML)的发展,越来越多的开发者希望在嵌入式设备(如树莓派)上运行 AI 模型,实现目标检测、人脸识别等功能。TensorFlow Lite(TF…...
金融时间序列分析(Yahoo Finance API实战)
这里写目录标题 金融时间序列分析(Yahoo Finance API实战)1. 引言2. 项目背景与意义3. 数据集介绍4. GPU加速在数据处理中的应用5. 交互式GUI设计与加速处理6. 系统整体架构7. 数学公式与指标计算8. 完整代码实现9. 代码自查与BUG排查10. 总结与展望金融时间序列分析(Yahoo …...
Python 正则表达式模块 re
Python 正则表达式模块 re flyfish 一、正则表达式基础 1. 什么是正则表达式? 正则表达式(Regular Expression, RE)是一种用于匹配、查找和替换文本模式的工具,由普通字符(如字母、数字)和特殊字符&…...
Vue生命周期
一、Vue的生命周期及其阶段 Vue生命周期:一个Vue实例从 创建 到 销毁 的整个过程。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。 生命周期的四个阶段:① 创建 ② 挂…...
vue3数据双向绑定解析
Vue 3 的双向绑定原理主要基于 Proxy 和 Reflect,核心源码在 reactivity 模块中。 1. 核心模块:reactivity reactivity 模块负责响应式数据的实现,主要包括以下几个文件: reactive.ts:处理对象和数组的响应式。ref.t…...
Gemini 2.0 全面解析:技术突破、应用场景与竞争格局
摘要 2025年3月,谷歌正式发布Gemini 2.0大模型,凭借其在多模态处理、代码生成和长上下文理解等领域的突破性进展,迅速成为AI领域的焦点。本文将深入剖析Gemini 2.0的技术架构、应用场景及与Grok3、DeepSeek R1、ChatGPT-4.5等竞品的对比&…...
【Linux系统编程】管道
目录 1、什么是管道2、管道的种类3、数据的读写3.1、管道通信3.2、管道的命令实例: 4、无名管道4.1、pipe() 无名管道的创建示例:简单读写示例:加入进程示例:通过 管道(pipe) 实现 父子进程之间的双向通信 …...
LeeCode题库第643题
643.子数组最大平均数I 项目场景: 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。 请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。 任何误差小于 10-5 的答案都将被视为正确答案。 示例 1: 输入ÿ…...
数据炼丹与硬件互动:预测湿度的武学之道
前言 在这茫茫数据江湖中,高手过招,唯有融合机器学习与物联网之精髓,方能于风云变幻间自成一派。本文正是为各位江湖同道献上的秘籍,既有数据炼丹(预处理、模型训练)之奥义,也有硬件互通&#…...
【SpringBoot】MD5加盐算法的详解
目录 一、什么是加盐算法 二、如何实现加盐算法 2.1 加盐算法代码实现 2.2 注册页面中进行密码加盐 2.3 登录页面进行加盐的解密 2.4 注册和登录 一、什么是加盐算法 加盐算法是一种用于增强密码安全性的技术。这种技术通过在密码存储过程中添加一个随机生成的盐值&…...
IP风险度自检,互联网的安全“指南针”
IP地址就像我们的网络“身份证”,而IP风险度则是衡量这个“身份证”安全性的重要指标。它关乎着我们的隐私保护、账号安全以及网络体验,今天就让我们一起深入了解一下IP风险度。 什么是IP风险度 IP风险度是指一个IP地址可能暴露用户真实身份或被网络平台…...
如何手动使用下载并且运行 QwQ-32B-GGUF
首先使用安装 pip install ModelScope 使用 ModelScope 下载对应的模型 modelScope download --model Qwen/QwQ-32B-GGUF qwq-32b-q4_k_m.gguf 第二步开始下载 ollama git clone https://githubfast.com/ggerganov/llama.cpp # githubfast.com 可以加速下载 切换到目录&am…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-3-从ES 7.x到8.x的平滑迁移策略
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 附录-版本升级指南 3-Elasticsearch 7.x 到 8.x 平滑迁移策略指南1. 升级必要性分析1.1 版本特性对比1.2 兼容性评估矩阵 2. 预升级准备清单2.1 环境检查表2.2 数据备份策略 3. 分阶段…...
IP 地址
文章目录 IP 地址IP 地址的分类IPv4 地址IPv6 地址 公有 IP 与私有 IP静态 IP 与动态 IP子网与子网掩码常见 IP 地址用途IP 地址的工作方式总结 IP 地址 IP(Internet Protocol)地址是计算机网络中的标识符,用于唯一标识网络中的设备。它可以…...
利用余弦相似度在大量文章中找出抄袭的文章
我前面的2篇文章分别讲了如果利用余弦相似度来判断2篇文章的相似度,来确定文章是否存在抄袭,和余弦相似度的原理,即余弦相似度到底是怎么来判断文章的相似性高低的等等。这一篇再说下,对于文章字数多和大量文章时,如果…...
《C语言中“输入魔法师”:scanf函数的奥秘与技巧》
🚀个人主页:fasdfdaslsfadasdadf 📖收入专栏:C语言 🌍文章目入 一、引言二、scanf函数的基本语法三、格式说明符的种类及用法(一)整数输入(二)浮点数输入(三&…...
VSTO(C#)Excel开发6:与窗体交互
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
PCL 点云OBB包围盒(二)
文章目录 一、简介二、实现步骤二、实现代码三、实现效果参考资料一、简介 包围盒是一种求解离散点集最优包围空间的算法,基本思想是用体积稍大且特性简单的几何体(称为包围盒)来近似地代替复杂的几何对象。(来源于百度)常用的求解包围盒的算法主要有AABB和OOB算法,但AAB…...
IDEA 一键完成:打包 + 推送 + 部署docker镜像
1、本方案要解决场景? 想直接通过本地 IDEA 将最新的代码部署到远程服务器上。 2、本方案适用于什么样的项目? 项目是一个 Spring Boot 的 Java 项目。项目用 maven 进行管理。项目的运行基于 docker 容器(即项目将被打成 docker image&am…...
农业建设项目管理系统评测:8款推荐工具优缺点分析
本文主要介绍了以下8款农业建设项目管理系统:1.PingCode; 2. Worktile ;3. 建米农业工程项目管理系统;4. 开创云数字农业管理平台; 5. Trimble Ag Software;6.Conservis; 7. Agworld ࿱…...
【MySQL】表的约束(上)
文章目录 表的约束什么是表的约束空属性默认值列描述(comment)零填充(zerofill)主键 总结 表的约束 什么是表的约束 表的约束(Constraints)是数据库表中的规则,用于限制存储的数据,…...
根据TCP中的拥塞控制细说网卡了数据怎么传输
TCP(传输控制协议)中的拥塞控制是确保网络在数据传输过程中不会发生过载并导致网络崩溃的机制。拥塞控制通过动态地调整发送方的数据传输速率来适应网络的负载,从而避免网络拥塞。TCP的拥塞控制主要是根据网络的状况自动调整其发送速率&#…...
【SpringMVC】入门版
1.基本概念 1.1三层架构 三层架构也就是我们常说的b/s架构中的表现层,业务层和持久层,每层都各司其职,下面来分别讲解这三层的作用。 表现层: 也就是我们常说的web层。它负责接收客户端的请求,向客户端响应结果,通…...
DAY33 贪心算法Ⅱ
122. 买卖股票的最佳时机 II - 力扣(LeetCode) 想到把整体利润分解为每天的利润,就豁然开朗了。 class Solution { public:int maxProfit(vector<int>& prices) {int result0;for(int i1;i<prices.size();i){resultmax(0,pric…...
re-二维四向迷宫题
关于迷宫 我们结合具体的来进行描述。 迷宫,顾名思义是有墙,且只有一条路可以走下去。当我们在题目中获得了map(地图)就拥有了上帝视角,就可以顺利的走出迷宫。 在下面这个图就是一个迷宫的map,其中A是起…...
并发编程面试题一
1、什么是进程、线程、协程,他们之间的关系是怎样的 进程是操作系统进行资源分配和调度的基本单位。每个进程都有独立的内存空间,进程之间相互独立,一个进程崩溃不会影响其他进程,进程间通信(IPC)需要通过…...
3.14周报
本周主要是在找双目视觉三维人体姿态估计方向的文章,这篇dual-diffusion,双目三维人体姿态估计的双扩散文章,引起了兴趣,作者从由于摄像机数量的减少,增加了3d重建的不确定性入手,然后使用了扩散模型&#…...
【redis】zset 类型:基本命令(上)
set 集合: 唯一无序。(顺序不重要)孙行者、行者孙>同一只猴 list 有序。(顺序很重要)孙行者、行者孙>不同的猴 zset 有序。升序/降序 有序集合 排序的规则是什么? 给 zset 中的 member 引入了…...
3分钟复现 Manus 超强开源项目 OpenManus
文章目录 前言什么是 OpenManus构建方式环境准备克隆代码仓库安装依赖配置 LLM API运行 OpenManus 效果演示总结个人简介 前言 近期人工智能领域迎来了一位备受瞩目的新星——Manus。Manus 能够独立执行复杂的现实任务,无需人工干预。由于限制原因大部分人无法体验…...
【Java篇】一法不变,万象归一:方法封装与递归的思想之道
文章目录 Java 方法的使用:从基础到递归的全面解析一、方法的概念及使用1.1 什么是方法 (method)?1.2 方法定义1.3 方法调用的执行过程1.4 实参和形参的关系1.5 没有返回值的方法 二、方法重载2.1 为什么需要方法重载2.2 方法重载的概念2.2.4 C 和 Java 的比较&…...
SpringBoot解决跨域
将这个类添加到项目中 ResponseAdvice.java package com.example.homeLearn.config;import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework…...
【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-2-性能调优工具箱
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 附录-性能调优工具箱 2-Elasticsearch 性能调优工具箱深度指南一、性能诊断工具集1.1 实时监控工具1.2 慢查询分析 二、硬件与基础架构优化2.1 存储方案选型2.2 JVM调优参数 三、索引…...
UDP协议栈之整体架构处理
在之前的章节中,笔者就UDP、ICMP、IP、ARP、MAC层的报文格式,以及组帧解帧、CRC校验、分片处理等操作进行了具体介绍以及详细代码实现,并且通过了仿真测试。但之前的仿真测试都是对单层报文的组帧解帧进行的,这些模块仍处于“孤立…...
健康医疗:动态代理 IP 保障医疗数据安全,提升远程医疗服务质量!
在数字化浪潮的推动下,远程医疗服务以其便捷性和高效性受到了广泛的关注。然而,随之而来的是数据安全问题,尤其是医疗数据的安全性,成为了制约远程医疗服务发展的关键因素。幸运的是,动态代理IP技术的出现,…...
Navicat SqlServer 设置自增主键
Navicat是一款优秀的数据库管理工具,可以连接很多类型的数据库。使用它可以极大的提高工作效率。 Navicat 不能设置SqlServer自增字段,只能通过sql语句来实现 建表时设置 create table <表名> ( <字段1-主键> int identity (1,1) primar…...
实验8 搜索技术
实验8 搜索技术 一、实验目的 (1)掌握搜索技术的相关理论,能根据实际情况选取合适的搜索方法; (2)进一步熟悉盲目搜索技术,掌握其在搜索过程中的优缺点; (3)…...
IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T3【传球游戏】题解
目录 一、提问词 二、DeepSeekR1回复 题目描述 解题思路 实现代码 代码说明 三、说明 【IMADeepSeekR1本地知识库】撰写NOIP2008普及组复赛题解系列 1、IMADeepSeekR1本地知识库撰写NOIP2008普及组T1【ISBN 号码】题解-CSDN博客 2、IMADeepSeekR1本地知识库撰写NOIP200…...
查找特定的值(信息学奥赛一本通-1110)
【题目描述】 在一个序列(下标从1开始)中查找一个给定的值,输出第一次出现的位置。 【输入】 第一行包含一个正整数n,表示序列中元素个数。1 <n< 10000。 第二行包含n个整数,依次给出序列的每个元素,相邻两个整数之间用单个…...
Qt项目中集成第三方模块的.pri文件
对于功能模块较多的Qt项目,使用pri文件管理模块文件,降低工程复杂度,提高软件模块的封装性和重用性。 一、.pro与.pri 对于模块化编程,Qt提供了pro和pri,pro管理项目,pri管理模块。 .pro 文件是Qt项目的…...
200多种算法应用于二维和三维无线传感器网络(WSN)覆盖场景
2.1 二元感知模型 在当前无线传感器网络(WSN)覆盖场景中,最常见且理想的感知模型是二元感知模型[27]。如图2所示, Q 1 Q_1 Q1和 Q 2 Q_2 Q2代表平面区域内的两个随机点。 Q 1 Q_1 Q1位于传感器的检测区域内,其感…...
【QT】文件系统相关 -- QFile
一、Qt 文件概述 🔥 文件操作是应用程序必不可少的部分。Qt 作为⼀个通用开发库,提供了跨平台的文件操作能力。Qt 提供了很多关于⽂件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件制或重命名等 二、输…...