性能优化
网页性能优化可以从哪几方面入手?
提高访问和响应速度->提高用户体验!
第一类是页面级别的优化;第二类则是代码级别的优化。
- 代码优化
- DOM渲染优化
- 事件委托
- 使用文档碎片减少DOM交互次数
- 使用innerHTML
- css硬件加速(GPU加速)
- 缓存DOM节点
- 采用基于vue/react数据影响视图的模式
- 分离读写操作
- 动画效果应用到position属性值为absolute或fix的元素上(脱离文档流)。
- 慎用with(增加了查找作用域的消耗时间)
- 避免使用 eval和 Function(将源代码转换成可执行代码很消耗资源)
- 算法优化
- js和css的引用位置
- 将外部脚本置底(防止阻塞其他资源的加载)
- css引用放在HEAD中(加快渲染,减少页面空白时间)
- DOM渲染优化
- 浏览器
- 减少HTTP请求
- 使用缓存
- 请求资源的合并
- 避免重定向(增加多余请求)
- 缩短请求时间
- 减少DNS查找
- 减少重复代码
- 请求资源的压缩
- 网络安全
- 减少HTTP请求
- 资源加载
- 懒加载(按需加载)
- 资源压缩(减小体积)
- CDN(本质仍然是缓存)
For of 和 for (let i = 0; i < ...) 哪种写法性能更高?为什么?
for > for-of > for-in
for-in循环除了遍历数组元素以外,还会遍历自定义属性。
for-of循环不会循环对象的key,只会循环出数组的value,因此for-of不能循环遍历普通对象。
for-of和for-in的key是String类型,有转换过程,开销比较大,但是for循环的i是Number类型,开销较小。
不过for-of语法在内存占用上也有一定的优势。
模块化
了解过js的模块化吗?node如何实现模块化?ES6的模块化又是什么?
模块化就是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块。
Nodejs通过 CommonJs 实现模块化。在 CommonJs 的模块化规范中,每一个文件就是一个模块,拥有自己独立的作用域、变量、以及方法等,对其他的模块都不可见。每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。require 方法用于加载模块。
ES6语法规范中,在语言层面上定义了ES6模块化规范,是浏览器与服务端通用的模块化开发规范。ES6模块化中每个js文件都是一个独立的模块,导入模块成员使用import关键字,暴露模块成员使用export关键字。
webpack工作流
-
初始化参数
从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
-
开始编译
用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
-
确定入口
根据配置中的 entry 找出所有的入口文件;
-
编译模块
从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
-
完成模块编译
在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
-
输出资源
根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
-
输出完成
在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
微前端
讲讲什么是微前端,微前端解决什么问题?
- 什么是微前端
微前端就是将不同的功能按照不同的维度拆分成多个子应用,通过主应用来加载这些子应用。
核心在于拆,拆完后再合。
-
解决什么问题
- 不同团队间开发同一个应用技术栈
- 每个团队都可以独立开发,独立部署
- 项目中还需要应用老的代码
将一个应用划分成若干个子应用,将子应用打包成一个个的lib。当路径切换时加载不同的子应用,这样每个子应用都是独立的,技术栈也不用做限制,从而解决了前端协同开发的问题。
-
与iframe区别
如果使用iframe, iframe中的子应用切换路由时用户刷新页面,路由状态丢失,无法实现很多功能。
浏览器机制
浏览器执行js的时候是否会阻塞html的解析?为什么?
在构建DOM树的时候,当遇到JS元素时,HTML解析器就会将控制权转让给JavaScript引擎线程,该线程会阻断HTML解析器的运行,当js加载并且执行完毕后,JavaScript引擎线程会将控制权还给HTML解析器,让其去继续构建dom树。
现在有十个相同大小的css文件,加载一个要n秒,加载10个要多少秒?js呢?
Chrome 中所有 link 一开始会同时建立连接,但每次只并行加载 6 个资源,其余资源会被延迟加载。所以应该是2n秒。
JS 都是串行加载,所以需要10n秒。
浏览器多线程机制
- GUI渲染线程
负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
- JS引擎线程
也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
JS引擎线程负责解析Javascript脚本,运行代码。
JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序。
- 事件触发线程
归属于浏览器而不是JS引擎,用来控制事件循环。(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助)
当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中。 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。
- 定时触发器线程
setInterval与setTimeout所在线程。
浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确) 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
- 异步http请求线程
XMLHttpRequest在连接后是通过浏览器新开一个线程请求。 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
浏览器缓存如何实现
- 服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。
- 304是HTTP状态码,服务器用来标识这个文件没修改,不返回内容,浏览器在接收到个状态码后,会使用浏览器已缓存的文件。
Vue
Vue的生命周期
四个阶段
- 初始化阶段
new Vue()到created阶段,在Vue.js实例上初始化一些属性、事件以及响应式数据。
- 模版编译阶段
created到beforeMount阶段,将模版编译为渲染函数。
- 挂载阶段
beforeMount到mounted阶段,Vue.js会将模版渲染到指定的dom元素中。在挂载的过程中,Vue.js会开启watcher来持续追踪依赖的变化。
- 卸载阶段
调用$destory()后,Vue.js将自身从父组件中移除,取消实例上所有依赖的追踪并且移除事件监听器。
执行异步队列之前为什么要根据id排序呢?
flushSchedulerQueue中首先会将队列中所有的 watcher 按照 id 进行排序,之后再遍历队列依次执行其中的 watcher,排序的原因是要保证 watcher 按照正确的顺序执行(watcher 之间的数据是可能存在依赖关系的,所以有执行的先后顺序,可以看下 watcher 的初始化顺序)。此时的 flushSchedulerQueue 已经通过 nextTick(flushSchedulerQueue) 变成了异步执行,这样做的目的是在一个事件循环(clickHandler)中让 flushSchedulerQueue 只执行一次,避免多次执行、渲染。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!