Shopify C 端页面优化思考
date
Nov 11, 2023
slug
shopify-client-page-optimization-thoughts
status
Published
tags
Shopify
性能优化
summary
C 端项目优化事项
type
Post
FCP
- 在支持 HTTP 2.0 的站点避免使用 bundle 产物,拆分 JS/CSS 代码充分利用 HTTP 2.0 多路复用特性加载资源
- 提取 JS/CSS 关键代码(包括但不限于首屏组件,例如:header 等,布局、reset 等样式代码)将其转为内联代码
- 拆分长任务,避免主线程阻塞
经测试,如果加载重复的 JS/CSS 资源除了当前最新版本的 Firefox 外其他浏览器均能智能识别做到只加载一次
避免主线程阻塞参考
function sleep(delay) {
return new Promise((resolve) => {
setTimeout(resolve, delay)
})
}
async function taskScheduler(_tasks = [], delay = 0) {
if (!_tasks.length) return
const tasks = _tasks.filter((task) => typeof task === 'function')
let deadline = performance.now() + 50
while (tasks.length > 0) {
// Optional chaining operator used here helps to avoid
// errors in browsers that don't support `isInputPending`:
if (
navigator.scheduling?.isInputPending() ||
performance.now() >= deadline
) {
// There's a pending user input, or the
// deadline has been reached. Yield here:
await sleep(delay)
// Extend the deadline:
deadline = performance.now() + 50
// Stop the execution of the current loop and
// move onto the next iteration:
continue
}
// Shift the task out of the queue:
const task = tasks.shift()
// Run the task:
await task()
}
}
参考
TBT
- 连续的 JS Animation 使用
requestAnimationFrame
进行拆分
- 避免重绘、重排。常见处理方法网上都有,这里说一个点,对于需要使用当前视口数据的如:
window.innerWidth
等,可以在进入页面后配合上述taskScheduler
获取后挂载在window
上后续监听窗口变化再更新即可
- liquid/JS 中遍历语法提前返回
- 使用 Partytown 将
content_for_header
代码拆分进入 Service Worker 中执行
1. SW 文件需要放在 HTML 同级下,所以在 Shopify 中需要开发一个 APP 来对 Partytown 资源做代理
2. 由于 SW 的限制,如果某个 APP 需要操作 DOM,则需要将其延迟加载即可不用放入 SW
参考
CLS
- 动态内容设置占位图(三方代码)
- 自有代码考虑将布局相关样式放至内联
SPEED INDEX
- 因为 liquid 模板的特殊性,如果需要获取特定的 page/blog 内容用作显示的话,应避免直接将其内容防止在当前页面中从而导致增加 liquid/html 体积。应使用 Alternate templates 去通过
fetch
动态获取内容将其显示
- 静态内容可以考虑使用 Section Rendering API 去通过
fetch
动态获取内容将其显示,从而达到减轻 liquid/html 体积的目的