三 兼容 和 性能优化

203 阅读11分钟

一:你能说一下项目中遇到的兼容问题吗?

一.css部分:

1. 在ios键盘中首字母大写的问题?
                <input type="text" autocapitalize='off'>
2. ios日期转换NAN问题
                具体就是,new Date('2020-11-12 00:00:00')在ios中会为NAN
                解决方案:用new Date('2020/11/12 00:00:00')的日期格式,或者写个正则转换
3. 在移动端使用click事件有300ms延迟的问题
                禁止双击缩放===》meta:user-scalabel=no
4. 	移动端touch事件有穿透(点透)的问题,怎么解决?
                4.1 阻止默认行为 : e.preventDefault();
                4.2 fastclick.js
5. 安卓部分版本input的placeholder偏上
                input{
                         line-height:normal;
                }
6.元素设置1px 实际比1px 大,设置一下缩放 transform:Scale(/2

image.png

image.png 2. h5低版本标签浏览器不兼容 html5shiv.js

二:js部分:
1. click300ms 延时问题(因为移动端浏览器会有一些默认的行为,比如双击缩放、双击滚动,用户对页面进行操作的时候,移动端浏览器会优先判断用户是否要触发默认的行为,所以就会有 `300ms` 的延迟)
解决:fastclick.js 
**原理**`FastClick``touchend` 阶段调用 `event.preventDefault`,然后通过 `document.createEvent` 创建一个 `MouseEvents`,然后通过 `eventTarget.dispatchEvent` 触发对应目标元素上绑定的 `click` 事件。

二 项目性能优化环节:

   新答案:
   css优化:
       1.代码去重:把相同功能的样式部分提取出来
       2.代码压缩:将各种换行 空格压缩起来
       3.雪碧图压缩:一张图片做出1个按钮的3种状态,如果从后端请求,就可以减少请求
       4.css文件合并压缩:将多个css文件压缩一起请求过来
   js优化:
       1.尽可能少声明变量
       2.尽可能少使用闭包,浪费资源
       3.尽可能少使用for in 循环
       4.尽量少使用dom操作,比如用for循环生成很多个dom节点,就会卡死, -->用变量,就像jQuery把所有东西都以变量存在数组里了
       5.减少代码重用,封装成函数调用
       6.代码压缩、文件合并

一:你在前端项目做过哪些性能优化

新答案:加载时的优化:
     0. 减少http请求(需要跟后端沟通),一个完整的http请求需要经历的过程说一下,请求较多时直接体现在了消耗性能上面,这就是为什么要将多个小文件合并成一个大文件,从而减少http请求次数的原因。
     场景:搜索课程的时候,去判断搜索内容是否和当前搜索的内容一致,如果一致就不再重新请求。
     
     2. 使用服务端渲染,我们知道,当客户端渲染时,是获取html文件,根据需要下载js文件,运行文件生成dom再渲染,这个过程在无形之中会拖慢性能,那么服务端渲染又是怎么一回事呢,就是服务器端返回html文件,客户端只需要只需要解析HTML文件即可
     3. 静态资源使用CDN,CDN就是内容分发网络,他是一组分布在多个不同地理位置的web服务器,我们都知道,当服务器离我们越远时,延迟越高,CDN就是为了解决这个问题,在多个位置部署服务器,让用户李服务器更近,从而缩短请求时间,CDN的原理
     4. CSS写在头部,JS写在底部,所有放在header标签里的css和js文件都会堵塞渲染,如果这些css和js需要加载和解析很久的话,页面就空白了,所以js要放在底部,等html解析完了再加载js文件,
     为什么css文件要放在头部,因为先加载html再加载css,会让用户在第一时间看到的页面是没有样式的,为了避免这种情况的发生就要将css文件放在头部了,
     另外js文件也不是不可以放在头部,只要给script标签加上default属性就可以了
     5.  字体图标代替图片图标,字体图标就是将图标制作成一个字体,使用时就跟字体一样可以设置属性,例如font-sizecolor等非常方便,并且字体图标是矢量图,不会失真,还有一个优点就是生成的文件特别小
     6.利用缓存不重复加载相同的资源,为了避免用户访问网站都得请求文件,可以添加express来控制这个行为,express设置了一个时间,只要在这个时间之前,浏览器都不会请求文件,而是直接使用缓存
     7. 图片优化,分为几个小点,
         7.1首先是图片延迟加载,就是在页面中先不给图片设置路径,只有图片出现在浏览器的可视区域时才去加载真正的图片,这就是延迟加载,对于图片很多的网站来说,一次性加载全部图片,会对用户体验造成很大的影响,所以需要使用图片延迟加载
         7.2 第二个就是使用雪碧图
         7.3 小图片或颜色单一的图片可以使用base64内联
          base64内面如何转换 
              1、将字符串通过Buffer.from获取buffer,并将buffer中的每个16的buffer字节转为2进制 
              2、将所有二进制拼接在一起,6个一组进行划分,在前面补00,凑成8位二进制
                   将每个字节转为二进制1. (0xe5).toString(2); // 11100101 
              3、将新的二进制转换成10进制 ,parseInt('00001000', 2); // 二进制变为10进制 8 
              4、在base64集合中分别通过10进制下标取出,并链接
              
    8. 通过webpack按需加载代码,懒加载或按需加载是一种很好的应用网页或应用方式,实际上是先把代码在一些逻辑断点处分离开,然后再某些代码块中完成某些操作后立即引用,或者即将引用另一种新的代码块,这样加快了应用的初始加载速度,减轻了总体体积,因为某些代码块可能永远也不会加载
    提取第三方代码,减少es6转es5的冗余代码

运行时的优化:
    1. 减少重绘重排,具体操作就是,js修改样式时,不要直接写样式,而是替换为class类来改变样式,
    再一个就是如果要对dom元素执行一系列的操作,可以将dom元素脱离文档流(float absolute fixed),
    修改完成之后再将它带回文档,推荐使用隐藏元素或文档碎片都能很好的实现这个方案

文档碎片

image.png

    2. 使用事件委托,事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类的所有事件,所有用到按钮的事件,比如鼠标事件,键盘事件都可以使用到事件委托技术,节省内存
    3. 不要覆盖原生方法,因为无论你的代码如何优化都比不上原生方法,因为原生方法是用低级语言写的,并且被编译成机器码,成为浏览器的一部分,当原生方法可用时,尽量使用他们,特别是数学运算和DOM操作
    4. 降低css选择器的复杂性,我们知道浏览器读取选择器遵循的原则,是从选择器的右边到左边读取,所以尽可能的降低css选择器的复杂性
    5. 使用弹性布局flxebox,在早期布局css的方式中,能对元素实行绝对定位,相对定位和浮动定位,而现在有了flex布局,比早期的布局方式来说更有优势,性能比较好,不过弹性布局,他的兼容性还是有一点问题,不是所有浏览器都支持他,所以使用的时候需要谨慎
    6. 用transform和opacity属性来实现动画,在css中这2个属性更新是不会触发重排和重绘的,他们是由合成器单独处理的属性
    


   

image.png

image.png Object.free()双向的变成单向 image.png

旧答案: 
 
一 优化是一个比较大的话题,一般我在做优化的时候都会借助一些工具:说两款(提前了解)
1. Lighthouse 详细的内容,可以去参考git:https://github.com/GoogleChrome/lighthouse 
2. 测试网站 https://www.webpagetest.org/

二 具体的优化有这么几类:看这篇文章(三、前端性能优化):尽量把共性的多说一些(自己去背吧)https://juejin.cn/post/6979873370733183013
1. 加载优化
        
        1. 压缩合并
        2. 代码分割(code spliting),可以基于路由或动态加载
        3. 第三方模块放在CDN
        4. 大模块异步加载,例如: Echarts,可以使用require.ensure,在加载成功后,在显示对应图表
        5. 小模块适度合并,将一些零散的小模块合并一起加载,速度较快
        6. 可以使用pefetch预加载,在分步场景中非常适合
2. 图片优化
    1. 小图使用雪碧图,iconFont,base64内联
    1.1 大图用 file-loader 单独打包到img文件夹发送请求 防止页面首次渲染太慢
    1.2 base64内面如何转换
        1、将字符串通过Buffer.from获取buffer,并将buffer中的每个16的buffer字节转为2进制
        2、将所有二进制拼接在一起,6个一组进行划分,在前面补00,凑成8位二进制1.  \
         // 将每个字节转为二进制1.  (0xe5).toString(2); // 11100101
        3、将新的二进制转换成10进制  ,parseInt('00001000', 2); // 二进制变为10进制 8
        4、在base64集合中分别通过10进制下标取出,并链接
    2. 图片使用懒加载
    3. webp代替其他格式
    4. 图片一定要压缩
    5. 可以使用的img的srcset,根据不同分辨率显示不同尺寸图片,这样既保证显示效果,又能节省带宽,提高加载速度

3. css优化
    1. css写在头部
    2. 避免css表达式
    3. 移除空置的css规则
    4. 避免行内style样式

4. js优化
    1. js写在body底部
    2. js用defer放在头部,提前加载时间,又不阻塞dom解析
    3. script标签添加crossorigin,方便错误收集

5. 渲染优化
    1. 尽量减少回流和重绘 ,回流一定会出发重绘
    回流:窗口大小改变,文字大小 脚本操作dom
    重绘:改元素属性的颜色
    
    1.1 用变量缓存dom样式,不要频繁读取
    1.2 通过DocumentFragment或innerHTML批量操作dom
    1.3 dom隐藏,或复制到内存中,类似virtual dom,进行修改,完成后再替换回去
    1.4 动画元素一定要absolute,脱离文档流,不影响其他元素。动画不要用left,top等操作,要使用transform和opacity,同时开启渲染层(will-change或translate3d(0,0,0))
    1.5 动画尽量用requestAnimationFrame,不要用定时器
    1.6 移动端硬件加速,触发GPU渲染,还是translate3d(0,0,0)

6. 首屏优化
    原则:显示快,滚动流畅,懒加载,懒执行,渐进展现
    1. 代码分离,将首屏不需要的代码分离出去
    2. 服务端渲染或预渲染,加载完html直接渲染,减少白屏时间
    3. DNS prefetch,使用dns-prefetch减少dns查询时间,PC端域名发散,移动端域名收敛
    4. 减少关键路径css,可以将关键的css内联,这样可以减少加载和渲染时间

7. 打包优化(主要是webpack优化)
    1. 拆包 externals dllPlugin
    2. 提取公共包 commonChunkPlugin或splitChunks
    3. 缩小范围 各种loader配置include和exclude,noParse跳过文件
    4. 开启缓存 各种loader开启cache
    5. 多线程加速 happypack或thead-loader
    6. tree-shaking ES模块分析,移除死代码
    7. Scope Hoisting ES6模块分析,将多个模块合并到一个函数里,减少内存占用,减小体积,提示运行速度

8.webpack长缓存优化
    1. js文件使用chunkhash,不使用hash
    2. css文件使用contenthash,不使用chunkhash,不受js变化影响
    3. 提取vendor,公共库不受业务模块变化影响
    4. 内联webpack runtime到页面,chunkId变化不影响vendor
    5. 保证module Id稳定,不使用数字作为模块id,改用文件内容的hash值,使用HashedModuleIdsPlugin,模块的新增或删除,会导致其后面的所有模块id重新排序,为避免这个问题
    6. 保证chunkhash稳定,使用webpack-chunk-hash,替代webpack自己的hash算法。webpack自己的hash算法,对于同一个文件,在不同开发环境下,会计算出不用的hash值,不能满足跨平台需求。

8. vue优化
    1. 路由懒加载组件
    2. keep-alive缓存组件,保持原显示状态
    3. 列表项添加key,保证唯一
    4. 列表项绑定事件,使用事件代理(v-for)
    5. v-if和v-for不要用在一个标签上,它会在每个项上进行v-if判断


10. SEO优化
    1. 添加各种meta信息
    2. 预渲染
    3. 服务端渲染