当前位置: 首页 > 面试题库 >

在构建时即时连接或最小化JavaScript-ASP.NET MVC

巫马松
2023-03-14
问题内容

作为此问题的扩展,在用户控件中链接JavaScript库的过程中,我正在研究一些示例,这些示例说明了人们如何在构建时动态地串联和最小化JavaScript。我也想看看它如何进入您的母版页。

我不介意像现在这样将页面特定的文件进行最小化和单独链接(请参阅下文),但是我希望将主主页上的所有JavaScript文件(大约有5或6个)连接在一起并进行缩小。

凡是还结合了CSS串联和缩小功能的人,都将获得积分!:-)

当前的母版页,其中包含我想串联和缩小的常见JavaScript文件:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<head runat="server">
    ... BLAH ...
    <asp:ContentPlaceHolder ID="AdditionalHead" runat="server" />
    ... BLAH ...
    <%= Html.CSSBlock("/styles/site.css") %>
    <%= Html.CSSBlock("/styles/jquery-ui-1.7.1.css") %>
    <%= Html.CSSBlock("/styles/jquery.lightbox-0.5.css") %>
    <%= Html.CSSBlock("/styles/ie6.css", 6) %>
    <%= Html.CSSBlock("/styles/ie7.css", 7) %>
    <asp:ContentPlaceHolder ID="AdditionalCSS" runat="server" />
</head>
<body>
    ... BLAH ...
    <%= Html.JSBlock("/scripts/jquery-1.3.2.js", "/scripts/jquery-1.3.2.min.js") %>
    <%= Html.JSBlock("/scripts/jquery-ui-1.7.1.js", "/scripts/jquery-ui-1.7.1.min.js") %>
    <%= Html.JSBlock("/scripts/jquery.validate.js", "/scripts/jquery.validate.min.js") %>
    <%= Html.JSBlock("/scripts/jquery.lightbox-0.5.js", "/scripts/jquery.lightbox-0.5.min.js") %>
    <%= Html.JSBlock("/scripts/global.js", "/scripts/global.min.js") %>
    <asp:ContentPlaceHolder ID="AdditionalJS" runat="server" />
</body>

在这样的页面中使用(我很满意):

<asp:Content ID="signUpContent" ContentPlaceHolderID="AdditionalJS" runat="server">
    <%= Html.JSBlock("/scripts/pages/account.signup.js", "/scripts/pages/account.signup.min.js") %>
</asp:Content>

更新: 目前(2013年末)的建议:

我会看一下Microsoft
ASP.NET的内置捆绑和缩小。


问题答案:

尝试这个:

我最近完成了相当多的研究工作,并随后进行了一些开发工作,这些工作对提高Web应用程序前端的性能大有帮助。我以为我会在这里分享基本的解决方案。

首先要做的是使用Yahoo的YSlow和Google的PageSpeed对您的网站进行基准测试。这些将凸显出“垂头丧气”的性能改进。除非您已经这样做,否则最终的建议几乎肯定会包括组合,缩小和gzip您的静态内容。

我们将要执行的步骤是:

编写一个自定义HTTPHandler来组合和缩小CSS。编写一个自定义HTTPHandler来组合和缩小JS。包括一种机制,以确保上述内容仅在应用程序不处于调试模式时才能发挥作用。编写自定义服务器端Web控件以轻松维护css / js文件的包含。在IIS 6上启用某些内容类型的GZIP。首先,让我们从实现.NET IHttpHandler接口的CSSHandler.asax开始:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

namespace WebApplication1
{
    public class CssHandler : IHttpHandler
    {
        public bool IsReusable { get { return true; } }

        public void ProcessRequest(HttpContext context)
        {
            string[] cssFiles = context.Request.QueryString["cssfiles"].Split(',');

            List<string> files = new List<string>();
            StringBuilder response = new StringBuilder();
            foreach (string cssFile in cssFiles)
            {
                if (!cssFile.EndsWith(".css", StringComparison.OrdinalIgnoreCase))
                {
                    //log custom exception
                    context.Response.StatusCode = 403;
                    return;
                }

                try
                {
                    string filePath = context.Server.MapPath(cssFile);
                    string css = File.ReadAllText(filePath);
                    string compressedCss = Yahoo.Yui.Compressor.CssCompressor.Compress(css);
                    response.Append(compressedCss);
                }
                catch (Exception ex)
                {
                    //log exception
                    context.Response.StatusCode = 500;
                    return;
                }
            }

            context.Response.Write(response.ToString());

            string version = "1.0"; //your dynamic version number 

            context.Response.ContentType = "text/css";
            context.Response.AddFileDependencies(files.ToArray());
            HttpCachePolicy cache = context.Response.Cache;
            cache.SetCacheability(HttpCacheability.Public);
            cache.VaryByParams["cssfiles"] = true;
            cache.SetETag(version);
            cache.SetLastModifiedFromFileDependencies();
            cache.SetMaxAge(TimeSpan.FromDays(14));
            cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        }
    }
}

