65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Nant 将多个 CSS 文件合并为一个文件并最小化 CSS 和 JavaScript

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (8投票s)

2011年1月2日

CPOL

4分钟阅读

viewsIcon

73607

downloadIcon

863

如何将多个 CSS 文件合并,以及在自动化构建中使用 NAnt 时最小化 CSS 和 JavaScript。

引言

当您在项目中使用了多个 CSS 文件时,每个 CSS 文件都会向服务器发出额外的 HTTP 请求。即使您使用 ASP.NET 主题,它也会分散成多个 CSS 文件。此外,如果您减小 CSS 文件的大小,您的页面加载速度将会更快。

背景

在开发期间,您可能希望将 CSS 组织成多个文件,并带有适当的空格和注释。但是您需要记住,Internet Explorer 6、7 在单个页面中不支持超过 31 个 CSS 文件。在部署时,您可以将多个 CSS 文件合并为一个 CSS 文件,并使用像 YUI compressor 这样的压缩器来减小文件大小,从而更快地加载您的页面。在这里,我提供了一种合并多个 CSS 文件并压缩 CSS 和 JavaScript 文件的方法。

实现

如果您使用 ASP.NET 主题,那么您的页面中将不会有 CSS 链接的直接引用。因此,将多个 CSS 文件合并到一个文件中不会影响整个应用程序。您可以使用 Script Manager 中的复合脚本引用将多个 JavaScript 文件合并到一个文件中 将客户端脚本合并为复合脚本。在这里,我只讨论部署时的过程,这将有助于更快地加载您的页面。所以,我只使用 Nant 来压缩 JavaScript 文件。

为了自动化所有这些过程,我使用了 NAnt 工具。使用 NAnt 中的 Nant 任务可以轻松地将多个文件合并为一个文件。我还使用 YUI compressor 来压缩 CSS 和 JavaScript 文件。

首先,我将在举例之前讨论过程步骤。

  • 将所有 CSS 文件合并为一个文件。NAnt 通过 Nant concat 任务为您提供了一种简单的方法。

  • 合并多个 CSS 文件后,JavaScript 文件将使用 YUI compressor 进行压缩。YUI compressor 可以安全地减小您的 CSS 和 JavaScript 文件的大小。

  • 在项目中创建单个 CSS 文件,并从项目中移除其他未使用的 CSS 文件引用,这样就不会破坏您的设置,并且在部署后您将只有一个压缩后的 CSS 文件。

我在此处附上了我的Nant.build 文件,并且在我之前的两篇文章中,构建自动化的工作流程使用 MSDeploy 和 NAnt 脚本自动发布网站到 IIS,我讨论了我的构建过程的步骤,并在那里描述了 NAnt 脚本。

在本文中,我将使用相同的脚本,并介绍合并 CSS 文件以及压缩 JavaScript 和 CSS 文件的脚本。

我提供了一个代码块,它将多个 CSS 文件合并到一个名为style.css 的文件中,并删除Theme 文件夹中的其他 CSS 文件。

可以使用 Nant concat 任务连接多个文件,该任务在加载 Nant contrib.Task.dll 后可用,为此,您需要注册 NAnt contrib DLL,或者您可以在调用 <concat> 任务之前添加 <loadtasks assembly="${NAntContrib}\NAnt.Contrib.Tasks.dll" />

<target name="css" description="Concatenate CSS source files">
    <loadtasks assembly="${NAntContrib}\NAnt.Contrib.Tasks.dll" />
    <echo message="Building ${BuildDir}\${CssFileLocation}\style.css" />
    <concat destfile="${BuildDir}\${CssFileLocation}\style.css" append="true">
      <fileset>
        <include name="${BuildDir}\${CssFileLocation}\*.css" />
        <exclude name ="${BuildDir}\${CssFileLocation}\default.css"/>
      </fileset>
    </concat>
    <echo message="${BuildDir}\${CssFileLocation}\style.css built." />
    <echo message="delete other files except style.css" />
    <delete>
      <fileset>
        <include name="${BuildDir}\${CssFileLocation}\*.css"/>
        <exclude name="${BuildDir}\${CssFileLocation}\style.css"/>
        <exclude name ="${BuildDir}\${CssFileLocation}\default.css"/>
      </fileset>
    </delete>
    <echo message="delete other files except style.css is done" />
  </target> 

在 theme 文件夹中,我有七个 CSS 文件。您可以看到 CssFileLocation 文件夹中的 CSS 文件被合并到一个名为 style.css 的文件中,但在这里我也排除了 default.css 文件。您可能有一个 CSS 文件将动态加载并具有替代样式,而 style.css 包含这些。所以我排除了项目中的 default.css 文件。在此操作之后,CssFileLocation 文件夹下只有两个 CSS 文件:style.cssdefault.css

为了减小 CSS 文件和 JavaScript 文件的大小,我使用了 YUI compressor。文章 YUI Compressor and NAnt 提供了用于压缩 CSS 和 JavaScript 的优秀脚本文件,我也从中借鉴了代码。这是我的代码

