[Достойно коллекции] Подробное объяснение оптимизации внешнего интерфейса и несколько вопросов, требующих внимания.

Webpack

Фронтенд-оптимизация — это большая тема, и для ее понимания требуется много времени. Итак, на этот раз я сделал систематизированный обзор оптимизации рендеринга, оптимизации упаковки и оптимизации кода, а также расширил несколько вопросов, требующих внимания.Статья может быть немного длинной, и вы должны прочитать ее до конца. В конце концов написать не просто.Надеюсь если вы считаете что ничего страшного,пожалуйста помогите мне волной лайков.Заранее спасибо. Конечно, если что-то не так написано, пожалуйста, укажите на это, и я буду активно это улучшать и расти вместе.

Оптимизация рендеринга

Оптимизация рендеринга является очень важной частью оптимизации внешнего интерфейса. Хорошее первое экранное время может принести пользователям хороший опыт. Здесь следует сказать об определении первого экранного времени. Разные команды имеют разные определения первого экранного времени. Точно так же некоторые команды считают, что время в верхней части страницы — это время белого экрана, то есть время от загрузки страницы до первого появления на экране. Но когда мы говорим о пользовательском опыте, этого недостаточно, поэтому некоторые фронтенд-команды считают, что первое экранное время должно быть временем от загрузки страницы до момента, когда пользователи могут выполнять обычные операции со страницей, затем мы следуем последнему, чтобы объяснить

js порядок загрузки css

Прежде чем говорить об оптимизации рендеринга, нам также нужно рассказать о небольшом эпизоде, который представляет собой относительно классический вопрос «что случилось с URL, введенным в адресную строку браузера». Только поняв это, мы можем понять влияние загрузки js и css. заказ на рендеринг.

Вопрос 1: Что происходит, когда вы вводите URL-адрес в адресной строке

Этот вопрос часто поднимают, кто-то отвечает более лаконично, кто-то более развернуто, давайте поговорим об основном процессе.

  • Во-первых, будет выполнен парсинг URL-адресов и поиск IP-адресов в соответствии с системой DNS.
  • Сервер можно найти по ip, а затем браузер и сервер произведут трехстороннее рукопожатие TCP для установления соединения.Если в это время это https, то также будет установлено TLS-соединение и будет активирован алгоритм шифрования будет оговариваться. Будет еще одна проблема, требующая внимания. "https и разница между http" (будет обсуждаться позже)
  • После установления соединения проблемный браузер начинает отправлять запросы на получение документов, на этот раз будет ситуация что кешируется, соединение устанавливается идет сразу в кеш или извлекается, нужно смотреть настройки фона, так там основное внимание будет уделено «механизму кеширования браузера», например, о кешировании мы будем говорить, у нас сейчас, когда нет кеша, напрямую получить файл
  • Во-первых, получить html-файл и построить DOM-дерево, этот процесс состоит в том, чтобы парсить во время загрузки, не ждать, пока все html-файлы будут загружены, затем парсить html, что является пустой тратой времени, а загрузить немного и разобрать немного
  • Ну а при парсинге в хтмл шапку будет другая проблема, где ставить css и js? Различные позиции будут вызывать разные рендеринги. В это время будет еще один вопрос, на который необходимо обратить внимание: "Где должны быть размещены позиции css и js? Почему?", мы сначала объясним в соответствии с правильной позицией (css помещается в голову, js помещается в хвост)
  • После синтаксического анализа в заголовке html найден файл css. В это время файл css загружается. Файл css также анализируется во время загрузки и строится дерево CSSOM. Когда дерево DOM и дерево CSSOM построены , браузер будет отображать дерево DOM и CSSOM. Дерево встроено в дерево рендеринга.
  • Расчет стиля, последнее предложение выше "Дерево DOM и дерево CSSOM будут объединены в дерево рендеринга" немного общее. На самом деле, есть более подробные операции, но общего ответа должно быть достаточно. Давайте поговорим о структура сейчас Что еще делается при рендеринге дерева. Во-первых, это вычисление стиля.После того, как дерево DOM и дерево CSSOM становятся доступными, браузер начинает вычисление стиля, в основном для того, чтобы найти соответствующий стиль для узлов в дереве DOM.
  • Построить дерево макета.После того, как стиль рассчитан, начните строить дерево макета. В основном это нужно для того, чтобы найти соответствующую позицию на странице для узлов в дереве DOM и скрыть некоторые элементы «display: none».
  • Построить многоуровневое дерево.После того, как дерево макета будет завершено, браузеру также необходимо построить многоуровневое дерево, в основном для выполнения сложных многоуровневых операций, таких как полосы прокрутки, z-индекс и положение.
  • Замостите иерархическое дерево и используйте растр, чтобы найти соответствующее растровое изображение под окном просмотра. Главным образом потому, что длина страницы может составлять несколько экранов, и рендерить ее сразу расточительно, поэтому браузер найдет тайл, соответствующий окну просмотра, и отобразит эту часть тайла.
  • Окончательный процесс рендеринга рендерит всю страницу, и в процессе рендеринга будет перестановка и перерисовка.Это также популярный вопрос «Почему перестановка и перерисовка влияет на рендеринг и как этого избежать?»
  • Приведенный выше процесс примерно объясняет весь процесс от url до рендеринга страницы, на самом деле он включает в себя несколько моментов, требующих внимания, давайте поговорим об этом подробнее.

