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

vite性能优化

性能优化

我们平时说性能优化是在说什么东西?

  1. 开发时态的构建速度优化: npm run dev 敲下的瞬间到呈现结果要占用多少时长
  • webpack在这方面下的功夫是很重:
    • webpack4 会用到 cache-loader, webpack5 提供了cache选项, 作用就是: 如果两次构建源代码没有产生变化,则直接使用缓存 不调用loader,
    • thread-loader 开启多线程去构建
  • vite 是按需加载,所以我们不需要太在意这方面
  1. 页面性能指标: 和我们怎么去写代码有关
  • 首屏渲染时长: fcp (页面中第一个元素的渲染时长)
    • 懒加载: 需要我们去写代码实现的
    • 服务端渲染
    • http优化: 协商缓存和强缓存
    • 强缓存: 服务端给响应头追加一些字段(expires),客户端会记住这些字段,在expires(截止失效时间)没有到达之前,无论你怎么刷新页面,浏览器都不会重新请求页面,而是从缓存里取
    • 协商缓存: 是否使用缓存要跟后端商量一下,当服务端给我们打上协商缓存的标记以后,客户端在下次刷新页面, 需要重新请求资源时会发送一个协商请求给到服务端,服务端如果说需要变化, 则会响应具体的内容,如果服务端觉得没变化则会响应304
  • 页面最大元素的一个时长: lcp (largest content paint)
  1. js逻辑
  • 我们要注意副作用的清除, 组件是会频繁的挂载和卸载: 如果我们在某一个组件中有计时器(setTimeout),如果我们在卸载的时候不去清除这个计时器,下次再次挂载的时候计时器等于开了两个线程
# 经常看到这样的react代码
const [timer,setTimer]=useState(null);
userEffect(()=>{setTimer(setTimeout(()=>{}));return()=>clearTimeout(timer);    
})
  • 我们再写法上一个注意事项: requestAnimationFrame,requestIdleCallback 这两个API卡浏览器帧率 对浏览器渲染原理要有一定的认识 然后再这方面做优化
    • requestIdleCallback: 传一个函数进去, 这个函数会在js逻辑和重排重绘完成之后执行
    • 浏览器的帧率:16.6ms去更新一次(执行js逻辑 以及重排重绘..),假设我的js执行逻辑超过了16.6, 重排重绘的时间就会被挤占, 就会出现掉帧
  • 防抖节流,要使用lodash.js, 自己写的通常不是最佳实践
  • 对于大量循环, 不使用 Array.prototype.forEach()方法, 使用lodash.js提供的forEach()方法
  • 对于作用域的控制
const arr = [1,2,3]
for(let i=0, len=arr.length; i<len; i++) {
}
  1. css
  • 关注继承属性: 能继承的旧不要重复写
  • 尽量避免太过于深的css嵌套
  1. 构建优化: vite(rollup) webpack
  • 优化体积: 代码压缩,treeshaking,图片资源压缩,cdn加载,分包

分包策略

  1. 使用odash, 完成一个简单的循环任务, 然后查看打包结果
npm install lodash
import { forEach } from "lodash";const arr = [1, 2, 3, 4, 5]
forEach(arr, (item) => {console.log(item);
})

  1. 打包后的代码是经过压缩的, 很难阅读, 我们配置一下不压缩
import { defineConfig } from "vite"
import check from "vite-plugin-checker"export default defineConfig({"build": {"minify": false},plugins: [check({typescript: true})]
})
  1. 再打包看结果, 业务代码和工具代码被打包在一起了, 这样并不是最好的方式, 因为业务代码经常变动, 工具代码基本不变, 从浏览器缓存这个角度考虑, 把不会常规更新的文件单独打包处理, 可以让浏览器更好的复用缓存资源, 减少HTTP传输压力

  1. 这样去配置
