Рубрики
Без рубрики

Избегайте этого общего анти-образного узора в Pull-Stage Vue / Laravel Apps

Я вижу много приложений Larave, используя AJAX, чтобы отправить начальное состояние приложения в клиент Vue.js. Эта дополнительная круговая поездка на сервер задержать страницу интерактивности без необходимости. В этой статье я продемонстрирую альтернативный метод, который гибкий и простой для реализации.

Автор оригинала: Anthony Gore.

Если вы хотите ваше одностранное приложение Vue.js, чтобы общаться с Backend Laravel, вы, вполне разумно, думаете об использовании AJAX. Действительно, Laravel поставляется с библиотекой Axios, загруженной по умолчанию.

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

Я вижу, что многие приложения Vue/Laravel Apports, архивационные таким образом. Альтернатива этой антиграмме состоит в том, чтобы ввести начальное состояние приложения в головку страницы HTML, поэтому она доступна для приложения, как только это необходимо. Затем Ajax можно использовать более правильно для последующих устройств данных.

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

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

Примечание: эта статья была первоначально опубликована здесь на блоге разработчиков Vue.js на 2017/08/07.

Передача данных в Vue от laravel

Вот пример Full-Stage Vue/Laravel App, которое я построен для Office Time, фиктивный винтажный автомобильный ритейлер. Приложение имеет переднюю страницу, которая показывает доступные автомобили, а также общая детализация, которая показывает специфику конкретной модели.

Это приложение использует Vue Router для обработки навигации страницы. Каждая страница нуждается в данных из бэкэнда (например, название модели автомобиля, цена и т. Д.), поэтому требуется механизм отправки его между Vue и Laravel. Стандартный шаблон дизайна предназначен для настройки конечных точек API для каждой страницы в Laravel, а затем используйте Vuue Router’s Beforereenter Крюк для асинхронного загрузки данных через AJAX перед переходами страницы.

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

Устранение запроса AJAX здесь сделает страницу интерактивной намного раньше, особенно на медленных интернет-соединениях.

Инъекционное начальное заявление государства

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

Мы можем реализовать это с помощью JSON-кодирования государственной серверной стороной и назначением его глобальной переменной:

index.html.


...

  ...
  


  

Затем он тривиален для приложения для доступа и использования состояния:

let initialState = JSON.parse(window.__INITIAL_STATE__);

new Vue({
  ...
})

Этот подход устраняет необходимость запроса AJAX и уменьшает начальную процесс загрузки приложения к этому:

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

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

Реализация в приложении с несколькими маршрутами

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

Это означает, что у нас есть следующие проблемы для решения:

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

Типы навигации

Vue Router может захватить любые изменения маршрута, которые возникают из На странице и обрабатывать их без обновления страницы. Это означает нажатие ссылок или команды JavaScript, которые меняют местоположение браузера.

Но маршрут меняется из браузера e.g. Бар URL или ссылки на приложение с внешних страниц, не могут быть перехвачены Vue Router и приведут к загрузке свежей страницы.

Core Concept рисунка дизайна

Имея в виду, нам нужно убедиться, что каждая страница имеет необходимую логику, чтобы получить свои данные из либо Инъекция на страницу или через ajax, в зависимости от того, загружается ли страница свежего с сервера, или Vue Routeer.

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

Вы можете увидеть полный код в этом Github Repo Отказ

Настройка Backend

Маршруты

Поскольку сайт имеет две страницы, есть два разных маршрута для обслуживания: Главная Маршрут, а деталь маршрут. Шаблон дизайна требует, чтобы маршруты подавали либо виды, либо как полезные нагрузки JSON, поэтому я создал как веб-маршруты API для каждого:

маршруты/web.php.

Маршруты/API.PHP.

Контроллер

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

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

Приложение/HTTP/Контроллеры/Carcontroller.php

 '/detail/' . $id], $this->get_cars($id));
      return view('app', ['state' => $state]);
  }

  /* Returns a JSON payload */
  public function detail_api($id)
  {
      $state = array_merge([ 'path' => '/detail/' . $id], $this->get_cars($id));
      return response()->json($state);
  }

  public function home_web() { ... }

  public function home_api() { ... }
}

Вид

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

Ресурс/Просмотры/app.blade.php





  


  

Настройка Frontend

Маршрутизатор

Frestend App App использует стандартную настройку Vue маршрутизатора. У меня есть другой компонент для каждой страницы I.E. Home.vue и Detail.vue Отказ

Обратите внимание, что маршрутизатор в Режим истории Потому что я хочу, чтобы каждый маршрут лечился отдельно.

Ресурсы/Активы/js/app.js

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

import Home from './components/Home.vue';
import Detail from './components/Detail.vue';

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '/', component: Home },
    { path: '/detail/:id', component: Detail }
  ]
});

const app = new Vue({
  el: '#app',
  router
});

Страница компонентов

В компонентах страницы очень мало происходит. Ключевая логика находится в Мистин Что я покажу дальше.

Home.vue.vue.



Смешин

Этот микс должен быть добавлен в Все Компоненты страницы, в этом случае Главная и Деталь Отказ Вот как это работает:

  1. Добавляет Beforereenter Крюк для каждого компонента страницы. Когда приложение первые нагрузки, или всякий раз, когда маршрут меняется, этот крючок вызывается. Это в свою очередь называет getdata метод.
  2. getdata Метод загружает впрыщенное состояние и проверяет путь имущество. Из этого он определяет, может ли он использовать введенные данные или если он должен получить новые данные. Если последний, он просит соответствующую конечную точку API с помощью клиента AXIOS HTTP.
  3. Когда обещание вернулось из getdata решает, Beforereenter Крюк будет использовать любые данные, которые возвращаются и назначают его данные свойство этого компонента.

mixin.js.

import axios from 'axios';

let getData = function(to) {
  return new Promise((resolve, reject) => {
    let initialState = JSON.parse(window.__INITIAL_STATE__) || {};
    if (!initialState.path || to.path !== initialState.path) {
      axios.get(`/api${to.path}`).then(({ data }) => {
        resolve(data);
      })
    } else {
      resolve(initialState);
    }
  });
};

export default {
  beforeRouteEnter (to, from, next) {
    getData(to).then((data) => {
      next(vm => Object.assign(vm.$data, data))
    });
  }
};

Реализуя эту микн, компоненты страницы имеют необходимую логику для получения их начального состояния из данных, введенных в страницу, либо через AJAX, в зависимости от того, загружена страница с сервера, или была навещена от Vue Router.

Улучшения производительности для старых автомобилей времени

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

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

Одной метрики актуальности является Время первой осмысленной краски , который вот 2570 мс.

Давайте сравним это с улучшенной архитектурой:

Путем загрузки исходного состояния приложения из на странице, а не из API, время для первой значимой краски до 2050 мс, улучшение на 25%.

Стать старшим Vue Developer в 2020 году.

Учитесь и осваивайте, какие профессионалы знают о строительстве, тестировании и развертывании, полностью стековых Vue Apps в нашем последнем курсе.

Учить больше