Вопрос 2: Влияние порядка js и css на оптимизацию интерфейса

Выше мы говорили обо всем процессе рендеринга, но не говорили о влиянии css и js на рендеринг. Состав дерева рендеринга должен состоять из дерева DOM и дерева CSSOM, поэтому построение дерева CSSOM как можно быстрее является важным методом оптимизации.Если файл css помещается в конец, весь процесс представляет собой последовательный процесс. Сначала анализируется DOM, а затем анализируется css. Поэтому css вообще помещают в голову, чтобы построение DOM-дерева и CSSOM-дерева осуществлялось синхронно.

Давайте снова посмотрим на js, потому что выполнение js предотвратит рендеринг дерева DOM, поэтому, как только наш js будет помещен в голову, и эти операции не будут загружаться асинхронно, как только js будет запущен, дерево DOM никогда не будет Тогда страница всегда будет иметь интерфейс с белым экраном, поэтому обычно мы помещаем файл js в конец. Конечно, нет никакой проблемы, если он размещен в конце, но проблема относительно невелика, если файл js, размещенный в конце, слишком большой, он будет выполняться долго, и когда код загрузится, будет много трудоемких операций, которые сделают страницу некликабельной. Это еще одна проблема, но это определенно лучше, чем белый экран. Белый экран означает, что страницы вообще нет. Это страница, на которой есть только работа не плавная.

Есть еще одна причина, по которой js-скрипт ставится в конец, иногда js-код будет работать на DOM-узле, если он выполняется в начале, то DOM-дерево не построено, и DOM-узел не может быть получен, но если вы используете его снова, произойдет ошибка. , если ошибка не будет обработана должным образом, страница сразу выйдет из строя

Вопрос 3: Почему перекомпоновка и перерисовка влияют на рендеринг и как этого избежать?

Почему переупорядочивание и перерисовка влияют на рендеринг, какой из них оказывает большее влияние и как этого избежать — тема, которая часто задается.Давайте сначала поговорим о перерисовке.

  • перерисовать

    Перерисовка относится к операциям, которые не влияют на макет интерфейса, например, изменение цвета, тогда, согласно приведенному выше объяснению рендеринга, мы знаем, что после перерисовки нам нужно только повторить вычисление стиля, а затем мы можем визуализировать напрямую, что влияет рендеринг браузера. Относительно небольшой

  • переставлять

    Под перекомпоновкой понимаются операции, влияющие на компоновку интерфейса, такие как изменение ширины и высоты, скрытие узлов и т. д. Для реорганизации это не так просто, как пересчет стиля.Поскольку макет изменяется в соответствии с описанным выше процессом рендеринга, задействованные этапы включают расчет стиля, регенерацию дерева компоновки и регенерацию иерархического дерева.Воздействие на рендеринг относительно велико.

  • Как избежать

    • js сводит к минимуму манипуляции со стилями и использует css, если это можно сделать с помощью css.
    • Минимизируйте операции с dom и используйте createDocumentFragment везде, где это возможно.
    • Если вы должны использовать стиль работы js, вы можете максимально объединить и не делить его на несколько операций.
    • Событие изменения размера лучше всего добавлять для защиты от сотрясений и запускать как можно реже.
    • При загрузке изображения пишите ширину и высоту заранее