import { defineConfig } from "vite"
import check from "vite-plugin-checker"export default defineConfig({"build": {"minify": false,"rollupOptions": {"output": {"manualChunks": (id: string) => {console.log("id:", id); // 拿到工程中所有的文件路径/*** 这是一个简单处理: * 1.所有路径包含node_modules的文件我们都认为是工具包* 2.所有工具包都打包到 vendor-随机哈希值 文件中* 3.报错: includes()这个方法是es6之后的方法, ts默认工程环境是es5, 所以要配置一下*/if (id.includes("node_modules")) {return "vendor";}}}}},plugins: [check({typescript: true})]
})
// 配置一些ts的检查手段和规则
{"compilerOptions": {"moduleResolution": "node", // 模块解析方案"skipLibCheck": true, // 忽略对node_modules目录的检查"module": "ESNext", // 编译为最新的ES语法"lib": [ // 配置ts工程环境是es7"ES2017","DOM"]}
}
  1. 重新打包, 业务代码和工具代码分在不同包, 这样用户就可以更多的使用vendor.js缓存, index.js传输体积也会更小

gzip压缩

  1. 有时候我们的文件资源实在是太大了
  • js文件 ---> 打包后2000kb --->http传输压力大
  1. 将所有的静态文件进行压缩,已达到减少体积的目的
  • vite服务端 -> 执行打包 --> 压缩文件 -> 得到压缩过的打包结果
  • 客户端请求资源 -> 收到压缩包资源 --> 浏览器解压缩 --> 得到原始资源 -> 渲染
  1. 使用打包插件
npm install vite-plugin-compression
import { defineConfig } from 'vite'
import viteCompression from 'vite-plugin-compression'export default defineConfig({plugins: [viteCompression()]
})

  1. 浏览器不能直接渲染压缩后的资源
  • 用户请求 index.html, 服务端返回 index.js.gz
  • 当服务端读取到gzip文件 (.gz后缀), 就要设置一个响应头 (content-encoding: gzip)
  • 代表告诉浏览器该文件是使用gzip压缩过的
  • 浏览器收到响应结果 发现响应头里有gzip对应字段,赶紧解压, 得到原来原原本本的js文件 (浏览器是要承担一定的解压时间的)
  • 如果体积不是很大的话 不要用gzip压缩

动态导入

  1. 动态导入的作用和按需加载的作用是差不多的
  • 按需加载: 一个文件导出了很多方法, 用到哪个方法就导入哪个方法, 不要把整个文件都引入进来
  • 动态导入: 一个工程会有很多文件, 当前页面用到哪些文件就去解析对应文件, 不要把所有文件都解析完
  1. vite和webpack实现动态导入的方式是不一样的
  • vite使用的es6提供的动态导入技术 (新特性)
// 静态导入
import "./src/imageLoader"// 动态导入(es6新特性)
// import函数始终返回一个Promise
import("./src/imageLoader").then(data => {log(data)
})// 动态导入典型的应用场景是路由
const Home = () => import('@/view/home')
// 挂载页面
router: [{path: '/', component: Home}
]
  • webpack是自己封装的动态导入方法
function import(path) {//resolve不被调用的话 Promise永远是pending状态return new Promise((resolve)=>{//进入到对应路由时将webpack_require.e这个promise的状态设置为fullfilled (调用resolve) //如果我从来没进入过home页面,我就让这个webpack_require.e永远在悬停(pending)状态webpack__require.e().then(()=>{const result = await webpack__require(path)})})
}// 核心思想
// 当没有进入过某个页面或者组件的时候,我们让这个组件的代码放入一个script标签里 但是这个script标签不塞入到body里去
// 当进入这个页面时,我们将script标签塞入到整个body里去
// 动态导入的文件会不会被webpack编译???? 肯定是会被编译
// 动态导入的文件会不会被加载?? 不会,用到了才会加载

cdn加速

  1. cdn全称 content delivery network (内容分发网络)
  2. 我们的所有依赖以及源码文件在我们进行打包以后(yarn build)会放到我们的服务器上面去
  3. 我的服务器在深圳, 你在纽约访问我这个网站, 由于网络传输距离太远, 就会有点卡
  4. 典型情况, 就是不翻墙的情况下, 访问没有被封的网站, 比如github, 普遍就很慢
  5. cdn加速就是将我们依赖的第三方模块全部写成cdn的形式,就近加载, 提高速度
  6. 并且也让我们自身的代码体积变小了, 服务器和客户端的传输就更轻松 (依赖的lodash是通过cdn加载的, 源码自身的体积也就变小了)
  7. 搭建基础工程

import _ from "lodash"
const obj = _.cloneDeep({name: "张三"
})
console.log("obj=", obj);
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script src="./src/main.js" type="module"></script>
</body></html>
npm init -y
npm install lodash
{"name": "05vite-cnd","version": "1.0.0","main": "index.js","scripts": {"dev": "vite","test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","description": "","dependencies": {"lodash": "^4.17.21","vite": "^7.1.4"}
}

  1. 在工程中使用cnd插件实现优化
npm install vite-plugin-cdn-import -D
import { defineConfig } from "vite";
import viteCDNPPlugin from "vite-plugin-cdn-import"export default defineConfig({plugins: [viteCDNPPlugin({modules: [{name: "lodash",var: "_",path: "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"}]})]
})
  1. 打包工程, 打包后的文件中不再有loadsh的内容, 而是通过cnd就近分发给用户

  1. 插件的原理
  • 区分工程环境, 开发环境不工作, 生产环境的话就开始做事情
  • 往head中注入script标签, 引用第三方库

  • 因为vite生产环境的打包使用rollup, 所以还会修改一下rollup的配置, 类似于下面的效果

配置跨域

  1. 同源策略

http交互默认情况下只能在同协议同域名同端口的两台终端进行通信

  1. 什么是跨域

跨域【仅发生在浏览器】: 当A源浏览器的网页 向 B源的服务器地址(不满足同源策略,满足同源限制) 请求对应信息,就会产生跨域,跨域请求默认情况下会被浏览器拦截,除非对应的请求服务器出具标记说这个A源是值得信任的

  1. 跨域解决方案

开发时态

  • 我们一般就利用构建工具或者脚手架或者第三方库的proxy 代理配置
import { defineConfig }from "vite";export default defineConfig({server:{  //开发服务器中的配置proxy:{ // 配置跨域解决方案"/api":{target:"https://www.360.com", // 目标地址changeOrigin: true,// 要换源rewrite:(path)=> path.replace(/^\/api/,'') // 路径重写}}}
})
  • 或者我们自己搭一个开发服务器来解决这个问题
// vite服务器处理跨域的伪代码if(ctx.request.url.includes("/api")) {const target =proxy.target;const rewrite = str => strconst result =await request(target + rewrite("/api"));ctx.response.body = result;
}// 基本原理
// 1.前端启动本地vite服务
// 2.前端请求基地址都使用127.0.0.1
// 3.所以的请求都会打到我们自己的vite服务
// 4.使用服务端去请求资源, 然会返回给前端
// 5.本质就是通过vite服务转发请求, 绕过同源策略 

生产时态: 我们一般是交给后端去处理跨域

  • nginx代理服务
  • 配置身份标记
Access-Control-Allow-Origin: 被信任的朋友, 被标记的域名不再受同源策略限制

// 声明服务器支持范围请求(Range Requests), 客户端可请求资源的部分内容(如大文件分块下载、断点续传)
accept-ranges:bytes
access-control-allow-credentials: true // 允许跨域请求携带凭证信息(如Cookies、HTTP认证)
access-control-allow-methods:GET,HEAD // 允许的跨域请求的方法
access-control-allow-origin: https://baike.baidu.com // 指定允许跨域访问的源(Origin)
// 暴露自定义响应头给浏览器, 使客户端可通过JavaScript(如response.headers)读取这些头信息
access-control-expose-headers: ETag, Content-Length, x-bce-next-append-offset,x-bce-object-type, x-bce-request-id 
// 设置CORS预检请求(OPTIONS)的缓存时间。在30分钟内,相同请求的跨域预检结果可被缓存,无需重复发送OPTIONS请求,减少网络开销。
access-control-max-age:1800

public

我们可以在项目根目录创建一个public目录, 这里面的资源不会经过vite打包处理, 直接放到dist结果中

const img = import("/public/morgan.png")
console.log("img=", img);
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><img src="/public/morgan.png" alt=""><script src="./src/main.js" type="module"></script>
</body></html>

  1. 也不是经常使用, 因为尽量让资源都经过vite处理, 这样会有一些压缩优化
  2. 如果有资源确实不需要vite处理, 就放在里面挺合适
http://www.dtcms.com/a/456592.html

相关文章:

  • git添加远程仓库报错To add an exception for this directory解决方案-优雅草卓伊凡
  • 手机AIDE使用OpenCV
  • AI智能体(Agent)大模型入门【9】--如何在pycharm等其他编译软件调用ocr工具【只写后端代码不演示】
  • 浅析SpringBoot框架常见未授权访问漏洞
  • 有什么可以做翻译的网站点的排版设计网站
  • 第五十三章 ESP32S3 TCPClient 实验
  • 中国突破柔性电池技术瓶颈:可弯折20000次引领能源存储革命
  • 网站制作公司的宣传海报品牌免费网站建设
  • 基于模板缓冲的矢量贴地显示
  • flink keyby使用与总结 基础片段梳理
  • flink UTDF函数
  • 乐陵网站开发贾汪区建设局网站
  • VS安装EEPlus库及解决[弃用的]CS0618问题
  • 《算法闯关指南:优选算法--滑动窗口》--15.串联所有单词的子串,16.最小覆盖子串
  • 行驶证识别技术通过OCR和AI实现信息自动化采集与处理,涵盖图像预处理、文字识别及结构化校验,提升效率与准确性
  • 第十七篇:数组与链表:结构特性、操作与经典题目
  • 营销型网站的优点深圳推广系统
  • 攻防世界-Web-easyupload
  • 符号主义对自然语言处理深层语义分析的影响与启示
  • 高要区住房和城乡建设局网站西安建设市场信息平台
  • 新手可以做网站营运吗成都手机模板建站
  • 成都市做网站的公司网站开发客户端
  • 农业机械网站模板网站建设图片像素是多大的
  • 素材网站php程序源码公司简介介绍
  • 网站规划的一般步骤建设企业网站包含什么
  • 奉贤做网站建设wordpress访问很慢吗?
  • 大学生网站建设开题报告免费交流网站建设
  • 邢台做网站优化哪儿好怎样建网站
  • 企业网站 asp php修改wordpress邮件
  • 宠物网站开发背景怎样自己制作效果图