Аппаратная среда: MacPro2018 i7+512G жесткий диск 16g память+100M пропускная способность Wi-Fi соединение
Веб-сайт представляет собой веб-сайт электронной коммерции, на этот раз основной оптимизацией является домашняя страница веб-сайта.
Этот оптимизированный веб-сайт основан на vue+nuxtРазработанный nuxt представляет собой фреймворк Vue SSR (он также может генерировать некоторые чистые статические SPA), благодаря оптимизации собственного фреймворка nuxt и рендеринга на стороне сервера производительность веб-сайтов, разработанных на основе nuxt, достигла хорошего уровня. Сетевая среда Wi-Fi, домашняя страница Lighthouse тестовая оценка веб-сайта достигла полного балла.
Lighthouse — это программное обеспечение Google с открытым исходным кодом для тестирования производительности веб-сайта, SEO и многих других показателей. Оно может имитировать различные сетевые среды для сбора комплексных показателей веб-сайта, а также предоставлять некоторые предложения по оптимизации вашего веб-сайта. Используйте его в Chrome-> Инструменты разработки-> Аудит. . Существует много подобных сайтов или инструментов для тестирования производительности, которые вы можете написать до того, какПредставлениеУзнайте в этой статье. Поскольку веб-сайт еще не запущен, реальная производительность пользовательской среды не может быть собрана, поэтому здесь мы собираем только некоторые данные моделирования среды для инструментов производительности среды разработки.
В смоделированной сетевой среде slow4g оценка домашней страницы веб-сайта не так идеальна, что указывает на то, что эта страница все еще имеет много возможностей для оптимизации, затем сначала запишите данные ее индекса производительности и используйте их для сравнения после оптимизации.
code coverage
Другим важным показателем является коэффициент использования кода (покрытие) страницы. Вы также можете проверить этот показатель в инструментах разработки Chrome -> покрытие. Покрытие показывает, сколько js текущей страницы действительно необходимо выполнить на текущей странице. Можно просто использовать компонент библиотеки пользовательского интерфейса, но упаковать всю библиотеку пользовательского интерфейса, вы также можете избежать этого с помощью древовидной акулы (оптимизация производительности javascript для современных браузеров), если вы обнаружите, что ваше покрытие кода не использует относительно большую часть кода, вам следует подумать, возможно ли, что вы упаковали весь код, который вам не нужен. Если вы используете webpack для упаковки js, вы можете использоватьWebpack Bundle Analyzerдля анализа вашего файла пакета js. Его покрытие кода оптимизированной домашней страницы:
Покрытие кода более 50% не является идеальным.Хорошее покрытие кода должно быть близко к 30% или ниже.Конечно, идеальное значение, которое может быть достигнуто в разных средах, должно быть разным, но более 50% должно быть оптимизировано пространство.Уменьшите js, чтобы улучшить покрытие кода
В настоящее время уменьшение размера js в браузере может напрямую повлиять только на производительность вашей текущей страницы.Передаются только файлы js, необходимые для первого экрана, а код остальных js разбивается и загружается в подпакеты или ленивые загрузки, что может напрямую улучшить производительность вашей страницы.
http2
До оптимизации сайт по-прежнему использует протокол http1.0, но есть несколько преимуществ в производительности при использовании http2.
- HTTP2 может использовать одно TCP-соединение для параллельной отправки нескольких запросов.Это самое важное преимущество HTTP2, поскольку современные браузеры ограничивают определенное количество TCP-подключений к серверу, в HTTP1 каждый запрос должен создавать TCP-запрос, Это означает, что количество параллельных запросов, отправляемых на сервер, ограничено количеством TCP-соединений, которые может установить браузер. HTTP2 нужно только установить TCP-соединение с сервером.После того, как соединение установлено, клиент может отправлять запросы параллельно через это соединение, что может не только уменьшить потребление клиента для создания TCP-соединения, но и только сервера необходимо поддерживать одно соединение с клиентом.
- Потоковая передача данных.В HTTP2 данные инкапсулируются и передаются через потоки. В HTTP1 данные передаются в виде простого текста. Преимущество потоковой передачи заключается в том, что она уменьшает размер запросов и ответов и позволяет серверам и клиентам более эффективно анализировать их.
- Заголовки запросов и ответов сжимаются и используются повторно.
После использования HTTP2 это также приносит некоторые проблемы.HTTP2 отправляет запросы через TCP-соединение, так как же он узнает, какой запрос важнее?Resource loading, prioritization, HTTP/2, хорошие английские друзья могут узнать об этом (перейти через стену), если будет возможность, я тоже хочу написать блог на эту тему.
В nuxt js выполняет разделение кода через webpack + SplitChunksPlugin. SplitChunksPlugin основан на следующих условиях, чтобы определить, нужно ли разделить пакет.
- Новый пакет будет разделен, если его размер после сжатия превышает 30 КБ.
- Можно поделиться новыми пакетами или модулями из папки node_modules.
- При загрузке пакетов по требованию количество параллельных запросов меньше или равно 5
- Параллельный запрос пакета, необходимый для начальной страницы, меньше или равен 3
При использовании HTTP2 вы можете сами настроить количество параллельных запросов.
config.optimization.splitChunks.maxInitialRequests = 20; // for HTTP2
config.optimization.splitChunks.maxAsyncRequests = 20; // for HTTP2
Это означает, что при поддержке большего количества параллельных запросов ваш пакет может быть лучше разделен, а модули, совместно используемые несколькими пакетами, могут быть упакованы отдельно в пределах количества параллельных запросов, а js в пакете js также может быть меньше и покрытие вашего кода будет лучше.
Загружайте только нужные файлы в верхней части страницы
Если вы также используете фреймворк nuxt, вы можете взглянуть на свой файл nuxt.config.js и проверить глобальную конфигурацию head, css, плагинов, они загружаются глобально, то есть, является ли ваша страница реальной или нет. Если вам нужен определенный файл, Nuxt упакует этот файл в пакет js или сразу в целый файл css. Если вам действительно нужно ввести файл js в голову, который необходимо использовать глобально, например, сторонний файл js, вы также можете рассмотреть возможность установки этого файла сценария вasync.
В нашем проекте нужно использовать даже одну страницуvideo.js
, этот файл js по-прежнему представлен на каждой странице
css: [
"normalize.css"
"video.js/dist/video-js.css"
],
plugins: [
{ src: "~/plugins/nuxt-video-player-plugin.js", ssr: false }
]
После оптимизации глобального файла. Вы можете обратить внимание на нашу домашнюю страницу и оптимизировать файлы, которые нужны только первому экрану. Прежде всего, для разных страниц вам необходимо проанализировать элементы вашего первого экрана, чтобы найти самый важный элемент.
Самое главное на главной странице нашего сайта — это первая картинка в карусели, она находится в середине сайта и занимает самое большое место, это то место, которое пользователи увидят с первого взгляда, поэтому для обеспечения это первое изображение Изображение может быть просмотрено пользователем ранее, первый элемент карусели визуализируется на стороне сервера, а остальные элементы загружаются, когда карусель требуется в первый раз.Затем, за исключением элементов, которые можно увидеть на первом экране, лениво загружаются «думаю, вам нравится модуль» и «этаж продукта».
components: {
FavoritePane: LazyComponent({
component: () => import("@/components/index/FavoritePane.vue")
}),
FloorProvider: LazyComponent({
component: () => import("@/components/index/FloorProvider.vue")
})
}
///////////////////////////////////LazyComponent关键代码段/////////////////////////////////////////////
function gen({ component, option }) {
let resolveComponent;
return () => ({
component: new Promise(resolve => {
resolveComponent = resolve;
}),
loading: {
mounted() {
this.el = this.$el;
this.checkInView();
this.initListener();
},
render(h) {
return h(loading, {
props: {
height: "300px"
}
});
},
props: {
preLoad: {
type: Number,
default: option.preLoad || 0.9
}
},
data() {
return {
el: null,
rect: {}
};
},
methods: {
initListener() {
on(this.el, this.checkInView);
},
getRect() {
this.rect = this.$el.getBoundingClientRect();
},
checkInView() {
this.getRect();
if (
inBrowser &&
(this.rect.top < window.innerHeight * this.preLoad &&
this.rect.bottom > 0) &&
(this.rect.left < window.innerWidth * this.preLoad &&
this.rect.right > 0)
) {
this.load();
this.destroy();
}
},
load() {
component().then(resolveComponent);
},
destroy() {
off(this.el, this.checkInView);
}
}
}
});
}
LazyComponent здесь является асинхронным компонентом. Асинхронный компонент Vue может устанавливать параметры загрузки. Мы выводим эту загрузку только при рендеринге на стороне сервера.Займите эту позицию, и тогда, когда вам понадобится визуализировать асинхронные компоненты позже, вы сможете уменьшить накладные расходы, вызванные ретрансляцией.После того, как компоненты загружаются лениво, библиотеку, изначально использовавшуюся для ленивой загрузки картинок, тоже можно не использовать, а наш js здесь меньше.
После сортировки глобальных js и ленивой загрузки компонентов, отличных от первого экрана, наш js был уменьшен с исходных 670 до 362, сокращение на 46%, а покрытие кода уменьшено с 56% до 46%.
long task
Длинные задачи повлияют на TTI или вызовут задержки анимации и задержки ответа, поэтому нам нужно найти длинные задачи, разделить задачи и установить приоритеты для выполнения задач. В среде разработки через производительность с Таймингами и Главной найдите задачу, которая занимает основной поток на долгое время, и проанализируйте, из каких методов она состоит. После попытки разделить его, казните его по приоритету.
Следующий метод можно использовать для последовательного выполнения разделенных компонентов, разбивая длинную задачу на две небольшие задачи.<ProductSwpier v-if="defer(1)"/>
<ProductInfo v-if="defer(2)" />
/////////////////////////////defer.js//////////////////////////////
export default function(count = 5) {
return {
data() {
return {
displayPriority: 0
};
},
mounted() {
this.countDisplayPriority();
},
methods: {
countDisplayPriority() {
const step = () => {
if (this.displayPriority < count) {
this.displayPriority++;
requestAnimationFrame(step);
}
};
requestAnimationFrame(step);
},
defer(priority) {
return this.displayPriority >= priority;
}
}
};
}
tips
async await
async asyncData() {
let banner = (await getBannerItemList()).data;
let mediaObjSrc = (await getVideoEntrance()).data;
return { banner, mediaObjSrc };
}
Вышеуказанный метод обусловлен асинхронным управлением, даже если две асинхронные задачи не имеют зависимостей, они все равно будут выполняться одна за другой.Асинхронные задачи без зависимостей в asyncData оптимизированы с помощью promise.all
async asyncData() {
let [banner,mediaObjSrc] = await Promise.all([getBannerItemList(),getVideoEntrance()])
return { banner, mediaObjSrc };
}
Асинхронно запрашиваемые данные оптимизируются с помощью v-if
<el-carousel class="carousel" height="500px">
<el-carousel-item v-for="(item,index) in banner" :key="index">
</el-carousel-item>
</el-carousel>
Даже если данные баннера все равно не возвращаютсяel-carousel
пойдет первымinit->render->patch
Но так как нет данныхpatch
Результат пустой.
<el-carousel class="carousel" v-if="banner" height="500px">
<el-carousel-item v-for="(item,index) in banner" :key="index">
</el-carousel-item>
</el-carousel>
После оптимизации с v-if она будет выполнена только после возврата данныхel-carousel-item
изinit-render-patch
Суммировать
Выше приведены некоторые мелкие детали, на которые необходимо обратить внимание при программировании, а также некоторые идеи по оптимизации. Но оптимизация никогда не заканчивается.Что сложно для команды, так это атмосфера или культура, ориентированная на оптимизацию производительности. Во многих командах или проектах часто случается, что после периода итерации или командной разработки кода, который только что был оптимизирован, производительность становится все менее и менее идеальной.Поскольку так называемая небольшая команда полагается на публичность, большие команды полагаются на инструменты. . Проверка кода в непрерывных итерациях и командная культура, ориентированная на производительность, — вот секреты поддержания высокой производительности в непрерывных итерациях.