Проблема 4: механизм кэширования браузера

Кэширование в браузере — относительно распространенная проблема.Я объясню, как кеширует браузер, как реализован кеш и где кеш находится.

Метод кэширования

Существует два типа кешей браузера, о которых мы часто говорим: обязательный кеш и согласованный кеш.

  • Согласовать кеш

    Согласование кеша означает, что файл был закэширован, но нужно ли считывать из кеша, нужно согласовывать с сервером.Как согласовать, зависит от настроек поля заголовка запроса/заголовка ответа, которые будут рассмотрены ниже. Следует отметить, что кеш согласовывается или запрос отправляется

  • Принудительно кэшировать

    Принудительное кеширование означает получение файла напрямую из кеша без отправки запроса

реализация кэша

  • Принудительно кэшировать

Expires используется для принудительного кэширования в http1.0, которое представляет собой поле в заголовке ответа, указывающее время истечения срока действия файла. Это абсолютное время.Поскольку это абсолютное время, в некоторых случаях, когда часовой пояс сервера и часовой пояс браузера не совпадают, кеш будет аннулирован. Чтобы решить эту проблему, в HTTP1.1 введен новый элемент управления кешем заголовка ответа, необязательные значения которого следующие:

cache-control
  • max-age: время истечения кэша, относительное время
  • public: указывает, что и клиент, и прокси-сервер будут кэшировать
  • private: указывает, что кеш находится только на стороне клиента
  • no-cache: согласовать идентификатор кэша, указывающий, что файл будет кэширован, но его необходимо согласовать с сервером.
  • no-store: означает, что файл не будет кэшироваться

Http1.1 использует Max-Age: 600 для принудительного кэша, потому что это относительное время, поэтому не будет никаких истечений проблемы

  • Согласовать кеш

    Согласованное кэширование заключается в использовании двух пар заголовков ответа и заголовков запроса Last-Modified/if-Modified-Since, Etag/if-None-Match.

    Last-Modified/if-Modified-Since
    • В первый раз, когда браузер отправляет запрос на кэширование файла, заголовок ответа сервера возвращает Last-Modified для записи времени модификации.
    • Когда браузер отправляет запрос во второй раз, он выводит заголовок запроса if-Modified-Since, а время — это значение, возвращаемое Last-Modified. Затем сервер получает это поле и сравнивает его с установленным им самим временем, если время совпадает, то это означает, что модификации нет, и он возвращается сразу на 304 для получения файла из кеша.
    Etag/If-None-Match

    Поскольку временная гранулярность Last-Modified составляет секунды, некоторые файлы могут быть изменены несколько раз в течение 1 секунды. Этот метод по-прежнему не работает в этом особом случае, поэтому HTTP1.1 вводит поле Etag. Это поле создает маркер, такой как "W/"5f9583bd-10a8"" на основе содержимого файла, а затем сравнивает его с If-None-Match, чтобы более точно определить, был ли файл изменен.

где кеш

Зная метод и реализацию кеша, давайте поговорим о том, где находится кеш.Когда мы открываем самородки, мы можем увидеть следующую информацию . Есть два источника кеша: из кеша диска, из кеша памяти

form memory cache

Это кешируется в памяти. Преимущество в том, что это быстро, но чувствительно ко времени. Кэш будет недействителен, когда вкладка закрыта.

from disk cache

Это кешируется на диске.Хотя это медленно, но все же быстрее, чем запрос.Преимущество в том, что кеш всегда можно сохранить, даже если вкладка закрыта, он всегда будет существовать.

