【Апплет WeChat】Оптимизация производительности

внешний интерфейс Апплет WeChat

Контент организован в общедоступном классе WeChat.

Зачем оптимизировать производительность?

Все оптимизации производительности предназначены для оптимизации опыта.

1. При использовании мини-программ вы часто сталкиваетесь со следующими проблемами?

  • Открыт всегда белый экран

  • Открыто — это состояние загрузки, поверните несколько раз

  • Почему моя страница так медленно прыгает?

  • Почему мой список скользит и застревает?

2. Каковы направления нашей оптимизации?

  • Производительность загрузки при загрузке

  • производительность рендеринга

3. Производительность при загрузке

1. Первая загрузка

Вы когда-нибудь видели такую ​​картинку при первой загрузке апплета?

小程序加载

Чему соответствуют три состояния на этой картинке?

Когда апплет запускается, WeChat отображает фиксированный интерфейс запуска для апплета, который содержит значок апплета, имя и значок запроса на загрузку. На этом этапе WeChat сделает несколько вещей за кулисами:下载小程序代码包,加载小程序代码包,初始化小程序首页. Загруженный пакет кода апплета является не исходным кодом апплета, а пакетом кода после компиляции, сжатия и упаковки.

2. Порядок загрузки

В каком порядке загружаются апплеты?

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

小程序运行
Через 2 мы знаем, что первая картинка в вопросе 1资源准备(загрузка пакета кода); второе изображение业务代码的注入以及落地页首次渲染; третье изображение落地页数据请求时的loading态(Часть апплета существует)

3. Размер пакета управления

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

  • Установите флажок «сжимать код при загрузке кода» в инструментах разработчика;

  • Своевременно очищайте бесполезный код и файлы ресурсов (включая бесполезный код журнала)

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

С точки зрения разработчика, контроль размера пакета кода может помочь сократить время запуска апплета.Для пакетов кода размером менее 1 МБ время загрузки можно контролировать в пределах 929 мс (iOS) и 1500 мс (Android)..

4. Используйте механизм загрузки субпакетов

Согласно бизнес-сценарию, страницы с высокой скоростью доступа пользователей размещаются в основном пакете, а страницы с низкой скоростью доступа размещаются в подпакете и загружаются по требованию;

分包加载
При использовании подпакетов нужно обращать внимание на разделение директорий кода и файлов ресурсов. Страницы, к которым необходимо получить доступ при запуске, и зависимые от них файлы ресурсов должны быть помещены в основной пакет.

5 Использование субподрядной технологии предварительной загрузки

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

分包预加载
Эта технология предварительной загрузки подпакетов на основе конфигурации может оцениваться в соответствии с типом сети пользователя и предварительно загружаться только тогда, когда пользователь находится в хороших сетевых условиях; она является гибкой и управляемой.

6. Принять независимую субподрядную технологию

Есть много мелких программ主包+子包(2M + 6M), но когда мы выполняем много операционных действий, мы обнаружим, что действия (красные конверты) находятся в подпакете, но ссылка на целевую страницу работы и запуска продукта — это ссылка на подпакет. , что является прямой посадкой пользователей.При загрузке содержимого основного пакета (как правило, большего размера) сначала должно быть загружено содержимое подпакета (относительно основного пакета, меньшего размера), что делает пользовательский опыт не очень хорошо и расточительно в сценарии мини-программы, где у пользователя на короткое время задерживается большая часть трафика;

独立分包
Может использоваться независимая технология подпакетов, которая отличается от подпакетов и не имеет ничего общего с основным пакетом.В подпакетах с относительно независимыми функциями пользователям нужно только загрузить ресурсы подпакета;

7. Предложения по оптимизации загрузки в верхней части страницы

7.1 Предварительный запрос

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

7.2 Использование кеша

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

7.3 Избегайте белого экрана

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

7.4 Своевременная обратная связь

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


Оптимизация производительности рендеринга

1. Принцип рендеринга мини-программы

Для рендеринга интерфейса в двухпотоковом режиме уровень логики и уровень рендеринга апплета представляют собой два отдельных потока. На уровне рендеринга среда хоста преобразует WXML в соответствующий объект JS. Когда данные изменяются на логическом уровне, нам нужно передать данные с логического уровня на уровень рендеринга с помощью метода setData, предоставляемого хост-средой. , а затем сравните различия до и после. Примените различия к исходному дереву Dom и визуализируйте правильный интерфейс пользовательского интерфейса.

Анализировать этот процесс несложно: время инициализации страницы примерно складывается из времени начальной передачи данных страницы и времени начальной отрисовки. Среди них время передачи данных относится ко времени с момента, когда данные организованы с логического уровня, до момента, когда они полностью получены уровнем представления.Когда объем данных меньше 64 КБ, общая продолжительность может контролироваться в пределах 30 мс.. Время передачи, как правило, положительно коррелирует с объемом данных, и передача чрезмерно больших данных значительно увеличивает это время. Следовательно, уменьшение объема передаваемых данных является эффективным способом сокращения времени передачи данных.

2. Избегайте неправильного использования setData

