Комплексное решение Vue, совместимое с ie9

внешний интерфейс браузер Vue.js axios

предисловие

задний план

  • vue - 2.5.11
  • vue-cli использует шаблоныwebpack-simple
  • HTTP-запрос: аксиомы

Официальное описание Vue совместимости версии браузера IE — ie9+, то есть ie9 и более поздние версии. После тестирования основной фреймворк Vuevuejsсам по себе, а также официальные основные плагины экосистемы (VueRouter, Vuex и т. д.) могут нормально использоваться на ie9.

Автор Vue You Yuxi ForУчебные предложения для VueУпоминается, что для того, чтобы сделать проект более экологичным/инженерным, необходимо максимально изучить и использовать новую спецификацию ECMAScript. В настоящее время ES6/ES2015 является спецификацией с высокой доступностью и стабильностью, и документы полны.Также есть Ruan Yifeng в Китае.Начало работы с ECMAScript 6Было выполнено большое количество переводов документов, а среду разработки можно охарактеризовать как идеальную. Однако старые браузеры не поддерживают спецификацию es6, особенно браузер ie, даже самая высокая версия ie11 не полностью поддерживает спецификацию es6. В этом случае требуется обработка совместимости для всех браузеров, которые изначально не поддерживают функции ES6.

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

ES6-совместимый

В среде ie9 не поддерживаются некоторые новые объекты и выражения es6.Решением является использованиеbabel-polyfillКомпонент, который может переводить код es6 в код es5, который может быть распознан браузерами более ранних версий.

npm i babel-polyfill --save-dev

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

import 'babel-polyfill';

использовать в проектеvue-cliСгенерированный код, корневой каталог.babelrcфайл, который является конфигурационным файлом для проекта, использующего babel. В содержимом сгенерированного шаблона по умолчанию добавьте"useBuiltIns": "entry"Содержимое параметра, который является параметром, указывающим, какой контент должен быть полифиллированным (совместимым).

useBuiltIns имеет три параметра настройки

  • false- ничего не делать
  • entry- В соответствии с поддержкой версии браузера требования к полифиллу разделены и введены, и введены только те полифиллы, которые не поддерживаются браузером.
  • usage- В коде обнаруженияES6/7/8и т. д., загружайте только те полифилы, которые используются в коде

Рекомендуемая настройка здесьentry,полный.babelrcСодержание следующее:

{
  "presets": [
    [
      "env",
      {
        "modules": false,
        "useBuiltIns": "entry"
      }
    ],
    "stage-3"
  ]
}

После добавления этих кодов большая часть контента в проекте совместима с версией ie9.

Числовой объект

даже при использованииbabel-polyfillПосле перевода кода я обнаружил, что в es6 все еще есть некоторые новые функции, которые не были решены, такие какNumberобъектparseIntа такжеparseFloatметод

es6 будет глобальным методомparseInt()а такжеparseFloat(), портировано наNumberВышеуказанные объекты поведение полностью без изменений. Цель состоит в том, чтобы постепенно уменьшить глобальный подход, так что постепенно модульный язык.

Для решения этой проблемы не нужно вводить пакет для ее решения, в том числе в основной входной файл проекта.main.jsДобавьте следующий код (код должен быть как можно раньше, желательно перед ссылкойbabel-polyfillПозже )

if (Number.parseInt === undefined) Number.parseInt = window.parseInt;
if (Number.parseFloat === undefined) Number.parseFloat = window.parseFloat;

Метод requestAnimationFrame

window.requestAnimationFrameЭто интерфейс, используемый браузерами для операций с временным циклом, аналогичныйsetTimeout, основная цель — перерисовать веб-страницу кадр за кадром.

requestAnimationFrameПреимущество заключается в том, чтобы в полной мере использовать механизм обновления дисплея для экономии системных ресурсов. На дисплее есть фиксированная частота обновления (60 Гц или 75 Гц), то есть может повторно окрашена в 60 раз или в 75 раз в секунду.requestAnimationFrameОсновная идея состоит в том, чтобы идти в ногу с этой частотой обновления и использовать эту частоту обновления для перерисовки страницы. Кроме того, при использовании этого API обновления автоматически останавливаются, когда страница не находится на текущей вкладке браузера. Это экономит CPU, GPU и энергию.

Но есть одно замечание,requestAnimationFrameвыполняется в основном потоке. Это означает, что если основной поток очень занят,requestAnimationFrameЭффект анимации будет значительно снижен.

