Веб-сайт показывает ошибку JavaScript на iPad / iPhone под 3G, но не под WiFi

подключение к http://www.manage-us.com на iPad под 3G [используется для] привести к ошибке JavaScript, который можно увидеть, если консоль разработчика была включена. Если доступ к той же странице осуществляется с помощью того же iPad при подключении WiFi, ошибка не отображается. [Ошибка теперь ушла, потому что я применил исправление ниже!].

Почему это?

Я пробовал имитировать низкую пропускную способность (используя dummynet) на Safari на Mac и на симуляторе iPad на Mac. Это не воспроизводит проблему.

в настоящее время я подозреваю, что это проблема, вводимая моим оператором мобильной связи в Великобритании (O2), который, как известно, изменяет некоторый контент через прокси-кэш, такой как понижение файлов изображений. Если вы можете подтвердить, что вы не испытываете эту проблему при подключении 3G на iPad или iPhone через другого оператора мобильной связи, что было бы полезно.

2 ответов


Я исследовал это дальше и обнаружил, что проблема в том, что оператор мобильной связи Великобритании O2 (оригинальный эксклюзивный оператор iPhone для Apple) изменяет веб-контент перед отправкой его на iPhones и iPads. Вероятно, перед отправкой на любое устройство с мобильным браузером.

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

эти изменения также лишают авторских сообщений из защищенных авторским правом библиотек javascript и библиотек css и играют хаос с оптимизацией доставки.

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

Я написал блог о проблеме здесь в надежде, что если привлечь немного больше внимания к этому: http://stuartroebuck.blogspot.com/2010/07/mobile-proxy-cache-content-modification.html

мой обходной путь-использовать document.write() для вставки зависимостей библиотеки JavaScript во время загрузки и предотвращения их вставки O2. Это, кажется, работает весьма неплохо. например:

<script type="text/javascript">
// <![CDATA[
// Using document.write to load JavaScript dependencies to bypass O2 network inlining of JavaScript.
function loadJS(file){document.write("<" + "script type='text/javascript' src='" + file + "'></" + "script>")}
loadJS("/js/jquery-1.4.2.min.js");
loadJS("/js/myJSLibrary.js");
// ]]>
</script>

обратите внимание, что, как всегда, document.write не будет работать, если страница обслуживается как XHTML.


для тех, кто нуждается решение этого в ASP.NET это задает заголовок Cache-Control как в http://stuartroebuck.blogspot.com/2010/08/official-way-to-bypassing-data.html для файлы JavaScript, используя модуль переопределения URL-адресов 2.0 http://learn.iis.net/page.aspx/665/url-rewrite-module-20-configuration-reference.

<system.webServer>
        <rewrite>
            <outboundRules>
                <rule name="Compression header" preCondition="Match JS Files">
                    <match serverVariable="RESPONSE_Cache-Control" pattern="(.*)" />
                    <action type="Rewrite" value="no-transform" />
                </rule>
                <preConditions>
                    <preCondition name="Match JS Files">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="(javascript)$" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>

Альтернативно можно сделать с помощью HttpModule

public class AddHeaderModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.EndRequest += OnEndRequest;
    }

    void OnEndRequest(object sender, System.EventArgs e)
    {
        if(HttpContext.Current.Response.ContentType.Contains("javascript"))
            HttpContext.Current.Response.Headers.AddHeader("Cache-Control", "no-transform");
    }
}

и

<configuration>
   <system.web>
      <httpModules>
         <add name="AddHeaderModule" type="your.namespace.AddHeaderModule" />
      </httpModules>
   </system.web>
</configuration>