Для веб-сайта скорость открытия является очень важным показателем, но большую часть времени наша энергия может быть направлена на удовлетворение спроса, особенно когда мы делаем какие-то внутренние проекты, мы часто игнорируем эту оптимизацию с одной стороны. На самом деле, сделать некоторые стандартные оптимизации скорости открытия страницы несложно.В этой статье вы проделаете некоторые операции по оптимизации, которые не будут ни трудоемкими, ни занимающими много времени.Эти операции включают сжатие, кэширование и предварительную загрузку. Ключевые ресурсы, ресурсы ленивой загрузки кэша предварительной выборки и некоторые предложения по справочным компонентам и общей обработке библиотеки инструментов.
включить сжатие gzip
Когда мы используем веб-пакет для упаковки и сжатия кода js, некоторые js (например, поставщика) часто все еще очень велики и могут достигать размера около 1 МБ, хотя с точки зрения текущей пропускной способности, если мы являемся проектом на стороне ПК, это не является серьезной проблемой, но, очевидно, существует значительное пространство для оптимизации, а gzip — это форма.
В заголовке запроса браузера есть такое предложениеAccept-Encoding:gzip, deflate
, что говорит нам о том, что браузер может распознавать сжатие gzip, и файлы, сжатые с помощью gzip, будут значительно уменьшены, во многих случаях даже на 70%. Текущие сервисы в основном используют nginx для пересылки, На самом деле нам довольно легко включить gzip, если настроен следующий код.
server {
gzip on;
gzip_types text/xml text/css text/plain text/javascript application/javascript application/x-javascript;
}
На приведенном выше рисунке показано, что поставщик составляет почти 800 КБ, когда gzip не включен, и только около 250 КБ после включения gzip.
Можно сказать, что если мы даже не включим gzip, любая другая оптимизация будет немного избыточной, потому что, вероятно, нет другого метода оптимизации, который может сжать такое высокое соотношение.
кеш браузера
В дополнение к обычному сжатию gzip, еще один момент оптимизации, который можно использовать, — это кеш браузера. Попутно я расскажу о методе кэширования браузера, но не буду слишком подробно, заинтересованные студенты могут найти дополнительные материалы для изучения.
Браузер разделен на два кеша: сильные кеши и кеши согласования (также известные как слабые кеши), где кеш согласования не нужно настраивать самостоятельно, и мы будем наблюдать за кешем согласования, постоянно обновляя страницу.
Как показано выше, в первом запросе заголовок http-ответа nginx содержитLast-Modified: sometime
Тогда заголовок запроса браузера во втором запросе будет нести это время для сравнения.Когда время nginx раньше этого времени, это означает, что текущий ресурс не изменился, и возвращаемый код состояния соответственно станет 304,
Когда браузер получает 304, это означает, что срок действия кэшированного ресурса не истек, и браузер прочитает кэшированный файл. Следует отметить, что, хотя браузер, наконец, вызывает кеш, все еще существует HTTP-запрос для подтверждения того, что кеш недействителен, поэтому, очевидно, у браузера есть другой способ напрямую вызвать кеш без прохождения http-запроса. сильный кеш. Сильное кэширование можно настроить в nginx с помощью следующего кода
location ~* \.(css|js)$ {
proxy_set_header Host $host;
proxy_pass http://tomcat_xxx;
expires 7d;
}
location ~* \.(jpg|jpeg|png|gif|webp)$ {
proxy_set_header Host $host;
proxy_pass http://tomcat_xxx;
expires 30d;
}
Обратите внимание, что здесь мы используем tomcat. Конфигурация, которая может вам понадобиться, отличается от моей, но это не критично. В основном нам нужна конфигурация expires, которая указывает время, которое мы хотим кэшировать. JS, который мы настроили, одинаковы поскольку CSS кэшируется на 10 дней, а изображения — на 30 дней. Откройте браузер вместе, чтобы увидеть эффект.
Здесь к заголовку ответа браузера будет прикреплено значение max-age=604800. Единицей измерения здесь являются секунды. В пересчете на дни это 7 дней, которые мы только что установили. После повторного обновления браузера код состояния по-прежнему равен 200, но за ним есть еще один.from memory cache
Указывает, что в это время кеш берется напрямую из памяти, и HTTP-запрос не отправляется. Это весьма полезно для некоторых изображений и нашего поставщика пакетов зависимостей. Мы можем установить большее время кэширования для этих двух ресурсов, чтобы при userПосле первого посещения эти ресурсы всегда будут оставаться в кеше пользователя.Даже если мы позже изменим большую часть нашего бизнес-кода, пока зависимости не изменятся, пользователю нужно будет загрузить только несколько небольших файлов бизнес-кода. vendor по-прежнему доступен из кеша.
Мы можем кратко подытожить, как браузеры кешируют, и добавить несколько замечаний. Браузер сначала обнаружит сильный кеш. Если он сработает, он напрямую вернет кешированный файл, не отправляя HTTP-запрос. Если нет совпадения, он проверит слабый кеш. Когда слабый кеш сработает, он вернет 304 код состояния, и браузер по-прежнему будет получать ресурсы из кеша.Если слабый кеш также не попал, возвращается код состояния 200 для перезагрузки ресурса на сервере.
будь осторожен:
- Сильный кеш и слабый кеш - это только разница в названии, и нет никакой разницы между сильным и слабым.На самом деле, для обычных браузеров обновление сделает недействительным сильный кеш ресурса, который вы в настоящее время запрашиваете, потому что при обновлении заголовок запроса будет нести
max-age=0或是no-cache
, обратите внимание, что текущий ресурс запроса, о котором я говорил здесь, обычно относится к html-документу вашей страницы, но для js и img внешней ссылки в документе сильный кеш не будет аннулирован из-за обновления. Однако, если вы напрямую запросите файл js, надежный кеш файла js также будет недействительным после обновления. - Поскольку сильный кеш не будет инициировать http-запросы, что мне делать, если ресурсы сервера изменены? На самом деле хеш-код, сгенерированный webpack, помогает нам решить эту проблему.Когда app.123456.js внешней цепочки становится app.654321.js, браузер, естественно, повторно инициирует запрос, что также напоминает нам не менять поставщика, насколько это возможно. Приводит к тому, что изменение хэша поставщика вызывает проблему инвалидации кеша.
Предварительная загрузка для приоритетной загрузки ключевых ресурсов и некоторых ленивых ресурсов загрузки
Поскольку наш стек технологий — vue, мы используем vue для демонстрации в следующем примере, но по сути, независимо от того, какой стек технологий, он один и тот же. Предполагая, что наш проект является одностраничным приложением, первый момент, который следует оптимизировать, это ленивая загрузка маршрута, то есть не возвращать все коды вместе за один раз, а только тогда, когда мы переключаемся на текущий route мы запрашиваем код, соответствующий текущему маршруту. Для проекта, инициализированного vue-cli, настройка очень проста, достаточно изменить метод импорта в роутере.
const router = new Router({
routes: [
{
path: '/',
redirect: '/a',
},
{
path: '/a',
component: () => import('../components/a/index.vue'),
},
{
path: '/b',
component: () => import('../components/b/index.vue'),
},
]
Теперь мы можем динамически загружать файл js в зависимости от посещаемого нами маршрутизатора. Но пространство для оптимизации еще есть.Предположим, мы сейчас запрашиваем маршрут а и загружаем публичные js, такие как вендор и js самого а, тогда почему бы нам не загрузить js маршрута b на соответствующую страницу в свободное время посещения страница а. Это находится в кеше браузера, поэтому, когда пользователь переключается на маршрут b, файл в кеше можно использовать напрямую вместо отправки HTTP-запроса.
Здесь мы собираемся использовать плагин webpack,PreloadWebpackPlugin
, роль этого плагина состоит в том, чтобы помочь нам создать соответствующий<link rel="preload" href="xxxx">
и<link rel="prefetch" href="xxxx">
тег, браузер ресурсов href в предварительной загрузке будет загружен первым, и документ mdn о функции предварительной загрузки говорит об этом.
Предварительная загрузка происходит до того, как вмешается основной механизм рендеринга браузера. Этот механизм позволяет загружать ресурсы и делать их доступными раньше и с меньшей вероятностью блокирует первоначальный рендеринг страницы, тем самым повышая производительность.
Конкретная корреляция на самом деле является знанием критического пути браузера, который здесь не подробно описан, вы можете найти другую информацию.
Для prefetch браузер href будет предварительно загружен, и слова в документе mdn приведены здесь для его описания.
Он использует время простоя браузера для загрузки или предварительной выборки документов, к которым пользователь может получить доступ в ближайшем будущем. Веб-страница предоставляет браузеру набор подсказок предварительной выборки и начинает молча извлекать указанный документ и сохранять его в кэше после того, как браузер завершит загрузку текущей страницы. Когда пользователь получает доступ к одному из предварительно загруженных документов, его можно быстро извлечь из кеша браузера.
Итак, что нужно сделать для проекта, сгенерированного vue-cli, — это использовать предварительную загрузку для загрузки трех js-файлов поставщика, манифеста и приложения и использовать предварительную выборку для загрузки файлов, соответствующих всем маршрутам. Таким образом, когда мы обращаемся к маршруту a, сначала будут загружены необходимые js и css, а затем браузер автоматически загрузит другие файлы маршрута. В этот момент, когда пользователь переходит к другим маршрутам, запрос не будет отправлен, пока пользователь не щелкнет. Добавьте следующий код в webpack.prod.conf.js, обратите внимание наnew HtmlWebpackPlugin()
Ниже, поскольку наш проект состоит только из js и css, вы можете самостоятельно настроить такие ресурсы, как img и font.
new PreloadWebpackPlugin({
rel: 'prefetch',
}),
new PreloadWebpackPlugin({
rel: 'preload',
as(entry) {
if (/\.css$/.test(entry)) return 'style'
return 'script';
},
include: ['app', 'vendor', 'manifest']
})
О регистрации глобальных компонентов
Способ, который мы используем во многих сторонних компонентах, заключается в том, чтобы вводить компоненты в main.js, а затем передаватьVue.component()
Для регистрации глобальных компонентов, по сути, не стоит использовать это решение во многих случаях, потому что это увеличит размер вендора, особенно когда этот компонент используется только в одном из маршрутов, тем более неразумно ставить его в поставщику да, потому что кеширование кода этого компонента не приносит нам много пользы.Предположим, что на странице есть 5 маршрутов, что эквивалентно вводу остальных 4 маршрутов.Эти коды бессмысленны, поэтому во многих случаях локально прописанный Компонент будет упакован в код маршрутизации, это лучший вариант. Кроме того, если это огромная библиотека, такая как echarts, рекомендуется упаковать ее в вендор, потому что, поскольку бизнес-код всегда меняется, хеш-значение кода маршрутизации всегда меняется, а код с весом echarts не следует использовать каждый раз, каждый раз, когда я захожу в интернет, пользователю приходится перезагружать его снова...
Подумав об этом, я думаю, что могу ошибаться, потому что мы используем импортированные сторонние компоненты в качестве внешних зависимостей, даже если размер небольшой, каждый раз, когда он запаковывается в js, соответствующий маршруту, это также будет потому, что изменения привели к тому, что пользователь перезагрузил эту часть кода, а при большом объеме, как я уже говорил выше, ее невозможно упаковать в бизнес-код. Есть только один сценарий, о котором я могу думать, который может немного отличаться, то есть, когда код выходит в сеть, мы разрабатываем новые требования и должны вводить новые зависимости, но мы не хотим, чтобы поставщик, кэшированный пользователем, был недопустимо, поэтому мы можем упаковать новый пакет зависимостей , но это увеличит количество HTTP-запросов. Мы знаем, что в http1 наше направление оптимизации заключается в децентрализации доменных имен и уменьшении количества запросов. вопрос мнения Во всяком случае, я не должен этого делать.
Некоторые библиотеки инструментов могут потребовать от нас дополнительной обработки.
Наши общие библиотеки инструментов, такие как lodash и moment, на самом деле довольно велики, и часто мы используем только несколько небольших функций. Представлять такую огромную библиотеку с этими маленькими функциями действительно пустая трата времени. Вот несколько основных решений.
Лодаш: установитьlodash-webpack-plugin
babel-plugin-lodash
Настроить в .babelrc"plugins": ["lodash"]
,вводить lodash по требованию,но если честно,внедрить по требованию иногда не мало.Если вы действительно пользуетесь несколькими очень простыми функциями,может быть не лучший выбор написать самому.
момент: использоватьday.jsзаменить. Библиотека весит всего 2кб и имеет тот же апи, что и момент, больше похвалить не могу, исходники не читал.
Есть также огромные библиотеки, такие как echarts, которые могут быть введены по запросу.Вы можете попытаться оптимизировать размер своего собственного поставщика.