<target name="JavaScript.minify">
    <foreach item="File" property="filename">
      <in>
        <items>
          <include name="${BuildDir}\${JsFileLocation}\**\*.js"/>
          <exclude name ="${BuildDir}\${JsFileLocation}\jquery.min.js"/>
          <exclude name ="${BuildDir}\${JsFileLocation}\jquery.min-vsdoc.js"/>
          <exclude name ="${BuildDir}\${JsFileLocation}\jquery-ui.custom.min.js"/>
        </items>
      </in>
      <do>
        <echo message="${filename}" />
        <exec program="java">
          <arg value="-jar" />
          <arg value="${YUI}" />
          <arg value="--type" />
          <arg value="js" />
          <arg value="-o" />
          <arg value="${filename}.min" />
          <arg value="${filename}" />
        </exec>
        <move file="${filename}.min" tofile="${filename}" overwrite="true" />
      </do>
    </foreach>
  </target> 

在这里,我排除了对jquery.min.*.js 文件的压缩,因为它们已经经过压缩。还有 CSS 压缩代码

 <target name="css.minify" depends="css" description="Minimize CSS files">
    <foreach item="File" property="filename">
      <in>
        <items>
          <include name="${BuildDir}\${CssFileLocation}\**\*.css"/>
        </items>
      </in>
      <do>
        <echo message="${filename}" />
        <exec program="java">
          <arg value="-jar" />
          <arg value="${YUI}" />
          <arg value="-o" />
          <arg value="${filename}.min" />
          <arg value="${filename}" />
        </exec>
        <move file="${filename}.min" tofile="${filename}" overwrite="true" />
      </do>
    </foreach>
  </target>

但问题是,我在CssFileLocation 文件夹(即Theme 文件夹的位置)下有 7 个 CSS 文件。我在我的 'css' 目标中移除了 6 个 CSS 文件 - 除了 default.css - 但这些文件仍然在我的 Web 项目文件中被引用,带有 <Content include="App_theme\Base\xxx.css"\> 标签。因此,在执行上述操作后,当您创建设置时,由于源项目中缺少内容文件,将会出现错误。因此,在构建解决方案之前,您必须删除这些已移除 CSS 文件的引用。我使用了 C# 代码来删除WebProject.cproj 中的这些引用。

此代码首先查找 Web 项目中所有 CSS 文件的引用,然后删除这些引用,并添加新的style.css 引用。

<target name="ReplaceCss">
    <property name="filename" 
	value="${BuildDir}\Development\Client\Web\WebProject.csproj" />
    <script language="C#">
      <code>
        <![CDATA[				
				
     public static void ScriptMain(Project project)
     {
	StreamReader projectFileReader = 
		new StreamReader(project.Properties["filename"]);      
	string x = @"<Content Include=\""App_Themes\\Base\\(?!Default)[\w-]*.css\"" />"; 
          string output = @"<Content Include='App_Themes\Base\style.css'/>";
          Regex sourcePathRegx = new Regex(x);
          string projectFile;
          try
          {
             projectFile = projectFileReader.ReadToEnd();
          }
          finally
          {
             projectFileReader.Close();
          }
          MatchCollection match = sourcePathRegx.Matches(projectFile);
          if(match.Count>0)
          {
              int i = 0;
              foreach (Match collection in match)
              {
                  if(i==0)
                  {
                      projectFile = projectFile.Replace(collection.Value, output);
                  }
                  else
                  {
                      projectFile = projectFile.Replace(collection.Value, string.Empty);
                  }
                  i++;
              }                
          }
          StreamWriter projectFileWriter = 
		new StreamWriter(project.Properties["filename"]);
          try
          {
               projectFileWriter.Write(projectFile);
          }
          finally
          {
               projectFileWriter.Close();
          }   
     }
     ]]>
      </code>
    </script>
  </target> 

由于所有这些脚本需要在创建解决方案构建之前运行,因此我使用 MSbuild 在创建构建之前调用了这些目标。

<target name="BuildPublish" depends="setversion">
    <call target = "css.minify"/>
    <call target = "JavaScript.minify"/>
    <call target = "ReplaceCss"/>
    <echo message="Build solution"/>
    <exec program="${MSBuildPath}">
      <arg value="${BuildDir}\${SolutionFileName}" />
      <arg value="/property:Configuration=release" />
      <arg value="/t:Rebuild" />
    </exec>
  </target>

因此,在所有这些操作之后,您的项目中只有两个压缩后的 CSS 文件,其中style.css 文件是您项目中 6 个 CSS 文件的组合。现在,您只需要向服务器发出两次 HTTP 请求,而之前是七次。JavaScript 代码也得到了压缩。

看点

这个过程的好处在于,您可以根据模块维护独立的 CSS 文件,并且 JavaScript、CSS 文件具有良好的对齐和可读性。并且只有在创建解决方案构建时才通过自动化的构建来压缩和合并 CSS 和 JavaScript。因此,它不会影响您的 CSS 和 JavaScript 组织。

© . All rights reserved.