五、资源优化
1、资源的压缩与合并
* 为什么要压缩&合并
- 减少http请求数量
- 减少请求资源的大小
* html压缩
- 使用在线工具进行压缩
- 使用html-minifier等npm工具
* css压缩
- 使用在线工具进行压缩
- 使用clean-css等npm工具
* js压缩与混淆
- 使用在线工具进行压缩
- 使用webpack对js在构建时压缩
* css js文件合并
- 若干小文件,maybe...
- 无冲突,服务相同的模块,ok
- 优化加载,no!
2、图片优化的方案
* 图片格式比较
- jpeg/jpg的优点
- jpeg/jpg的使用场景
- jpeg/jpg的缺陷
- png的优点
- png的使用场景
- png的缺陷
- webp的优点
- 支持webp的浏览器
3、图片优化-图片加载优化
* 图片的懒加载(lazy loading)
- 原生的图片懒加载方案
- 第三方图片懒加载方案
~ verlok/lazyload
~ yall.js
~ blazy
* 使用渐进式图片
* 渐进式图片的优点和不足
* 渐进式图片的解决方案
- progressive-image
- libjpeg
- jpeg-recompress
- imagemagick
- jpegtran
- imagemin
* 使用响应式图片
- srcset属性的使用
- sizes属性的使用
- picture的使用
4、字体优化
* 什么是foit和fout
- 字体未下载完成时。浏览器隐藏或自动降级,导致字体闪烁
- flash of invisible text
- flash of unstyled text
* 使用font-display
- auto
- block
- swap
- fallback
- optional
* 使用css font loading api
* 使用ajax + base64
- 解决兼容性问题
- 缺点:缓存问题
六、构建优化
1、约定优于配置(convention over configuration)
* tree-shaking
- 上下文未用到的代码(dead code)
- 基于es6 import export
- package.json中配置sideEffects
- 至于babel默认配置的影响
* js压缩
- webpack4后引入uglifyjs-webpack-plugin
- 支持es6替换为terser-webpack-plugin
- 减少js文件体积
* 作用域提升
- 代码体积减少
- 提高执行效率
- 同样注意babel的modules配置
* babel7优化配置
- 在需要的地方引入polyfill
- 辅助函数的按需引入
- 根据目标浏览器按需转换代码
2、webpack的依赖优化
* noparse
- 提高构建速度
- 直接通知webpack忽略较大的库
- 被忽略的库不能有import,require,define的引入方式
* dllplugin
- 避免打包时对不变的库重复构建
- 提高构建速度
3、基于webpack的代码拆分(code splitting)
* 代码拆分做什么
- 把单个bundle文件拆分成若干小bundles/chunks
- 缩短首屏加载时间
* webpack代码拆分的方法
- 手工定义入口
- splitChunks提取公有代码,拆分业务代码与第三方库
- 动态加载
4、基于webpack的资源压缩(minification)
* minification
- terser压缩js
- mini-css-extract-plugin压缩css
- htmlwebpackplugin-minify压缩html
5、基于webpack的资源持久化缓存
* 持久化缓存方案
- 每个打包的资源文件有唯一的hash值
- 修改后只有受影响的文件hash变化
- 充分利用浏览器缓存
6、基于webpack的应用大小监测与分析
* 监测与分析
- stats分析与可视化图
- webpack-bundle-analyzer进行体积分析
- speed-measure-webpack-plugin速度分析
7、react按需加载的实现方式
* react按需加载
- react router基于webpack动态引入
- 使用reloadable高级组件
七、传输加载优化
1、启用压缩gzip
* gzip
- 对传输资源进行体积压缩,可高达90%
- 如何配置nginx启用gzip
2、启用keepalive
* keep alive
- 一个持久的tcp连接,节省了连接创建时间
- nginx默认开启keep alive
3、http资源缓存
* http缓存
- 提高重复访问时资源加载的速度
- cache-control/expires
- last-modified + if-modified-since
- etag + if-none-match
4、service workers
* service workers作用
- 加速重复访问
- 离线支持
* service workers原理
* service workers注意
- 延长了首屏时间,但页面总加载时间减少
- 兼容性
- 只能在localhost或https下使用
5、http/2的提升
* http/2优势
- 二进制传输
- 请求响应多路复用
- server push
* 搭建http/2服务
- https
- 适合较高的请求量
6、服务端渲染ssr
* ssr的好处
- 加速首屏加载
- 更好的seo
* 客户端渲染 vs 服务端渲染
* react ssr
- 基于next.js实现ssr
* 是否使用ssr?
- 架构-大型,动态页面,面向公众用户
- 搜索引擎排名很重要
八、前沿优化解决方案
1、拯救移动端图标-svg
* 从png到iconfont
- 多个图标 -> 一套字体,减少获取时的请求数量和体积
- 矢量图形,可伸缩
- 直接通过css修改样式(颜色,大小等)
* 从iconfont到svg
- 保持了图片能力,支持多色彩
- 独立的矢量图形
- xml语法,搜索引擎seo和无障碍读屏软件读取
2、使用flexbox优化布局
* flexbox的优势
- 更高性能的实现方案
- 容器有能力决定元素的大小,顺序,对齐,间隔等
- 双向布局
* flexbox的使用
- flex container容器
- flex items元素
3、优化资源加载的顺序
* 资源优先级
- 浏览器默认安排资源加载优先级
- 使用preload,prefetch调整优先级
* preload和prefetch适用场景
- preload:提前加载较晚出现,但对当前页面非常重要的资源
- prefetch:提前加载后继路由需要的资源,优先级低
4、预渲染页面
* 预渲染的作用
- 大型单页应用的性能瓶颈:js下载+解析+执行
- ssr的主要问题:牺牲ttfb来补救first paint;实现复杂
- pre-rendering打包时提前渲染页面,没有服务端参与
* 使用react-snap
- 配置postbuild
- 使用ReactDOM.hydrate()
- 内联样式,避免明显的fouc(样式闪动)
5、windowing(窗口化)提高列表性能
* 什么是windowing
* windowing的作用
- 加载大列表,大表单的每一行严重影响性能
- lazy loading仍然会让dom变得过大
- windowing只渲染可见的行,渲染和滚动的性能都会提升
* 使用react-window
- 配置一个一维列表list
- 配置一个二维列表grid
- 配置滚动到指定元素
6、使用骨架组件减少布局移动(layout shift)
* skeleton/placeholder的作用
- 占位
- 提升用户感知性能
* 使用react-placeholder
- 预置的placeholders
- 自定义placeholder
九、性能优化问题面试指南
1、web加载&渲染基本原理
* 问题
- 从输入url到页面加载显示完成都发生了什么?
* 分析
- 知识点广,区分度高
- 自己擅长的点可以适当展开
- 渲染过程是重点
* 解答
- ui thread:搜索 or url? -> 搜索引擎 or 请求的站点
- network thread:
- renderer process:
2、首屏加载优化
* 问题
- 什么是首屏加载?怎么优化?
* 分析
- web增量加载的特点决定了首屏性能不会完美
- 过长的白屏影响用户体验和留存
- 首屏(above the fold) -> 初次印象
* 解答
- 首屏:用户加载体验的3个关键时刻
- 测量指标:
~ first contentful paint(fcp)
~ largest contentful paint(lcp)
~ time to interactive(tti)
- 优化
~ 资源体积太大:资源压缩,传输压缩,代码拆分,tree shaking,http/2,缓存
~ 首页内容太多:路由/组件/内容lazy-loading,预渲染/ssr,inline css
~ 加载顺序不合适:prefetch,preload
3、javascript内存管理
* 问题
- js是怎样管理内存的?什么情况会造成内存泄漏?
* 分析
- 内存泄漏严重影响性能
- 高级语言 != 不需要管理内存
* 解答
- 变量创建时自动分配内存,不使用时“自动”释放内存(gc)
- 内存释放的主要问题是如何确定不再需要使用的内存
- 所有的gc都是近似实现,只能通过判断变量是否还能再次访问到
- 局部变量,函数执行完,没有闭包引用,就会被标记回收
- 全局变量,直至浏览器卸载页面时释放
- 引用计数(无法解决循环引用的问题)
- 标记清除
- 避免意外的全局变量产生
- 避免反复运行引发大量闭包
- 避免脱离的dom元素
十、互联网外企offer与立足之道
1、互联网外企offer
* 机会在哪里
* 职业生涯规划
- 技术路线的生命力
- 工作与生活的平衡
- 更大的世界
* 面试准备
- 算法/coding、cs基础知识、系统设计、项目经验
- 英语
- 沟通与表达
2、英语与工作
* 英语是日常输出
- 和国外同事一起做项目
- 和国外同事面对面
- 在海外工作/出差
* 怎么学英语
- 在工作中学习,邮件、电话/视频会议、报告、演示、tb等等
- 日常积累,背单词?no... √读书、美剧、模仿练习
- 参加高效的培训