- Автор: Чен Даютоу
- Первый адрес:GitHub.com/Крис А Чан/Есть…
- Описание: Рекорд обучения Рыбьей головы.
согласно сГруппа производительности W3CВнедрение более 50мс - долгая задача.
Изображение изОцените производительность с помощью моделей RAIL
Согласно приведенному выше рисунку мы можем знать, что когда задержка превышает 100 мс, пользователь почувствует небольшую задержку.
Итак, чтобы избежать этой ситуации, мы можем использовать две схемы, одна из которыхWeb Worker, другойРазделение времени.
Web Worker
Все мы знаем, что JS однопоточный, поэтому при выполнении длинных задач легко вызвать состояние приостановленных страниц.Хотя мы можем ставить задачи в очередь задач и выполнять их асинхронно, сути это не меняет Дж.С.
Поэтому для того, чтобы изменить эту ситуацию,whatwgвыпускатьWeb Workers.
Конкретная грамматика не будет объяснена, заинтересованная детская обувь может проверитьMDN Web Worker.
мы можем посмотреть на использованиеWeb Worker
После эффекта оптимизации:
const testWorker = new Worker('./worker.js')
setTimeout(_ => {
testWorker.postMessage({})
testWorker.onmessage = function (ev) {
console.log(ev.data)
}
}, 5000)
// worker.js
self.onmessage = function () {
const start = performance.now()
while (performance.now() - start < 1000) {}
postMessage('done!')
}
Код и скриншоты взяты изСделайте ваши веб-страницы более плавными
Разделение времени
Time slicing — широко используемое техническое решение, суть которого состоит в том, чтобы разбивать длинные задачи на задачи с коротким временем выполнения, а затем выполнять их одну за другой.
Эта концепция очень полезна для нашей ежедневной оптимизации производительности.
Например, когда нам нужно сразу вставить на страницу длинный список (конечно, обычно в этом случае мы будем использовать для этого пагинацию).
Если мы используем концепцию квантования времени для достижения этой функции, мы можем использоватьrequestAnimationFrame
+DocumentFragment
По поводу этих двух API я тоже не буду давать подробного описания, если вам интересно, вы можете ознакомиться с ними.MDN requestAnimationFrameа такжеMDN DocumentFragment.
Вот две демонстрации, вы можете сравнить беглость:
Не использовать разделение времени:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
let list = document.querySelector('.list')
let total = 100000
for (let i = 0; i < total; ++i) {
let item = document.createElement('li')
item.innerText = `我是${i}`
list.appendChild(item)
}
</script>
Используйте разделение времени:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
let list = document.querySelector('.list')
let total = 100000
let size = 20
let index = 0
const render = (total, index) => {
if (total <= 0) {
return
}
let curPage = Math.min(total, size)
window.requestAnimationFrame(() => {
let fragment = document.createDocumentFragment()
for (let i = 0; i < curPage; ++i) {
let item = document.createElement('li')
item.innerText = `我是${index + i}`
fragment.appendChild(item)
}
list.appendChild(fragment)
render(total - curPage, index + curPage)
})
}
render(total, index)
</script>
Я не делал слишком много оценок, но, судя по визуальному опыту пользователя, первое решение, которое я просто хочу обновить несколько раз, и при скольжении вниз также возникает явление белого экрана.
В дополнение к приведенной выше схеме генерации DOM мы также можем использовать Web Api.requestIdleCallback
и API ES6Generator]
реализовать.
Не буду много вводить, вы можете ознакомиться с подробными правиламиMDN requestIdleCallbackтак же какMDN Generator.
Конкретная реализация выглядит следующим образом:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
function gen(task) {
requestIdleCallback(deadline => {
let next = task.next()
while (!next.done) {
if (deadline.timeRemaining() <= 0) {
gen(task)
return
}
next = task.next()
}
})
}
let list = document.querySelector('.list')
let total = 100000
function* loop() {
for (let i = 0; i < total; ++i) {
let item = document.createElement('li')
item.innerText = `我是${i}`
list.appendChild(item)
yield
}
}
gen(loop())
</script>
использованная литература
- web-performance
- Measure Performance with the RAIL Model
- Сделайте ваши веб-страницы более плавными
- Высокопроизводительный внешний рендеринг 100 000 фрагментов данных (временной разрез)
постскриптум
Если вам нравится обсуждать технологии или у вас есть какие-либо комментарии или предложения по этой статье, вы можете добавить друзей Yutou в WeChat для совместного обсуждения.Конечно, Yutou также надеется поговорить с вами о жизни, хобби и поболтать. WeChat ID Fish Head: krisChans95 Вы также можете отсканировать код, чтобы подписаться на официальный аккаунт и подписаться на более интересный контент.