好的,现在一些解释:

IsReUsable属性:

我们没有处理任何特定于实例的事情,这意味着我们可以安全地重用处理程序的同一实例来处理多个请求,因为我们的ProcessRequest是线程安全的。更多信息。

ProcessRequest方法:

这里没有什么太忙的事情。我们正在遍历提供给我们的CSS文件(请参阅下面的CSSControl,了解它们的输入方式),并使用Yahoo的YUICompressor的.NET端口压缩每个文件,然后再将内容添加到输出响应流中。

该方法的其余部分涉及设置一些HTTP缓存属性,以进一步优化浏览器客户端下载(或视情况而定)下载内容的方式。

我们在代码中设置了Etags,以便它们在服务器场中的所有计算机上都相同。我们在实际文件上设置了响应和缓存依赖关系,因此,如果替换它们,缓存将失效。我们设置可缓存性,以便代理可以缓存。我们使用cssfiles属性来VaryByParams,以便我们可以缓存通过处理程序提交的每个CSS文件组。这是CSSControl,它是继承.NET LiteralControl的自定义服务器端控件。

面前:

<customcontrols:csscontrol id="cssControl" runat="server">
  <CustomControls:Stylesheet File="main.css" />
  <CustomControls:Stylesheet File="layout.css" />
  <CustomControls:Stylesheet File="formatting.css" />
</customcontrols:csscontrol>

背部:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Linq;
using TTC.iTropics.Utilities;

namespace WebApplication1
{
    [DefaultProperty("Stylesheets")]
    [ParseChildren(true, "Stylesheets")]
    public class CssControl : LiteralControl
    {
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public List<Stylesheet> Stylesheets { get; set; }

        public CssControl()
        {
            Stylesheets = new List<Stylesheet>();
        }

        protected override void Render(HtmlTextWriter output)
        {
            if (HttpContext.Current.IsDebuggingEnabled)
            {
                const string format = "<link rel=\"Stylesheet\" href=\"stylesheets/{0}\"></link>";

                foreach (Stylesheet sheet in Stylesheets)
                    output.Write(format, sheet.File);
            }
            else
            {
                const string format = "<link type=\"text/css\" rel=\"Stylesheet\" href=\"stylesheets/CssHandler.ashx?cssfiles={0}&version={1}\"/>";
                IEnumerable<string> stylesheetsArray = Stylesheets.Select(s => s.File);
                string stylesheets = String.Join(",", stylesheetsArray.ToArray());
                string version = "1.00" //your version number

                output.Write(format, stylesheets, version);
            }

        }
    }

    public class Stylesheet
    {
        public string File { get; set; }
    }
}

HttpContext.Current.IsDebuggingEnabled已连接到web.config中的以下设置:

<system.web>
  <compilation debug="false">
</system.web>

因此,基本上,如果您的站点处于调试模式,则将获得如下所示的HTML标记:

<link rel="Stylesheet" href="stylesheets/formatting.css"></link>
<link rel="Stylesheet" href="stylesheets/layout.css"></link
<link rel="Stylesheet" href="stylesheets/main.css"></link>

但是,如果您处于生产模式(debug = false),则将获得如下标记:

<link type="text/css" rel="Stylesheet" href="CssHandler.ashx?cssfiles=main.css,layout.css,formatting.css&version=1.0"/>

然后,后者显然将调用CSSHandler,它将负责组合,最小化和缓存读取静态CSS内容。

然后,您还可以为静态JavaScript内容复制以上所有内容:

