При полностью рендеринге на стороне сервера (не в Web 2.0) развертывание кода на стороне сервера будет непосредственно обновлять страницы на стороне клиента при перезагрузке страницы. В отличие от этого, в одностраничном приложении на основе React даже после обновления компонентов React все еще будут некоторые клиенты, использующие старую версию компонентов (они получают новую версию только после перезагрузки браузера, что случается редко) -> Если страницы полностью SPA, возможно, что некоторые клиенты обновляют страницы только через несколько часов.

Какие методы следует использовать, чтобы убедиться, что старые версии компонентов больше не используются клиентами?

Обновление: API не изменился, только React Component обновляется с более новой версией.

57
Pahlevi Fikri Auliya 21 Дек 2015 в 06:38

5 ответов

Лучший ответ

Вы можете сделать так, чтобы компонент React отправлял ajax-запрос на ваш сервер при загрузке приложения для получения «версии интерфейса» . В API сервера вы можете сохранить добавочное значение для версии клиента. Компонент React может хранить это значение на клиенте (cookie / локальное хранилище / и т. Д.). Когда он обнаруживает изменение, он может вызвать window.location.reload(true);, который должен заставить браузер отказаться от кэша клиента и перезагрузить SPA. Или, что еще лучше, сообщите конечному пользователю, что будет загружена новая версия, и спросите его, хотят ли они сохранить работу, а затем перезагрузить и т. Д. Зависит от того, что вы хотите сделать.

49
hazardous 21 Дек 2015 в 11:44

Вы можете отправить версию приложения с каждым ответом с любой конечной точки вашего API. Таким образом, когда приложение отправляет какой-либо запрос API, вы можете легко проверить, что есть новая версия, и вам нужна полная перезагрузка. Если версия в ответе API новее, чем версия, хранящаяся в localStorage, установите window.updateRequired = true. И у вас может быть следующий реагирующий компонент, который обертывает react-router Link:

import React from 'react';
import { Link, browserHistory } from 'react-router';

const CustomLink = ({ to, onClick, ...otherProps }) => (
  <Link
    to={to}
    onClick={e => {
      e.preventDefault();
      if (window.updateRequired) return (window.location = to);
      return browserHistory.push(to);
    }}
    {...otherProps}
  />
);

export default CustomLink;

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

Также вы можете показать всплывающее окно: «Там есть обновление, нажмите [здесь], чтобы включить его». если у вас есть только одна страница или ваши пользователи перемещаются очень редко. Или просто перезагрузите приложение, не спрашивая. Это зависит от вашего приложения и пользователей.

5
Yan Takushevich 10 Авг 2017 в 20:02

Аналогично ответу Стива Тейлора, но вместо конечных точек API-версий я бы сделал версию клиентского приложения следующим образом.

С каждым HTTP-запросом отправляйте свой заголовок, например:

X-Client-Version: 1.0.0

Затем сервер сможет перехватить такой заголовок и ответить соответствующим образом.

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

418 - I'm a Teapot

Затем клиент может быть запрограммирован реагировать на такой ответ, обновляя приложение:

window.location.reload(true)

Основная предпосылка заключается в том, что сервер знает о последней версии клиента.

РЕДАКТИРОВАТЬ:

Аналогичный ответ дан здесь.

10
Andy 3 Дек 2017 в 03:34

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

Я добавил метатег в мой файл index.html:

<meta name="version" content="0.0.3"/>

Затем у меня есть очень простой PHP-скрипт в той же папке, что и index.html, который отвечает на простой запрос REST. PHP-скрипт анализирует серверную копию файла index.html, извлекает номер версии и возвращает его. В моем коде SPA каждый раз, когда отображается новая страница, я выполняю ajax-вызов скрипта PHP, извлекаю версию из локального мета-тега и сравниваю их. Если отличается, я запускаю предупреждение для пользователя.

Скрипт PHP:

<?php
include_once('simplehtmldom_1_9/simple_html_dom.php');
header("Content-Type:application/json");
/*
    blantly stolen from: https://shareurcodes.com/blog/creating%20a%20simple%20rest%20api%20in%20php
*/

if(!empty($_GET['name']))
{
    $name=$_GET['name'];
    $price = get_meta($name);

    if(empty($price))
    {
        response(200,"META Not Found",NULL);
    }
    else
    {
        response(200,"META Found",$price);
    }   
}
else
{
    response(400,"Invalid Request",NULL);
}

function response($status,$status_message,$data)
{
    header("HTTP/1.1 ".$status);

    $response['status']=$status;
    $response['status_message']=$status_message;
    $response['content']=$data;

    $json_response = json_encode($response);
    echo $json_response;
}

function get_meta($name)
{
    $html = file_get_html('index.html');
    foreach($html->find('meta') as $e){
        if ( $e->name == $name){
            return $e->content ;
        }
    }
}
0
magic 5 Авг 2019 в 13:32

Какие методы следует использовать, чтобы убедиться, что старые версии компонентов больше не используются клиентами?

Сегодня (2018) многие фронтальные приложения используют сервисные работники. С его помощью можно управлять жизненным циклом вашего приложения несколькими способами.

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

import * as SnackBar from 'node-snackbar';

// ....

// Service Worker
// https://github.com/GoogleChrome/sw-precache/blob/master/demo/app/js/service-worker-registration.js

const offlineMsg = 'Vous êtes passé(e) en mode déconnecté.';
const onlineMsg = 'Vous êtes de nouveau connecté(e).';
const redundantMsg = 'SW : The installing service worker became redundant.';
const errorMsg = 'SW : Error during service worker registration : ';
const refreshMsg = 'Du nouveau contenu est disponible sur le site, vous pouvez y accéder en rafraichissant cette page.';
const availableMsg = 'SW : Content is now available offline.';
const close = 'Fermer';
const refresh = 'Rafraîchir';

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    function updateOnlineStatus() {
      SnackBar.show({
        text: navigator.onLine ? onlineMsg : offlineMsg,
        backgroundColor: '#000000',
        actionText: close,
      });
    }
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
    navigator.serviceWorker.register('sw.js').then((reg) => {
      reg.onupdatefound = () => {
        const installingWorker = reg.installing;
        installingWorker.onstatechange = () => {
          switch (installingWorker.state) {
            case 'installed':
              if (navigator.serviceWorker.controller) {
                SnackBar.show({
                  text: refreshMsg,
                  backgroundColor: '#000000',
                  actionText: refresh,
                  onActionClick: () => { location.reload(); },
                });
              } else {
                console.info(availableMsg);
              }
              break;
            case 'redundant':
              console.info(redundantMsg);
              break;
            default:
              break;
          }
        };
      };
    }).catch((e) => {
      console.error(errorMsg, e);
    });
  });
}

// ....

Есть также элегантный способ проверить наличие обновлений в фоновом режиме, а затем автоматически обновить приложение, когда пользователь нажимает внутреннюю ссылку. Этот метод представлен в ach.codes и обсуждается также в этой теме

4
LIIT 11 Сен 2018 в 12:03