Когда кэшировать в памяти, а когда кэшировать на диске?

Стандартный ответ на этот вопрос редко можно найти в Интернете.Все сходятся во мнении, что браузер автоматически сохраняет файлы js и изображения в памяти, а файлы css сохраняются на диск, потому что они не часто модифицируются.Открываем сайт Nuggets, большая часть из которых - все файлы основаны на этом правиле, но есть также несколько файлов js, которые также кэшируются на диске. Так каков именно его механизм хранения? Я проверил много статей с этим вопросом.Хотя я не нашел точного ответа в конце концов, ответ Zhihu может дать нам идеи.Вот цитата из ответчика Zhihu.

  • Первое явление (для примера возьмем картинку): зайти -> 200 -> выйти из браузера и войти -> 200 (из кеша диска) -> обновить -> 200 (из кеша памяти). Резюме: Возможно ли, что хром очень шустрый, чтобы судить о том, что раз он был взят с диска, второй раз быстро взять память. (смеется и плачет)

  • Второе явление (в качестве примера возьмем картинку): Пока картинка base64, я думаю, что из кеша мемрой. Резюме: Парсинг и рендеринг изображений — такая кропотливая вещь, сделай один раз и забери в память. Возьмите это прямо

  • Третье явление (в качестве примера возьмем js css): я обнаружил, что во время статического тестирования большие файлы js css напрямую кэшируются на диске. Knot: Скажет ли хром, что я ухожу, ты слишком большой, чтобы занимать место. Просто зайдите на жесткий диск и оставайтесь там. Помедленней.

  • Четвертое явление: в приватном режиме почти все из мемроя кеша. Резюме: режим конфиденциальности да. Я не могу разоблачать ваши вещи, давайте поместим их в память. Ты закрываешься, я умираю.

Приведенные выше пункты очень забавны, но вы можете найти некоторые ответы из них, но я думаю, что еще один ответ Zhihu, с которым я согласен

Когда браузер работает, он также координируется несколькими процессами, поэтому в целях экономии памяти операционная система будет обменивать часть ресурсов в памяти обратно в область подкачки диска. обмен является стратегическим.Например, наиболее часто используется LRU.

Когда сохранять диск и когда сохранять мемоэй все под контролем браузера.Если памяти не хватает, то можно рассмотреть вопрос о сохранении диска.Поэтому после вышеизложенного резюмирую результаты следующим образом.

  • Файлы большего размера будут кэшироваться на диске, потому что память тоже ограничена, а место на диске больше
  • Меньший файл js, картинки хранятся в памяти
  • Файлы CSS обычно существуют на диске
  • В особых случаях размер памяти ограничен, и браузер также будет хранить некоторые файлы js на диске по собственному встроенному алгоритму.

Вопрос 5: Разница между https и http

Когда дело доходит до разницы между https и http, мы можем говорить о разнице между HTTPS-сервером и клиентским соединением, а также о согласовании алгоритма шифрования, специфичном для https, и, возможно, даже о симметричном шифровании, асимметричном шифровании и сертификатах и ​​т. д., длина очень длинно, см. отдельную статью, которую я написал ранееПодробное объяснение https, очень подробно.

запросить оптимизацию

Если говорить перед первой оптимизацией запроса обобщить выше упомянутые файлы js, css для оптимизации порядка, чтобы сделать рендеринг быстрее, нам нужно поставить хвост js, css в голову, то вы должны уделять максимальное внимание при написании js сокращенная перестановка, перерисовка. Напишите html, css как можно короче, чтобы не было избыточности, цель состоит в том, чтобы быстро построить дерево DOM и дерево CSSOM. Ну скажем в запросе на оптимизацию оптимизация может запросить старт от количества запросов и запросов как раз

уменьшить количество запросов

  • Упакуйте небольшие изображения в base64
  • Используйте Sprite для объединения нескольких маленьких изображений
  • Использование кеша было упомянуто выше