Во время передачи данных логический уровень будет выполняться один раз.JSON.stringifyудалятьsetDataНепереносимая часть данных, после которой данные отправляются на уровень представления. В то же время уровень логики такжеsetDataЗаданное поле данных такое же, какdataобъединены, чтобы разработчики могли использоватьthis.dataИзмененные данные считываются. Поэтому, чтобы повысить производительность обновления данных, разработчик выполняетsetDataПри звонке лучше всего следовать следующим принципам:

2.1 Не вызывайте setData слишком часто и рассмотрите возможность объединения нескольких вызовов setData в один вызов setData;

2.2 Производительность передачи данных положительно связана с объемом данных, поэтому, если некоторые поля данных не отображаются в интерфейсе, а структура данных является сложной или содержит длинные строки, ее не следует использовать.setDataустановить эти данные;

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

Пример кода способов повышения производительности обновления данных

Page({
  onShow: function() {

    // 不要频繁调用setData
    this.setData({ a: 1 })
    this.setData({ b: 2 })
    // 绝大多数时候可优化为
    this.setData({ a: 1, b: 2 })

    // 不要设置不在界面渲染时使用的数据,并将界面无关的数据放在data外
    this.setData({
      myData: {
        a: '这个字符串在WXML中用到了',
        b: '这个字符串未在WXML中用到,而且它很长…………………………'
      }
    })
    // 可以优化为
    this.setData({
      'myData.a': '这个字符串在WXML中用到了'
    })
    this._myData = {
      b: '这个字符串未在WXML中用到,而且它很长…………………………'
    }

  }
})
  • Частичное обновление списка с помощью setData

В списке естьnЕсли вы хотите понравиться определенному фрагменту данных в это время, вы также можете увидеть эффект лайка во времени.

  • Решение

1. Вы можете использовать setData для глобального обновления.После того, как подобное будет завершено, повторно получить данные и повторно отобразить их глобально.Преимущества этого: удобно и быстро! Недостаток: пользовательский опыт очень плохой.Когда пользователь чистит более 100 фрагментов данных, в объеме повторного рендеринга будет пустая точка (не визуализируется).

2. Говоря о сути, это использованиеsetDataчастичное обновление

> a.将点赞的`id`传过去,知道点的是那一条数据, 将点赞的`id`传过去,知道点的是那一条数据
<view wx:if="{{!item.status}}" class="btn" data-id="{{index}}" bindtap="couponTap">立即领取</view>
> b.重新获取数据,查找相对应id的那条数据的下标(`index`是不会改变的)
> c.用setData进行局部刷新
this.setData({
    list[index] = newList[index]
})

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

2.4 Не устанавливайте данные на фоновой странице

Некоторые операции будут выполняться на некоторых страницах, и после перехода страницы логика кода все еще выполняется.В это время несколькоwebviewэто поделиться процессом js; фонsetDataОперация вытеснит ресурсы рендеринга главной страницы;

3. Неправильное использование пользовательских событий

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

1. Удалите ненужные привязки событий (в WXMLbindиcatch), тем самым уменьшая объем данных и количество коммуникаций; 2. Передача требуется при привязке событияtargetиcurrentTargetизdataset, так что неdataСлишком большие данные помещаются в атрибут префикса.

4. Принцип рендеринга слоев просмотра

4.1 Первый рендер

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

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

Пример упрощенного кода WXML

<view data-my-data="{{myData}}"> <!-- 这个 view 和下一行的 view 可以合并 -->
  <view class="my-class" data-my-data="{{myData}}" bindtap="onTap">
    <text> <!-- 这个 text 通常是没必要的 -->
      {{myText}}
    </text>
  </view>
</view>

<!-- 可以简化为 -->

<view class="my-class" data-my-data="{{myData}}" bindtap="onTap">
  {{myText}}
</view>

4.2 Повторный рендеринг

После первоначального рендеринга слой представления можно применять несколько раз.setDataДанные. каждое приложениеsetDataПри наличии данных выполняется повторный рендеринг для обновления интерфейса. Данные и текущее дерево узлов, полученные при первоначальном рендеринге, сохраняются для повторного рендеринга. Каждый раз, когда вы повторно рендерите,dataиsetDataДанные применяются к фрагменту WXML, в результате чего создается новое дерево узлов. Затем новое дерево узлов сравнивается с текущим деревом узлов, поэтому вы можете увидеть, какие свойства каких узлов необходимо обновить, а какие добавить или удалить. Наконец, будетsetDataданные объединены вdataи замените старое дерево узлов новым деревом узлов для следующего повторного рендеринга.

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

5. Используйте пользовательские компоненты

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

6. Избегайте неправильного использования onPageScroll

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

Суммировать

Производительность загрузки при запуске мини-программы

  • Контролируйте размер пакета кода

  • Загрузка подпакета

  • Первый экран (предварительный запрос, использование кеша, избегание белого экрана, своевременная обратная связь)

производительность рендеринга апплета

  • Избегайте неправильного использования setData

  • Разумное использование сообщений об инцидентах

  • Избегайте неправильного использования onPageScroll

  • Оптимизация узлов просмотра

  • Используйте пользовательские компоненты