24

在 3G 下的 iPad 上连接到http://www.manage-us.com [曾经] 会导致 JavaScript 错误,如果开发者控制台已启用,则可以看到该错误。如果在 WiFi 连接下使用同一 iPad 访问同一页面,则不会显示错误。[错误现在已经消失,因为我应用了下面的修复程序!]。

为什么是这样?

我尝试在 Mac 上的 Safari 和 Mac 上的 iPad 模拟器上模拟低带宽(使用 dummynet)。这不会重现问题。

我目前怀疑这是我在英国 (O2) 的移动运营商引入的一个问题,众所周知,它会通过代理缓存修改某些内容,例如降级图像文件。如果您可以确认通过其他移动运营商在 iPad 或 iPhone 上通过 3G 连接时没有遇到此问题,那将很有帮助。

4

2 回答 2

34

我对此进行了进一步调查,发现问题在于英国移动运营商 O2(Apple 最初的独家 iPhone 运营商)在将 Web 内容发送到 iPhone 和 iPad 之前对其进行了修改。可能在将其发送到任何运行移动浏览器的设备之前。

它们不确定地将一些 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 形式提供,则一如既往地不起作用。

于 2010-07-20T16:43:47.500 回答
1

对于需要在 ASP.NET 中解决此问题的任何人,这将根据http://stuartroebuck.blogspot.com/2010/08/official-way-to-bypassing-data.html为 javascript 文件设置 Cache-Control 标头,使用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>
于 2012-02-09T13:29:54.170 回答