Практика оптимизации белого экрана домашней страницы

внешний интерфейс

предисловие

С момента появления трех основных интерфейсных фреймворков — React, Vue и Angular — фронтенд-разработка постепенно стала стандартизированной и унифицированной.В большинстве случаев при создании новых фронтенд-проектов первое, что приходит на ум заключается в том, что используемая технология должна быть одной из трех основных сред. Эта среда дает большие преимущества для разработки интерфейса. Большое удобство и спецификации, но, поскольку все эти три среды основаны на JS, страница не может быть отображена до того, как JS будет проанализирован и загружен, и он будет долгое время находиться на белом экране, что вызывает определенные проблемы с пользовательским интерфейсом.Далее в этой статье я расскажу о некоторых проблемах и мыслях, с которыми я недавно столкнулся при оптимизации белого экрана.

SSR

Когда думаешь о проблеме белого экрана, первое решение, которое приходит на ум, — это рендеринг на стороне сервера. проблему белого экрана и так же решить проблему белого экрана.проблема сео,потому что нет необходимости в динамическом получении данных,но это очень похоже на мой ранний режим разработки при написании бэкенда,фронтенда и back-end связаны между собой, что не способствует сопровождению.В то же время для front-end инженеров,по мере роста требований нужно понимать определенный объем back-end знаний.Хотя есть SSR такие фреймворки, как Nuxt.js, которые помогают нам упростить серверную часть, по-прежнему неизбежно настраивать серверную часть при настройке или устранении ошибок. Стоимость отладки и обслуживания довольно высока, а рендеринг на стороне сервера, который необходимо следует учитывать, что это увеличит нагрузку на сервер и решит проблемы параллелизма, скорости работы и т. д.

предварительный рендеринг

Это решение является относительно простым и прямым решением, а стоимость пробной версии относительно низкая.Вот как использовать prerender-spa-plugin для предварительного рендеринга, чтобы его можно было визуализировать в браузере без развертывания кода Vue или React на Выше в качестве примера для настройки возьмите официальную демонстрацию vue-cli3, см. конкретный файл конфигурации:

const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
module.exports = {
  configureWebpack: config => {
    let plugins = []
    plugins.push(new PrerenderSPAPlugin({
      staticDir: path.resolve(__dirname, 'dist'),
      routes: ['/', '/about'],
      minify: {
        collapseBooleanAttributes: true,
        collapseWhitespace: true,
        decodeEntities: true,
        keepClosingSlash: true,
        sortAttributes: true
      },
      renderer: new Renderer({
        renderAfterDocumentEvent: 'custom-render-trigger'
      })
    }))
    config.plugins = [
      ...config.plugins,
      ...plugins
    ]
  }
}

Вышеприведенный код является конфигурацией часто используемого prerender-spa-plugin, адресом файла вывода предварительного рендеринга staticDir, маршрутами для предварительного рендеринга, конфигурацией, связанной с минимизацией сжатия, конфигурацией, связанной с механизмом рендеринга рендерера, вы можете передать в пользовательский механизм рендеринга Или напрямую использовать PuppeteerRenderer по умолчанию, renderAfterDocumentEvent — это атрибут в конфигурации механизма рендеринга, что означает, что предварительный рендеринг выполняется при запуске события.здесьСуществует полное введение в атрибуты механизма рендеринга, что очень важно, особенно для нужд некоторых конкретных сценариев.Конечно, в простых сценариях вы можете напрямую использовать параметры по умолчанию, не настраивая параметры механизма рендеринга.
Затем выполните компиляцию и посмотрите, что произойдет?

Папка, соответствующая маршруту, будет сгенерирована в каталоге dist, откройте index.html

  <div id="app">
   <div id="nav">
    <a href="/" class="router-link-exact-active router-link-active">Home</a> | 
    <a href="/about" class="">About</a>
   </div>
   <div class="home">
    <img alt="Vue logo" src="/img/logo.82b9c7a5.png" />
    <div class="hello" data-v-7b2de9b7="">
     <h1 data-v-7b2de9b7="">Welcome to Your Vue.js App</h1>
     <p data-v-7b2de9b7="">For a guide and recipes on how to configure / customize this project,<br data-v-7b2de9b7="" />check out the <a href="https://cli.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">vue-cli documentation</a>.</p>
     <h3 data-v-7b2de9b7="">Installed CLI Plugins</h3>
     <ul data-v-7b2de9b7="">
      <li data-v-7b2de9b7=""><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" data-v-7b2de9b7="" rel="noopener" target="_blank">babel</a></li>
      <li data-v-7b2de9b7=""><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" data-v-7b2de9b7="" rel="noopener" target="_blank">eslint</a></li>
      <li data-v-7b2de9b7=""><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest" data-v-7b2de9b7="" rel="noopener" target="_blank">unit-jest</a></li>
     </ul>
     <h3 data-v-7b2de9b7="">Essential Links</h3>
     <ul data-v-7b2de9b7="">
      <li data-v-7b2de9b7=""><a href="https://vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">Core Docs</a></li>
      <li data-v-7b2de9b7=""><a href="https://forum.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">Forum</a></li>
      <li data-v-7b2de9b7=""><a href="https://chat.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">Community Chat</a></li>
      <li data-v-7b2de9b7=""><a href="https://twitter.com/vuejs" data-v-7b2de9b7="" rel="noopener" target="_blank">Twitter</a></li>
      <li data-v-7b2de9b7=""><a href="https://news.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">News</a></li>
     </ul>
     <h3 data-v-7b2de9b7="">Ecosystem</h3>
     <ul data-v-7b2de9b7="">
      <li data-v-7b2de9b7=""><a href="https://router.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">vue-router</a></li>
      <li data-v-7b2de9b7=""><a href="https://vuex.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">vuex</a></li>
      <li data-v-7b2de9b7=""><a href="https://github.com/vuejs/vue-devtools#vue-devtools" data-v-7b2de9b7="" rel="noopener" target="_blank">vue-devtools</a></li>
      <li data-v-7b2de9b7=""><a href="https://vue-loader.vuejs.org" data-v-7b2de9b7="" rel="noopener" target="_blank">vue-loader</a></li>
      <li data-v-7b2de9b7=""><a href="https://github.com/vuejs/awesome-vue" data-v-7b2de9b7="" rel="noopener" target="_blank">awesome-vue</a></li>
     </ul>
    </div>
   </div>
  </div>

