内江市建设教育培训官方网站,微信小程序怎么做成链接,wordpress 插件 小程序,外贸网站建设需要注意什么2023年最新的前端面试收集 一、你在项目中做的性能优化的事情有哪些网络优化页面渲染优化JS优化图片优化webpack打包优化vue优化react优化 二、webworker中为什么能提升js执行的性能三、微前端 一、你在项目中做的性能优化的事情有哪些
网络优化 DNS预解析 link标签的rel属性设… 2023年最新的前端面试收集 一、你在项目中做的性能优化的事情有哪些网络优化页面渲染优化JS优化图片优化webpack打包优化vue优化react优化 二、webworker中为什么能提升js执行的性能三、微前端 一、你在项目中做的性能优化的事情有哪些
网络优化 DNS预解析 link标签的rel属性设置dns-prefetch提前获取域名对应的IP地址 使用缓存 减轻服务端压力快速得到数据(强缓存和协商缓存) 强缓存 浏览器在访问某个资源时会判断是否使用本地缓存里已经存在的资源文件使用本地缓存的话则不会发送请求到服务器从而达到减轻服务器访问压力的作用且由于直接从本地缓存读取资源文件大大提高了加载速度。服务器可以通过在响应头里设置Cache-Control: max-age31536000max-age代表缓存时间单位为秒Cache-Control除了max-age外还可以设置其它属性值 no-cache: 不使用强缓存但仍会使用协商缓存。 no-store: 不使用缓存不使用强缓存也不使用协商缓存每次都向服务器发送资源请求。 private 只允许客户端使用缓存不允许其他代理服务器进行缓存。 public: 客户端和代理服务器都可缓存。 s-maxage: 与max-age类似区别是s-maxage是设定代理服务器的缓存时间。 使用缓存的话状态码200后面会标明情况。浏览器缓存资源的地方有两个磁盘缓存disk cache和内存缓存memory cache。 一般来说浏览器会将较大的资源缓存到disk cache而较小的资源则被缓存到memory cache里。内存缓存与磁盘缓存相比访问速度要更快一些 强缓存除了使用Cache-Control实现之外还可以使用Expires字段缺点是依赖本地时间可以被篡改Expires是Http1.0规范Cache-Control是Http1.1规范,Cache-control的优先级要高于Expires如果两者同时设置会优先使用Cache-control而忽略掉Expires。 协商缓存 在强缓存里是否使用缓存是由浏览器来确定的而协商缓存则是由服务器来告诉浏览器是否使用缓存资源也就是浏览器每一次都要发送请求到服务器询问是否使用缓存浏览器初次请求资源服务器返回资源同时生成一个Etag值携带在响应头里返回给浏览器当浏览器再次请求资源时会在请求头里携带If-None-Match值是之前服务器返回的Etag的值服务器收到之后拿该值与资源文件最新的Etag值做对比。 如果没有变化则返回304告诉浏览器继续使用缓存不返回资源文件。如果发生变化则返回200和最新的资源文件给浏览器使用。 除了Etag外还有一个Last-Modified的属性是一个时间值它是Http1.0规范的服务器返回Last-Modified浏览器请求头对应携带的是If-Modified-since。相比Last-ModifiedEtag优先级更高使用上也更精确一些因为有时候会存在文件内容并没有改变但文件的修改时间变更了Last-Modified不一致所以服务器会重新返回资源文件实际上还是可以继续使用缓存的。 总结 强缓存优先级大于协商缓存即两者同时存在时如果强缓存开启且在有效期内则不会走协商缓存。 -强缓存就是浏览器本地根据服务器设置的过期时间来判断是否使用缓存未过期则从本地缓存里拿资源已过期则重新请求服务器获取最新资源。协商缓存则是浏览器本地每次都向服务器发起请求由服务器来告诉浏览器是从缓存里拿资源还是返回最新资源给浏览器使用。 使用 CDN内容分发网络 用户与服务器的物理距离对响应时间也有影响。内容分发网络CDN是一组分散在不同地理位置的 web 服务器用来给用户更高效地发送内容。典型地选择用来发送内容的服务器是基于网络距离的衡量标准的。例如选跳数hop最少的或者响应时间最快的服务器。 压缩响应 压缩组件通过减少 HTTP 请求产生的响应包的大小从而降低传输时间的方式来提高性能。从 HTTP1.1 开始Web 客户端可以通过 HTTP 请求中的 Accept-Encoding 头来标识对压缩的支持这个请求头会列出一系列的压缩方法如果 Web 服务器看到请求中的这个头就会使用客户端列出的方法中的一种来压缩响应。Web 服务器通过响应中的 Content-Encoding 头来告知 Web 客户端使用哪种方法进行的压缩目前许多网站通常会压缩 HTML 文档脚本和样式表的压缩也是值得的包括 XML 和 JSON 在内的任何文本响应理论上都值得被压缩。但是图片和 PDF 文件不应该被压缩因为它们本来已经被压缩了。 使用多个域名 Chrome 等现代化浏览器都会有同域名限制并发下载数的情况不同的浏览器及版本都不一样使用不同的域名可以最大化下载线程但注意保持在 2~4 个域名内以避免 DNS 查询损耗。 避免图片src为空 虽然 src 属性为空字符串但浏览器仍然会向服务器发起一个 HTTP 请求IE 向页面所在的目录发送请求Safari、Chrome、Firefox 向页面本身发送请求Opera 不执行任何操作。
页面渲染优化 Webkit 渲染引擎渲染流程 1. 处理 HTML 并构建 DOM 树 2. 处理 CSS 构建 CSS 规则树(CSSOM) 3. DOM Tree 和 CSSOM Tree 合成一棵渲染树 Render Tree。 4. 根据渲染树来布局计算每个节点的位置 5. 调用 GPU 绘制合成图层显示在屏幕上 避免css阻塞 css影响renderTree的构建会阻塞页面的渲染因此应该尽早将 CSS 放在 head 标签里和尽快启用 CDN 实现静态资源加载速度的优化)的将css资源加载 降低css选择器的复杂度 浏览器读取选择器遵循的原则是从选择器的右边到左边读取。 减少嵌套最多不要超过三层并且后代选择器的开销较高慎重使用避免使用通配符对用到的元素进行匹配即可利用继承避免重复匹配和定义正确使用类选择器和id选择器 避免使用CSS 表达式 css 表达式会被频繁地计算。 避免js阻塞 js可以修改CSSOM和DOM因此js会阻塞页面的解析和渲染并且会等待css资源的加载。也就是说js会抢走渲染引擎的控制权。所以我们需要给js资源添加defer或者async延迟js脚本的执行。 使用外链式的js和css 在现实环境中使用外部文件通常会产生较快的页面因为 JavaScript 和 CSS 有机会被浏览器缓存起来。对于内联的情况由于 HTML 文档通常不会被配置为可以进行缓存的所以每次请求 HTML 文档都要下载 JavaScript 和 CSS。所以如果 JavaScript 和 CSS 在外部文件中浏览器可以缓存它们HTML 文档的大小会被减少而不必增加 HTTP 请求数量。 使用字体图标 iconfont 代替图片图标 图片会增加网络请求次数从而拖慢页面加载时间iconfont可以很好的缩放并且不会添加额外的请求 首屏加载优化 使用骨架屏或者动画优化用户体验资源按需加载首页不需要的资源延迟加载 减少重绘和回流 增加多个节点使用documentFragment不是真实dom的部分不会引起重绘和回流使用 visibility 替换 display: none 因为前者只会引起重绘后者会引发回流改变了布局opacity 代替 visiabilityvisiability会触发重绘paint但opacity不会。把 DOM 离线后修改比如先把 DOM 给 display:none (有一次 Reflow)然后你修改 100 次然后再把它显示出来
JS优化
使用事件委托防抖和节流尽量不要使用JS动画 css3动画和canvas动画都比JS动画性能好 多线程 复杂的计算开启webWorker进行计算避免页面假死 计算结果缓存 减少运算次数比如vue中的computed
图片优化
雪碧图 借助减少http请求次数来进行优化 图片懒加载 在图片即将进入可视区域的时候进行加载判断图片进入可视区域 IntersectionObserver 的API
const observer new IntersectionObserver((entries, observer) {entries.forEach(entry {if (entry.isIntersecting) { // console.log(元素进入视口);} else {// console.log(元素离开视口);}});});// 添加监听targetElement监听的目标元素observer.observe(targetElement);// 要取消观察的目标IntersectionObserver.unobserve(targetElement);使用CSS3代替图片 有很多图片使用 CSS 效果渐变、阴影等就能画出来这种情况选择 CSS3 效果更好 图片压缩 压缩方法有两种 通过在线网站进行压缩 通过 webpack 插件 image-webpack-loader。它是基于 imagemin 这个 Node 库来实现图片压缩的。 使用渐进式jpeg 使用渐进式jpeg会提高用户体验 参考文章 使用 webp 格式的图片 webp 是一种新的图片文件格式它提供了有损压缩和无损压缩两种方式。在相同图片质量下webp 的体积比 png 和 jpg 更小。
webpack打包优化
缩小loader 匹配范围 优化loader配置test、include、exclude三个配置项来缩⼩loader的处理范围推荐include
include: path.resolve(__dirname, ./src),抽离css 借助mini-css-extract-plugin:本插件会将 CSS 提取到单独的文件中为每个包含 CSS 的 JS 文件创建一个 CSS 文件并且支持 CSS 和 SourceMaps 的按需加载 代码压缩 JS代码压缩 mode:production使用的是terser-webpack-plugin CSS代码压缩 css-minimizer-webpack-plugin Html文件代码压缩 html-webpack-plugin和html-minifier-terser 文件大小压缩 对文件的大小进行压缩减少http传输过程中宽带的损耗 图片压缩 一般来说在打包之后一些图片文件的大小是远远要比 js 或者 css 文件要来的大所以图片压缩较为重要
module: {rules: [{test: /.(png|jpg|gif)$/,use: [{loader: file-loader,options: {name: [name]_[hash].[ext],outputPath: images/,}},{loader: image-webpack-loader,options: {// 压缩 jpeg 的配置mozjpeg: {progressive: true,quality: 65},// 使用 imagemin**-optipng 压缩 pngenable: false 为关闭optipng: {enabled: false,},// 使用 imagemin-pngquant 压缩 pngpngquant: {quality: 65-90,speed: 4},// 压缩 gif 的配置gifsicle: {interlaced: false,},// 开启 webp会把 jpg 和 png 图片压缩为 webp 格式webp: {quality: 75}}}]},]
} Tree shaking 去除死代码 Tree Shaking 是一个术语在计算机中表示消除死代码依赖于ES Module的静态语法分析不执行任何的代码可以明确知道模块的依赖关系 代码分离 将代码分离到不同的bundle中之后我们可以按需加载或者并行加载这些文件默认情况下所有的JavaScript代码业务代码、第三方依赖、暂时没有用到的模块在首页全部都加载就会影响首页的加载速度代码分离可以分出更小的bundle以及控制资源加载优先级提供代码的加载性能这里通过splitChunksPlugin来实现该插件webpack已经默认安装和集成只需要配置即可默认配置中chunks仅仅针对于异步async请求我们可以设置为initial或者all splitChunks主要属性有如下
module.exports {...optimization:{splitChunks:{chunks:all}}
}配置如下 Chunks对同步代码还是异步代码进行处理 minSize 拆分包的大小, 至少为minSize如何包的大小不超过minSize这个包不会拆分 maxSize 将大于maxSize的包拆分为不小于minSize的包 minChunks被引入的次数默认是1 多线程打包提升打包速度 happypack
const HappyPack require(happypack);
const os require(os);
const happyThreadPool HappyPack.ThreadPool({ size: os.cpus().length });
module.exports { // ... module: { rules: [ { test: /\.js$/, use: { loader: happypack/loader, options: { id: js } } }] }, plugins: [ new HappyPack({ id: js, threadPool: happyThreadPool, loaders: [babel-loader] }) ] };- thread-loader vue优化
v-for添加key路由懒加载 import引入 第三方插件按需引入合理使用computed和watch 缓存依赖实时监听 v-for的同时避免使用v-ifdestory时销毁事件比如addEventListener添加的事件、setTimeout、setInterval、bus.$on绑定的监听事件等
react优化
map循环展示添加key路由懒加载第三方插件按需引入使用scumemo或者pureComponent避免不必要的渲染合理使用useMemo、memo、useCallback 他们三个的应用场景都是缓存结果当依赖值没有改变时避免不必要的计算或者渲染。 useCallback 是针对函数进行“记忆”的当它依赖项没有发生改变时那么该函数的引用并不会随着组件的刷新而被重新赋值。当我们觉得一个函数不需要随着组件的更新而更新引用地址的时候我们就可以使用 useCallback 去修饰它。React.memo 是对组件进行 “记忆”当它接收的 props 没有发生改变的时候那么它将返回上次渲染的结果不会重新执行函数返回新的渲染结果。React.useMemo是针对 值计算 的一种“记忆“当依赖项没有发生改变时那么无需再去计算直接使用之前的值对于组件而言这带来的一个好处就是可以减少一些计算避免一些多余的渲染。当我们遇到一些数据需要在组件内部进行计算的时候可以考虑一下 React.useMemo
二、webworker中为什么能提升js执行的性能 Web Worker 为 JavaScript 创造了多线程环境允许 JS 主线程创建 Worker 子线程将一些任务分配给后者运行。这样做就能充分发挥多核 CPU 主机的优势让两个线程并行执行 1. 独立线程每个 Web Worker 运行在自己的线程中拥有独立的 JavaScript 执行环境不会阻塞主线程。 2. 消息传递主线程和 Web Worker 之间通过消息传递进行通信。主线程可以向 Web Worker 发送消息Web Worker 可以向 主线程发送消息。这种通信是异步的不会阻塞任何线程。 3. 无 DOM 访问Web Workers 无法直接访问主线程中的 DOM 元素因为它们在不同的上下文中运行。 使用场景 图像处理和滤镜应用数据分析和计算实时通信和聊天应用大规模数据可视化异步加载资源如脚本和样式表 在主线程运行的同时Worker 线程在后台运行两者互不干扰。一些计算密集型或高延迟的任务被 Worker 线程负担了主线程通常负责 UI 交互就会很流畅 Worker 线程会在计算任务完成时通过特定的通信方式将结果返回给主线程。 注意 Worker 子线程是浏览器开的完全受主线程控制。即 Web Worker 是浏览器提供的JS 并不提供JS 还是单线程的
// 在主线程和myworker内都是通过postMessage()方法发送数据监听message事件接收数据
// 主线程内
var myWorker new Worker(work.js);
myWorker.onmessage function (event) { // 接收来自子线程内部的数据console.log(Received message event.data);doSomething();
}
const dataToProcess [1, 2, 3, 4, 5];
myWorker.postMessage(dataToProcess); // 向myworker内部发送数据// myWorker文件内容子线程
addEventListener(message, function (e) { // 接收来自主线程数据const result processData(e.data); // 调用方法移交处理数据的逻辑postMessage(result); // 将处理的好结果返回给主线程
}, false); // false指定事件句柄在冒泡阶段执行function processData(data) {// 处理数据的逻辑return data.map(item item * 2);
}三、微前端 为什么选择微前端 技术栈无关 主框架不限制接入应用的技术栈微应用具备完全自主权 独立开发、独立部署 微应用仓库独立前后端可独立开发部署完成后主框架自动完成同步更新 增量升级 在面对各种复杂场景时我们通常很难对一个已经存在的系统做全量的技术栈升级或重构而微前端是一种非常好的实施渐进式重构的手段和策略 独立运行时 每个微应用之间状态隔离运行时状态不共享 为什么不用iframe 隔离性无法被突破导致应用间上下文无法被共享随之带来的开发体验、产品体验的问题。 url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用UI 不同步DOM 结构不共享,想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框同时我们要求这个弹框要浏览器居中显示还要浏览器 resize 时自动居中全局上下文完全隔离内存变量不共享。iframe 内外系统的通信、数据同步等需求主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程 选择qiankun的理由 成熟稳定qiankun 是由 Ant Group蚂蚁金服团队开发和维护的微前端框架已经在蚂蚁金服内部和众多大型项目中广泛应用并经过验证。它经过了长期的发展和迭代具有较高的稳定性和可靠性。 功能丰富qiankun 提供了完整的微前端解决方案包括应用的注册、加载、通信、生命周期管理等功能。它具有独立运行、集成部署、按需加载等特性可以满足复杂的微前端架构需求。 灵活性qiankun 支持多种前端框架如 React、Vue、Angular的应用集成不限制开发团队使用的具体技术栈。它提供了统一的应用接入和管理方式使得不同团队开发的应用可以无缝集成实现共享组件和状态管理等。 性能优化qiankun 在应用加载和通信方面进行了优化采用了基于浏览器标准的沙箱隔离机制避免了应用之间的冲突和影响。它支持应用的按需加载减少了初始加载时的资源开销提高了整体性能和用户体验。 社区支持和生态系统qiankun 拥有活跃的社区和广泛的生态系统有大量的文档、教程和示例可供参考。它也得到了开源社区的认可和贡献可以获得及时的技术支持和问题解答。 qiankun的原理 registerMicroApps 注册子应用 import { registerMicroApps, start } from qiankun;registerMicroApps([{name: vue app,entry: http://localhost:27272,contrainer: #yourContainer,activeRule: /yourActiveRule}])// 通过 onGlobalStateChange 来通讯import { initGlobalState } from qiankun;const state {baiduinit: window,abc: 456}// 初始化通信池const actions initGlobalState(state);// 监听通讯池的变化actions.onGlobalStateChange((state, prev) {// state: 变更后的状态; prev 变更前的状态console.log(state, prev);});qiankun不足之处样式隔离 当我们在主应用中引入了多个子应用时子应用的样式会互相影响这是因为子应用的样式是全局的而 qiankun 默认情况下并没有对子应用的样式进行隔离 解决方案通过 scoped css 来实现应用的样式隔离
import { start, loadMicroApp } from qiankun
// 方法1启动添加experimentalStyleIsolation
start({sandbox: {experimentalStyleIsolation: true,}
})// 方法2手动添加
loadMicroApp(reactApp, {sandbox: {experimentalStyleIsolation: true,}
})静态资源引用问题 静态资源再子应用中相对路径引用主应用下可能无法读取到 微应用打包之后css中字体和背景图片404 原因是 qiankun 将外链样式改成了内联样式但是字体文件和背景图片的加载路径是相对路径。 而 css 文件一旦打包完成就无法通过动态修改 publicPath 来修正其中的字体文件和背景图片的路径解决方案 小图base64位大图上传资源服务器其他资源同样使用绝对路径引用。 所有图片等静态资源上传至 cdncss 中直接引用 cdn 地址推荐借助 webpack 的 url-loader 将字体文件和图片打包成 base64适用于字体文件和图片体积小的项目 通信数据初始化覆盖问题 使用initGlobalState初始化定义一级属性已经定义过的数据注意不要书写为如下 // initGlobalState() 的写法会覆盖掉已经初始化定义的一级属性const { setGlobalState } initGlobalState()解决方案在统一的位置定义一级属性将通信方法导出后挂载到window上供全局调用 const { setGlobalState } initGlobalState({demoData: ,demo2Data: })window.$setGlobalState setGlobalState// 需要通信更新更新demoData处调用示例window.$setGlobalState({demoData: this is demo})静态资源跨域问题 问题配置的子应用报跨域错误 解决方案由于 qiankun 是通过 fetch 去获取微应用的引入的静态资源的所以必须要求这些静态资源支持跨域。 如果是自己的脚本可以通过开发服务端跨域来支持。如果是三方脚本且无法为其添加跨域头可以将脚本拖到本地由自己的服务器 serve 来支持跨域。