Сокращение времени запроса

  • Максимально сжимайте js, css, html и другие файлы, чтобы уменьшить размер файла и ускорить загрузку.
  • Используйте упаковку WebPack по роутингу, не загружайте изначально все, тогда файл будет большой
  • Если вы можете перейти на более высокую версию http, вы можете перейти на более высокую версию (этот ответ является клише), почему более высокая версия может улучшить скорость, подробности см. В статье https, о которой я упоминал выше.
  • Создайте внутреннюю CDN, чтобы получать файлы быстрее

оптимизация веб-пакета

Введена оптимизация рендеринга.Теперь давайте взглянем на оптимизацию webpack.Когда я обычно пишу демки для обучения команды, я всегда пишу конфигурацию webpack сам.Хотя это всего несколько десятков строк, это позволяет мне закрепить базовые настройка вебпака каждый раз.Следующее Подскажите прямо какие есть методы оптимизации вебпака

Оптимизация базовой конфигурации

  • extensions

Эта конфигурация относится к разрешению и часто используется для расширения файлового суффикса.

resolve: {
    extensions: ['.ts', '.tsx', '.js']
}

Эта конфигурация представляет WebPack на основе расширений, чтобы найти расширение файла, поэтому, если наш проект в основном написан TS, то мы можем .tsx и .ts, написанные ранее, цель - разрешить быстрое разрешение

  • alias

Эта конфигурация также относится к разрешению. Она используется для отображения прочности дороги. Основная причина сокращения времени упаковки — позволить веб-пакету быстро разобрать путь к файлу и найти соответствующий файл. Конфигурация выглядит следующим образом.

resolve: {
  alias: {
    Components: path.resolve(__dirname, './src/components')
  }
}
  • noParse

noParse указывает файлы, которые не нужно анализировать.Некоторые файлы могут быть файлами третьих лиц и ProvidePlugin вводится как переменная на windows.Такие файлы относительно большие и уже упакованы, поэтому необходимо исключить такие файлы.Конфигурация следующая

module: {
  noParse: [/proj4\.js/]
}
  • exclude

У некоторых загрузчиков будет такой атрибут, цель указать область действия роли загрузчика, исключить означает, что некоторые файлы не нуждаются в обработке babel-загрузчиком, роль загрузчика небольшая, скорость упаковки естественно будет быстрее, используйте babel-loader, чтобы дать один простой пример

{
    test: /\.js$/,
    loader: "babel-loader",
    exclude: path.resolve(__dirname, 'node_modules')
}
  • devtool

Эта конфигурация является элементом отладки.Разные конфигурации имеют разные эффекты отображения,размер упаковки и скорость упаковки.Например,дешевая-исходная-карта определенно быстрее, чем исходная-карта в среде разработки.Почему, я настоятельно рекомендую, чтобы я написал это раньше.Статья, объясняющая devtool:статьи по инструментам разработки webpackОчень подробно.

{
    devtool: 'cheap-source-map'
}

.eslintignore

Хотя это не конфигурация WebPack, но она также очень полезна для скорости пакета, проверки Eslint в моей практике сильно зависят от скорости пакета, но во многих случаях мы не можем выполнить эту проверку Eslint, проверку eslint если только в VS, Может не страховка.

Поскольку возможно, что плагин eslint в вашем VS внезапно закрыт или по какой-то причине VS не может быть проверен, вы можете полагаться только на сборку веб-пакета, чтобы остановить отправку неправильного кода, даже это не гарантирует надежность, потому что вы можете отправить код один раз Я не запускал службу в спешке, поэтому я сделал слепое изменение и отправил его напрямую. В это время вы можете быть защищены только последним барьером, то есть во время КИ. Например, мы также проверим eslint для вас, когда jenkins будет построен, Три барьера гарантируют, что финальное изображение, которое мы создадим, не будет иметь никаких проблем.

Поэтому eslint очень важен и не может быть удален.Как мы можем уменьшить время проверки, когда его нельзя удалить?Мы можем игнорировать файлы и отключить eslint для ненужных файлов.Максимально увеличить скорость упаковки

Загрузчик, оптимизация плагинов