`JSHandler.ashx:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

namespace WebApplication1
{
    public class JSHandler : IHttpHandler
    {
        public bool IsReusable { get { return true; } }

        public void ProcessRequest(HttpContext context)
        {
            string[] jsFiles = context.Request.QueryString["jsfiles"].Split(',');

            List<string> files = new List<string>();
            StringBuilder response = new StringBuilder();

            foreach (string jsFile in jsFiles)
            {
                if (!jsFile.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
                {
                    //log custom exception
                    context.Response.StatusCode = 403;
                    return;
                }

                try
                {
                    string filePath = context.Server.MapPath(jsFile);
                    files.Add(filePath);
                    string js = File.ReadAllText(filePath);
                    string compressedJS = Yahoo.Yui.Compressor.JavaScriptCompressor.Compress(js);
                    response.Append(compressedJS);
                }
                catch (Exception ex)
                {
                    //log exception
                    context.Response.StatusCode = 500;
                    return;
                }
            }

            context.Response.Write(response.ToString());

            string version = "1.0"; //your dynamic version number here

            context.Response.ContentType = "application/javascript";
            context.Response.AddFileDependencies(files.ToArray());
            HttpCachePolicy cache = context.Response.Cache;
            cache.SetCacheability(HttpCacheability.Public);
            cache.VaryByParams["jsfiles"] = true;
            cache.VaryByParams["version"] = true;
            cache.SetETag(version);
            cache.SetLastModifiedFromFileDependencies();
            cache.SetMaxAge(TimeSpan.FromDays(14));
            cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        }
    }
}

及其随附的JSControl:

面前:

<customcontrols:JSControl ID="jsControl" runat="server">
  <customcontrols:Script File="jquery/jquery-1.3.2.js" />
  <customcontrols:Script File="main.js" />
  <customcontrols:Script File="creditcardpayments.js" />
</customcontrols:JSControl>

背部:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Linq;

namespace WebApplication1
{
    [DefaultProperty("Scripts")]
    [ParseChildren(true, "Scripts")]
    public class JSControl : LiteralControl
    {
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public List<Script> Scripts { get; set; }

        public JSControl()
        {
            Scripts = new List<Script>();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (HttpContext.Current.IsDebuggingEnabled)
            {
                const string format = "<script src=\"scripts\\{0}\"></script>";

                foreach (Script script in Scripts)
                    writer.Write(format, script.File);
            }
            else
            {
                IEnumerable<string> scriptsArray = Scripts.Select(s => s.File);
                string scripts = String.Join(",", scriptsArray.ToArray());
                string version = "1.0" //your dynamic version number
                const string format = "<script src=\"scripts/JsHandler.ashx?jsfiles={0}&version={1}\"></script>";

                writer.Write(format, scripts, version);
            }
        }
    }

    public class Script
    {
        public string File { get; set; }
    }
}

启用GZIP:

正如Jeff Atwood所说,在您的网站服务器上启用Gzip是一件容易的事。经过一些跟踪,我决定在以下文件类型上启用Gzip:

.css .js .axd(Microsoft Javascript文件).aspx(常规ASP.NET Web窗体内容).ashx(我们的处理程序)要在IIS 6.0 Web服务器上启用HTTP压缩,请执行以下操作:

打开IIS,右键单击“网站”,“服务”选项卡,启用“压缩应用程序文件”和“压缩静态文件”。停止IIS在记事本中打开IIS元数据库(C:\ WINDOWS \ system32 \ inetsrv \ MetaBase.xml)–如果需要,请进行备份。担心这些事情,找到并覆盖以下两个IIsCompressionScheme和一个IIsCompressionSchemes元素:

就是这样!这节省了我们大量的带宽,并且使整个Web应用程序的响应速度更快。



 类似资料:
  • 问题内容: 我是Java的初学者,也是我的一项工作。我必须做数据库操作。我有用于将数据插入数据库的Java代码,它工作正常。 我的问题是,每次代码运行时,我的代码都必须创建一个数据库连接和准备好的语句对象,据我所知,这是一项昂贵的操作。 有什么方法可以保持与数据库的单个连接并使用该连接来执行数据库工作? 问题答案: 您可以像这样使用设计模式Singleton Connection: 1-创建一个类

  • 我得到错误,而建立gradle(IDE工具版本3.1.3Android)Android版本: 3.1.3 gradle版本: 4.4无法下载文件下面时gradle同步下载https://jcenter.bintray.com/com/android/tools/build/gradle/3.1.3/gradle-3.1.3.pom21秒215毫秒 下载https://dl.google.com/d

  • 问题内容: 我正在与一个名为CommWeb的商户帐户集成,并向其URL(https://migs.mastercard.com.au/vpcdps)发送一个SSL帖子。当我尝试发送帖子时,出现以下异常: 执行该帖子的代码(我没有写过,并且已经存在于我们的代码库中)是: 商户帐户集成的文档对证书一无所知。他们确实提供了一些似乎盲目接受证书的示例JSP代码: 我们的Web应用程序有一个密钥库,我尝试使

  • 这与以下内容有关: 卡皮坦岛的Safari 9.1 塞拉山的Safari 10 当浏览器或选项卡失去焦点(主要是最小化)时,有人知道Safari在JavaScript引擎中对setTimeout()做了什么吗? 我创建了一个简单的JavaScript web应用程序,我在Safari中加载该应用程序,它调用JavaScript setTimeout(),并在超时值之后传递另一个要执行的函数。该函数

  • 这个问题在互联网上一次又一次地出现(即使是在SO上),但我还没有找到一个令人满意的解决方法: 如何在运行的web应用程序中更改/替换Javascript代码,而不重新加载页面? 很多人对此的回答是“你不能,因为这是不可能的”。IntelliJ IDEAs live edit插件的一些实验证明了这是可能的。但我不想为这个特性绑定到IDE。(加分:与浏览器无关) 下面是我尝试的: 将//#source

  • 问题内容: 有没有一种方法可以使用Jenkinsfile 脚本化管道 语法来触发Jenkins作业每小时运行一次? 我看到了使用声明性语法的示例,但没有使用管道语法的示例。 声明式语法示例 问题答案: 您可以将此代码段用于: 属性的参考在这里。您可以搜索“ pipelineTriggers”字符串,并发现生成触发器可能是例如人工制品或此列表中的其他内容(从链接的文档页面中提取了2019-03-23