window.requestAnimationFrame()Метод сообщает браузеру, что вы хотите выполнить анимацию, и просит браузер вызвать указанную функцию для обновления анимации перед следующей перерисовкой. Этот метод принимает в качестве параметра функцию обратного вызова, которая будет вызываться перед перерисовкой браузера.

Некоторые сторонние компоненты используют этот метод, например некоторые компоненты загрузки файлов и обработки изображений; затем, когда этот тип компонента используется в ie9, он сообщит

SCRIPT5007: Expected object.

window.requestAnimationFrame()Минимальная совместимая версия IE - это 10, то, чтобы сделать его совместимым на IE9, вам нужно сделать запросанимационную поверхность полифиллирования

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

Суть:requestAnimationFrame polyfill

Эта часть кода также выполняется при входе на сайт, насколько это возможно.

сетевой запрос http (междоменный)

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

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

Установите фон здесь:

  • На сервере полностью включена междоменная поддержка CROS
  • http-компонент использует axios
  • настройки аксиомwithCredentialsУстановите значение true, чтобы передавать данные cookie при включении междоменного доступа.

Браузеры с высокой версией (например, 10+ или chrome, ff) должны выполнять функции в фоновом режиме только для поддержки функции междоменного запроса данных.

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

ie8/ie9XMLHttpRequestObject, не поддерживает междоменный доступ, этот объект изначально поддерживает только междоменный доступ после ie10. Решение Microsoft предоставляется в ie8 / ie9XDomainRequest(XDR) для решения междоменных проблем, хотя с помощью этого объекта можно успешно получить междоменный доступ и вернуть данные, он все еще является полуфабрикатом с неполными функциями, и его использование имеет много ограничений:

  • XDR поддерживает только методы запросов GET и POST.
  • XDR не поддерживает настраиваемые заголовки запросов, если сервер используетheaderПользовательские параметры для аутентификации недоступны
  • заголовок запросаContent-TypeРазрешается устанавливать толькоtext/plain
  • XDR не разрешает межпротокольные запросы.Если веб-страница находится под протоколом HTTP, она может запрашивать интерфейс только по протоколу HTTP и не может получить доступ к интерфейсу HTTPS.
  • XDR принимает только запросы HTTP/HTTPS
  • При инициировании запроса он не будет выполнятьauthenticationилиcookies

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

Идеальное решение: прокси

Хотя axios бессилен для кросс-доменного ie9, решение, упакованное фронтенд-проектамиwebpackОбеспечивает элегантное и тщательное решение проблемы:играет роль

devServer.proxy

веб-пакетdevServer.proxyФункция определяетсяhttp-proxy-middlewareпроект для достижения

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

Конфигурация webpack.config.js в проекте

devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true,
    proxy: {
        '/api': {
            target: 'http://localhost:8081/myserver',
            pathRewrite: {
                '^/api': ''
            }
        }
    }
}

В конфигурации указано, чтоhttp://localhost:8081/myserverПрокси-сервер местоположения службы предназначен для локальной внешней службы.http://localhost:8080/api. Например, исходный запрос на чтение информации о пользователеhttp://localhost:8081/myserver/user/zhangsan, после прокси становитсяhttp://localhost:8080/api/user/zhangsan.

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

Тем не менее, веб-пакетdevServer.proxyДоступно только в режиме разработки, а не в режиме производства. В режиме разработки служба отладки может читатьwebpack.config.jsСодержимое конфигурации на сервере проксируется в режиме реального времени, и перед развертыванием проекта в производственной среде проект необходимо скомпилировать и преобразовать в статический js-файл.Без поддержки службы отладки прокси-сервер запроса не может быть выполнено.

конфигурация nginx

несмотря на то чтоdevServer.proxyФункция Vue может работать только в режиме разработки, поэтому в режиме производства, естественно, есть решение; обычно проектам Vue требуется только статический сервер после компиляции в окончательный файл js.nginxДля оптимального выбора малый вес, высокая производительность, высокий уровень параллелизма, служба обратного прокси и т. д. — все это его преимущества.обратный проксиФункция

conf/nginx.confДобавьте следующее в конфигурацию файла

location /api/ {
    proxy_pass http://localhost:8081/myserver/;
}

Эта конфигурация такжеhttp://localhost:8081/myserver/Прокси-сервер местоположения целевого сервера для локальной службы/apiпуть, поэтому проблема запроса данных в производственной среде также может быть решена

Личный оригинальный контент, перепечатка с указанием источника

Полный контент:github.com/TerryZ