Выше упоминалось несколько основных оптимизаций конфигурации.Должны быть и другие базовые конфигурации.В дальнейшем я продолжу их добавлять.Сейчас расскажу на примере использования некоторых загрузчиков и плагинов для повышения скорости упаковки.

  • cache-loader

Этот загрузчик кэширует результат упаковки при первой упаковке и напрямую считывает кэшированное содержимое при второй упаковке, тем самым повышая эффективность упаковки. Но его также нужно использовать разумно, мы должны помнить, что каждый добавленный вами загрузчик и плагины принесут дополнительное время на упаковку. Это дополнительное время больше, чем время сокращения, которое он приносит, поэтому бессмысленно увеличивать загрузчик вслепую, поэтому кеш-загрузчик лучше всего использовать на загрузчике, который занимает много времени, конфигурация следующая

{
  rules: [
    {
      test: /\.vue$/,
      use: [
        'cache-loader',
        'vue-loader'
      ],
      include: path.resolve(__dirname, './src')
    }
  ]
}
  • webpack-parallel-uglify-plugin, uglifyjs-webpack-plugin, terser-webpack-plugin

В приведенной выше оптимизации рендеринга мы уже знаем, что чем меньше размер файла, тем выше скорость рендеринга. Поэтому мы часто используем сжатие при настройке веб-пакета, но сжатие также требует времени, поэтому мы часто используем один из трех вышеперечисленных плагинов, чтобы включить параллельное сжатие и сократить время сжатия. иллюстрировать

optimization: {
  minimizer: [
      new TerserPlugin({
        parallel: true,
        cache: true
      })
    ],
}
  • happypack, parallel-webpack, thread-loader

Эти загрузчики/плагины также включают параллелизм, как указано выше, за исключением того, что включено параллельное построение. Поскольку автор happypack сказал, что его больше не интересует js, он больше не поддерживается, и рекомендуется использовать thread-loader, если вы используете webpack4. Базовая конфигурация выглядит следующим образом

     {
        test: /\.js$/,
        use: [
          {
            loader: "thread-loader",
            options: threadLoaderOptions
          },
          "babel-loader",
        ],
        exclude: /node_modules/,
      }
  • DllPlugin,webpack.DllReferencePlugin

Несколько параллельных плагинов, упомянутых выше, теоретически могут увеличить скорость сборки, об этом говорится во многих статьях в Интернете, но я использовал его в реальном процессе и обнаружил, что иногда это не только не улучшает, но и снижает скорость упаковки. Причина в том, что количество ядер вашего компьютера уже низкое, или ваш процессор уже загружен в это время, а затем открытие нескольких процессов снизит скорость сборки.

Несколько параллельных плагинов, упомянутых выше, в некоторых случаях могут не дать желаемого эффекта, однако, судя по опыту нашей команды, оптимизирующей производительность веб-пакета, два плагина, упомянутые на этот раз, очевидны и могут каждый раз улучшать скорость упаковки. Принцип заключается в том, чтобы сначала упаковать сторонние зависимости для генерации js-файла за раз, а затем, когда код проекта будет упакован, требуемые объекты будут получены непосредственно из упакованного js-файла в соответствии с файлом сопоставления, без необходимости для упаковки сторонних файлов. Просто конфигурация упаковки в этом случае немного сложнее, и нужно написать webpack.dll.js. Примерно так

webpack.dll.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
    entry: {
        library: ["vue", "moment"]
    },

    output: {
        filename: '[name].dll.js',
        path: path.resolve(__dirname, 'json-dll'),
        library: '[name]'
    },

    plugins: [
        new webpack.DllPlugin({
            path: './json-dll/library.json',
            name: '[name].json'
        })
    ]
}

webpack.dev.js

  new AddAssetHtmlWebpack({
     filepath: path.resolve(__dirname, './json-dll/library.dll.js')
  }),

 new webpack.DllReferencePlugin({
      manifest: require("./json-dll/library.json")
    })

Другие оптимизированные конфигурации

Эти плагины кратко представлены. Я использовал их в своих личных проектах. Я чувствую, что они в порядке. Для конкретного использования, пожалуйста, обратитесь к npm или github.

  • webpack-bundle-analyzer