Для удобства здесь публикуется только код узла приложения. Раньше, когда подключаемый модуль предварительного рендеринга не использовался, узел приложения был пуст и не имел содержимого. От загрузки файла index.html до завершение разбора файла js, узел приложения был пуст. , поэтому страница будет в состоянии белого экрана, но плагин пре-рендеринга компилирует соответствующий маршрут и вставляет его в узел приложения на этапе компиляции, так что содержимое может быть отображено во время процесса анализа js-файла.После завершения анализа js, Vue заменит содержимое в узле приложения содержимым, отображаемым Vue.Давайте посмотрим, в чем разница между рендерингом при отладке chrome: Обычный рендеринг:

Пререндеринг:
Используя функцию захвата экрана загрузки браузера Chrome, можно увидеть, что при обычном рендеринге будет очевидный белый экран, но предварительный рендеринг не будет создавать белый экран, так каковы недостатки предварительного рендеринга?

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

Скелетонный экран

Принцип реализации каркасного экрана аналогичен принципу предварительной загрузки, оба из которых используютPuppeteerФункция сканирования страниц, Puppeteer представляет собой безголовую библиотеку Chromenode из Chrome, которая предоставляет API для захвата SPA и создания предварительно обработанного контента.В отличие от предварительной загрузки, технология каркасного экрана будет генерировать контент с использованием алгоритма после того, как Puppeteer сгенерирует контент. страницы-скелета заменяется, и создается страница-скелет. Page-skeleton-webpack-plugin — это плагин веб-пакета, используемый для создания экрана-скелета. Далее давайте посмотрим, как его использовать, или возьмем сгенерированный официальный проект на vue-cli3 в качестве примера:

<div id="app"><!-- shell --></div>
const SkeletonPlugin = require('page-skeleton-webpack-plugin').SkeletonPlugin
const path = require('path')
module.exports = {
  publicPath: '/',
  outputDir: 'dist',
  configureWebpack: config => {
    let plugins = []
    plugins.push(new SkeletonPlugin({
      pathname: path.resolve(__dirname, './shell'), // pathname为来存储 shell 文件的地址
      staticDir: path.resolve(__dirname, './dist'), // 最好和 `output.path` 相同
      routes: ['/', '/about'], // 将需要生成骨架屏的路由添加到数组中
      port: '7890'
    }))
    config.plugins = [
      ...config.plugins,
      ...plugins
    ]
  },
  chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.plugin('html').tap(opts => {
        console.log(opts[0])
        opts[0].minify.removeComments = false
        return opts
      })
    }
  }
}

Приведенный выше пример представляет собой простую настройку page-skeleton-webpack-plugin, вы можете перейти к полной настройке самостоятельно.githubЧтобы получить, следует отметить, что этот код:

chainWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.plugin('html').tap(opts => {
        console.log(opts[0])
        opts[0].minify.removeComments = false
        return opts
      })
    }
  }

Это необходимо для изменения конфигурации сжатия html-webpack-plugin, встроенного в vue-cli3, и удаления комментариев удаления, поскольку page-skeleton-webpack-plugin вводит комментарии о зависимостях кода при компиляции, а vue-cli3 интегрирует html-webpack- Плагин будет сжимать и удалять комментарии во время компиляции, поэтому его нужно настраивать отдельно, иначе во время компиляции под сгенерированным узлом приложения не будет контента.
Есть еще один момент, на который следует обратить внимание при его использовании: если вы используете код, сгенерированный скаффолдингом vue-cli3, вы можете сообщить об этой ошибке во время выполнения:

Если вы столкнулись с этой ошибкой, как ее решить?githubСоответствующее решение по вышеизложенному уже есть, проблема решена, давайте посмотрим, как ее использовать, после запуска проекта выполните toggleBar в отладчике хрома

На странице будет отображаться кнопка «Предварительный просмотр скелета страницы», и при ее нажатии будет создано новое окно.
В этом окне отображается стиль экрана скелета и код текущей страницы.Вы можете изменить стиль экрана скелета, а затем нажать Сохранить в правом верхнем углу, чтобы сохранить экран скелета соответствующего маршрута в папку, соответствующую имени пути.
Затем выполните компиляцию.После компиляции в staticDir будет сгенерирован HTML-код, соответствующий маршруту.Скелетный экранный код, соответствующий маршруту, вставляется под узлом приложения в этих HTML-файлах, а затем доступ к службе запускается в staticDir, и эффект каркасного экрана можно увидеть:
Из процесса загрузки вы можете увидеть загрузку экрана скелета

Суммировать

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