Этот плагин может помочь нам проанализировать объем упаковки с визуализацией, чтобы использовать соответствующие методы оптимизации для улучшения конфигурации нашего веб-пакета.

  • speed-measure-webpack-plugin

Этот плагин может сообщить нам, сколько времени занимает упаковка каждого загрузчика или плагина, чтобы оптимизировать плагины и загрузчики, которые занимают много времени.

  • friendly-errors-webpack-plugin

Этот плагин может помочь нам оптимизировать журналы упаковки. Мы часто видим длинное сообщение журнала при упаковке. Иногда нам это не нужно, и мы не будем его читать. Поэтому мы можем использовать этот плагин для упрощения

Оптимизация кода

Это последняя часть оптимизации кода. Оптимизация производительности кода здесь - это только то, что я чувствую в работе. Что касается других относительно небольших моментов оптимизации, таких как использование createDocumentFragment, вы можете проверить другие статьи.

Не могу управлять домом, не управляю домом, даже если иногда требуется изменить дизайн

Во многих случаях мы можем использовать css для восстановления проекта дизайна, но иногда восстановить из одного css невозможно, особенно когда компоненты написаны не вами.Например, наша команда использует antd, и иногда дизайн продукта не может быть восстановлено из css. Для достижения этого используйте только js, удаляйте и добавляйте узлы, чтобы завершить соответствующий стиль.

Поскольку мы являемся компанией, занимающейся большими данными, в это время возникнут проблемы с производительностью.Когда мы впервые пишем код, продукт говорит то, что он говорит, и я найду способ получить его, независимо от того, какой метод я использую. Позже, в случае запросов больших данных на сайте заказчика, сразу же выявились недостатки производительности.

Таким образом, один из принципов оптимизации кода, я думаю, заключается в том, чтобы не писать код, который не может быть написан, конечно, это с точки зрения производительности, аргументировать продукт с помощью анализа производительности, и лучше всего предоставить лучшее решение, это то, что нам нужно рассмотреть.

Если вы используете реакцию, вы должны написать функцию жизненного цикла shouldComponentUpdate, иначе вы обнаружите, что вас смущает, почему вы выполняли так много раз при печати.

Превратите сложные сравнения в простые сравнения

Что означает это предложение? Возьмем, к примеру, shouldComponentUpdate, с этой функцией проблем нет, но ее можно сделать лучше, о чем мы часто пишем в своей работе.

shouldComponentUpdate(nextPrpops) {
  return JSON.stringify(nextPrpops.data) !== JSON.stringify(this.props.data)
}

Если это таблица подкачки, данные — это данные каждой страницы, и данные изменяются и повторно отображаются, что само по себе не является проблемой в сценариях с небольшим объемом данных. Однако, если могут быть проблемы в сценарии с большими данными, у некоторых людей могут возникнуть сомнения, поскольку разбиение на страницы выполняется, как могут быть большие данные, потому что наш продукт предназначен для журналов анализа больших данных, десять журналов на страницу и некоторые журналы. может быть очень длинным, то есть сравнение даже 10 фрагментов данных занимает много времени, поэтому я подумал в то время, могу ли я найти другие заменяющие переменные, чтобы указать, что данные изменились? например следующее

shouldComponentUpdate(nextPrpops) {
  return nextPrpops.data[0].id !== this.props.data[0].id
}

Если id первого элемента не тот, значит данные изменились. Очевидно, что он существует при определенных обстоятельствах. Кто-то скажет, что id может быть тот же. Если его заменить на следующий?

shouldComponentUpdate(nextPrpops) {
  return nextPrpops.current !== this.props.current
}

Преобразуйте сравнение данных в текущее сравнение, потому что количество страниц изменилось, данные в основном изменились.Для отображения наших собственных журналов в принципе нет двух абсолютно одинаковых страниц данных.Если есть, то это может быть фоновый вопрос. Затем я тщательно обдумываю эту проблему.Даже если есть две страницы с идентичными данными, в лучшем случае таблица не будет повторно отображаться, но нет никаких проблем, если две страницы данных идентичны и не отображаются повторно, потому что данные одинаковые. Или, если вы все еще беспокоитесь, будет ли лучше следующее?

this.setState({
  data,
  requestId: guid()
})

shouldComponentUpdate(nextPrpops) {
  return nextPrpops.requestId !== this.props.requestId
}

Дайте requestId для отслеживания данных, а затем сравните только requestId. Могут быть проблемы с вышеперечисленными методами написания, но главное, что мы можем думать о том, можем ли мы «превратить сложные сравнения в простые сравнения» при написании кода.

Изучите структуры данных и алгоритмы, которые обязательно пригодятся вам в работе

Мы часто слышим, что изучение структур данных и алгоритмов не очень полезно, потому что работа по сути бесполезна. Я думал, что это предложение было правильным раньше, но теперь оно кажется очень неправильным. Каждый навык, которому мы учимся, пригодится в дальнейшей жизни. Написав код раньше, я потерял его и не оптимизировал, поэтому считаю алгоритм бессмысленным, сложным и легко забываемым. Но теперь я прошу себя выполнить требования, открыть мок, открыть perfermance для тестирования большого количества данных, и посмотреть на отмеченные красным флейм-графы и видимые зависания, и тогда я понимаю важность алгоритмов и структур данных, потому что в это время вы можете получить от него только оптимизацию Обычно вы отказываетесь от этого, но когда дело доходит до оптимизации, вы так хотите ее иметь. Я беру код, который я написал ранее, в качестве примера. Поскольку код компании является конфиденциальным, я изменю переменную. Псевдокод выглядит следующим образом.

data.filter(({id}) => {
  return selectedIds.includes(id);
})

Всего несколько строк кода, как это, логика заключается в том, чтобы отфильтровать данные, которые были проверены в данных. В принципе, так могут писать многие, потому что я вижу, что у нас в команде так пишут. Продукт имеет ограниченные данные до максимум 200 данных на тот момент, поэтому запись не требуется, и производительность не снижается. Однако, следуя принципу оптимизации производительности (в основном из-за того, что меня пугала внутренняя среда~~~), я запустил mock-сервис, скорректировал данные до 20 000 и затем протестировал его. интерфейс застрял., он зависнет при повторном выборе. Потом начал оптимизировать, конкретные идеи на тот момент были такие

Согласно текущему коду, это двухуровневая петля со сложностью времени перебора O(n^2). Поэтому я задался вопросом, смогу ли я уменьшить сложность хотя бы до O(nlogn).После прочтения кода я смог начать только с предложения selectedIds.includes(id).Последовательно, как можно разделить мои массивы на строки?

Помолчав некоторое время, я вспомнил курсы и книги по алгоритмам, которые я читал, и задачи по алгоритмам, которые я решал.

1: указатель вверх

2: Увеличение размера массива

3: Используйте хеш-таблицу

Первые два были отвергнуты мной, потому что я не думал, что это так сложно, поэтому я использовал идею хеш-таблицы для решения этой проблемы, потому что в js есть естественная структура хеш-таблицы, которая является объектом. Мы знаем, что запрос хеш-таблицы равен O(1), поэтому я переписываю код следующим образом.

const ids = {};
selectedIds.forEach(id => ids[id] = 1);

data.filter(({id}) => {
  return !!ids[id];
})

При переходе от запроса selectedIds к запросу ids временная сложность изменится с O(n^2) на O(n). Этот код добавляет

const ids = {};
selectedIds.forEach(id => ids[id] = 1);

Фактически, добавление обхода selectedIds также является сложностью O (n).В общем, сложность составляет O (2n), но из-за долгосрочного ожидания временной сложности это все еще сложность времени O (n), но добавляется дополнительный объект An, так что это тоже типичный пример пространства для времени, но не волнуйтесь, механизм сборки мусора переработает идентификаторы после того, как они будут израсходованы.

наконец

На самом деле, написание этой статьи все еще очень полезно для меня, позвольте мне систематически разобраться с оптимизацией интерфейса, которую я понимаю, и я надеюсь, что она поможет и вам.