结合使用Microsoft AJAX Minifier和Visual Studio 2010 1单击发布 [英] Using Microsoft AJAX Minifier with Visual Studio 2010 1-click publish

查看:84
本文介绍了结合使用Microsoft AJAX Minifier和Visual Studio 2010 1单击发布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Microsoft AJAX Minifier 提供了此线程文章,我尝试在我的WAP根目录中创建一个名为'[ProjectName] .wpp.targets的文件,并使用以下XML:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="Minify" BeforeTargets="MSDeployPublish">
    <ItemGroup>
      <JS Include="**\*.js" Exclude="**\*.min.js;**\*vsddoc.js;**\*debug.js" />
    </ItemGroup>
    <ItemGroup>
      <CSS Include="**\*.css" Exclude="**\*.min.css" />
    </ItemGroup>
    <AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="@(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
  </Target>
</Project>

这似乎没有任何效果,不幸的是,Visual Studio在这些工具的反馈或调试信息方面并没有提供太多帮助.

有人使用Visual Studio 2010一键式发布功能在缩小JavaScript/CSS方面取得了成功吗?

解决方案

我刚刚在以下位置撰写了有关如何执行此操作的详细博客条目 http://sedodream.com/2011/02/25/HowToCompressCSSJavaScriptBeforePublishpackage.aspx

尽管该问题专门指出了Microsoft AJAX Minifier,但我决定使用Packer.NET(资源部分中的链接)中包含的压缩器.这样做是因为当我查看AJAX Minifier的MSBuild任务时,似乎无法控制压缩文件的输出位置.取而代之的是,它将简单地写入扩展名为.min.cs或.min.js的同一文件夹.无论如何,当您发布/打包Web应用程序项目(WAP)时,文件会在发布/打包发生之前复制到一个临时位置.该位置的默认值为obj {Configuration} \ Package \ PackageTmp \,其中{Configuration}是您当前用于WAP的构建配置.因此,我们需要做的是允许WPP将所有文件复制到该位置,然后我们可以压缩该文件夹中的CSS和JavaScript.将文件复制到该位置的目标是CopyAllFilesToSingleFolderForPackage. (要了解有关这些目标的更多信息,请查看文件%Program Files(x86)%\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft.Web.Publishing.targets.)使我们的目标在此目标之后运行我们可以使用MSBuild AfterTargets属性.我创建的用于证明这一点的项目称为CompressBeforePublish,因为我创建了一个名为CompressBeforePublish.wpp.targets的新文件来包含我的更改.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="SmallSharpTools.Packer.MSBuild.Packer"
             AssemblyFile="$(MSBuildThisFileDirectory)..\Contrib\SmallSharpTools.Packer\SmallSharpTools.Packer.dll" />

  <!-- This target will run after the files are copied to PackageTmp folder -->
  <Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForPackage">
    <!-- Discover files to compress -->
    <ItemGroup>
      <_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
      <_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
    </ItemGroup>

    <Message Text="Compressing JavaScript files" Importance="high" />
    <!-- 
      Compress the JavaScript files. 
      Not the usage of %(JavaScript.Identity which causes this task to run once per
      .js file in the JavaScriptFiles item list.
      For more info on batching: http://sedotech.com/resources#Batching
    -->
    <Packer InputFiles="%(_JavaScriptFiles.Identity)"
            OutputFileName="@(_JavaScriptFiles->'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')"
            Mode="JSMin"
            Verbose="false"
            Condition=" '@(_JavaScriptFiles)' != ''" />

    <Message Text="Compressing CSS files" Importance="high" />

    <Packer InputFiles="%(_CssFiles.Identity)"
            OutputFileName="@(_CssFiles->'$(_PackageTempDir)\Content\%(RecursiveDir)%(Filename)%(Extension)')"
            Mode="CSSMin"
            Verbose="false"
            Condition=" '@(_CssFiles)' != '' "/>
  </Target>
</Project>

在这里,我创建了一个目标CompressJsAndCss,并添加了AfterTargets =" CopyAllFilesToSingleFolderForPackage",这使它在CopyAllFilesToSingleFolderForPackage之后执行.在此目标内,我做两件事,收集需要压缩的文件,然后压缩它们.

1.收集要压缩的文件

<ItemGroup>
  <_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
  <_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
</ItemGroup>

在这里,我将项目列表用于JavaScript文件和CSS文件.请注意,我正在使用_PackageTempDir属性来拾取.js&写入要打包的临时文件夹中的.css文件.我这样做而不是选择源文件的原因是因为我的构建可能正在输出其他.js& .css文件,这些文件将要发布.注意:由于_PackageTempDir属性以下划线开头,因此不能保证其在将来的版本中表现出来(甚至存在).

2.压缩文件

我使用Packer任务来压缩.js和.css文件.对于这两组文件,用法都非常相似,因此我只看第一种用法.

<Packer InputFiles="%(_JavaScriptFiles.Identity)"
        OutputFileName="@(_JavaScriptFiles->'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')"
        Mode="JSMin"
        Verbose="false"
        Condition=" '@(_JavaScriptFiles)' != ''" />

在这里,任务将被送入所有.js文件以进行压缩.记下如何使用%(_ JavaScriptFiles.Identity)将文件传递到任务中,在这种情况下,这样做是使每个.js文件执行一次此任务. %(abc.def)语法调用批处理,如果您不熟悉批处理,请参见下文.对于输出文件的值,我再次使用_PackageTempDir属性.在这种情况下,由于该项目已经存在,因此我可以简化为@(_ JavaScriptFiles->'%(FullPath)'),但我认为在压缩尚不存在的文件时,该表达式可能会有所帮助在_PackageTempDir文件夹中.

现在,我们已将此目标添加到.wpp.targets文件中,我们可以发布/打包我们的Web项目,并且将其中包含的.js& .css文件将被压缩.注意:每当您修改.wpp.targets文件时,都将必须卸载/重新加载Web项目,以使所做的更改被选中,Visual Studio会缓存您的项目.

在下面的图像中,您可以看到压缩这些文件的区别.

您可以在下面下载整个项目,也可以查看我可能会对您感兴趣的其他资源.

资源

The Microsoft AJAX Minifier provides a build task which can be used in TFS or local build definitions.

I have succsfully used this in both a local project file (building to seperate files) and in TFS build definitions (overwriting the existing JS files).

I'd like to move to using Visual Studio 2010's 1-click publish feature rather than a TFS build definition, however adding the minification task as an AfterBuild target in the project file doesn't appear to effect the 1-click publish feature.

Using information found in this thread and these articles, I tried creating a file named '[ProjectName].wpp.targets in my WAP root directory, and used the following XML:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="Minify" BeforeTargets="MSDeployPublish">
    <ItemGroup>
      <JS Include="**\*.js" Exclude="**\*.min.js;**\*vsddoc.js;**\*debug.js" />
    </ItemGroup>
    <ItemGroup>
      <CSS Include="**\*.css" Exclude="**\*.min.css" />
    </ItemGroup>
    <AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="@(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css" />
  </Target>
</Project>

This doesn't appear to have any effect, and unfortunately Visual Studio doesn't give much in the way of feedback or debugging info for these tools.

Has anyone had any success minifying JavaScript / CSS using the Visual Studio 2010 1-click publish feature?

解决方案

I just wrote a detailed blog entry on how to do this at http://sedodream.com/2011/02/25/HowToCompressCSSJavaScriptBeforePublishpackage.aspx and http://blogs.msdn.com/b/webdevtools/archive/2011/02/24/how-to-compress-css-javascript-before-publish-package.aspx.

Here are the contents

Today I saw a post on stackoverflow.com asking Using Microsoft AJAX Minifier with Visual Studio 2010 1-click publish. This is a response to that question. The Web Publishing Pipeline is pretty extensive so it is easy for us to hook in to it in order to perform operation such as these. One of those extension points, as we’ve blogged about before, is creating a .wpp.targets file. If you create a file in the same directory of your project with the name {ProjectName}.wpp.targets then that file will automatically be imported and included in the build/publish process. This makes it easy to edit your build/publish process without always having to edit the project file itself. I will use this technique to demonstrate how to compress the CSS & JavaScript files a project contains before it is published/packaged.

Eventhough the question specifically states Microsoft AJAX Minifier I decided to use the compressor contained in Packer.NET (link in resources section). I did this because when I looked at the MSBuild task for the AJAX Minifier it didn’t look like I could control the output location of the compressed files. Instead it would simply write to the same folder with an extension like .min.cs or .min.js. In any case, when you publish/package your Web Application Project (WAP) the files are copied to a temporary location before the publish/package occurs. The default value for this location is obj{Configuration}\Package\PackageTmp\ where {Configuration} is the build configuration that you are currently using for your WAP. So what we need to do is to allow the WPP to copy all the files to that location and then after that we can compress the CSS and JavaScript that goes in that folder. The target which copies the files to that location is CopyAllFilesToSingleFolderForPackage. (To learn more about these targets take a look at the file %Program Files (x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets.) To make our target run after this target we can use the MSBuild AfterTargets attribute. The project that I created to demonstrate this is called CompressBeforePublish, because of that I create a new file named CompressBeforePublish.wpp.targets to contain my changes.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="SmallSharpTools.Packer.MSBuild.Packer"
             AssemblyFile="$(MSBuildThisFileDirectory)..\Contrib\SmallSharpTools.Packer\SmallSharpTools.Packer.dll" />

  <!-- This target will run after the files are copied to PackageTmp folder -->
  <Target Name="CompressJsAndCss" AfterTargets="CopyAllFilesToSingleFolderForPackage">
    <!-- Discover files to compress -->
    <ItemGroup>
      <_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
      <_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
    </ItemGroup>

    <Message Text="Compressing JavaScript files" Importance="high" />
    <!-- 
      Compress the JavaScript files. 
      Not the usage of %(JavaScript.Identity which causes this task to run once per
      .js file in the JavaScriptFiles item list.
      For more info on batching: http://sedotech.com/resources#Batching
    -->
    <Packer InputFiles="%(_JavaScriptFiles.Identity)"
            OutputFileName="@(_JavaScriptFiles->'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')"
            Mode="JSMin"
            Verbose="false"
            Condition=" '@(_JavaScriptFiles)' != ''" />

    <Message Text="Compressing CSS files" Importance="high" />

    <Packer InputFiles="%(_CssFiles.Identity)"
            OutputFileName="@(_CssFiles->'$(_PackageTempDir)\Content\%(RecursiveDir)%(Filename)%(Extension)')"
            Mode="CSSMin"
            Verbose="false"
            Condition=" '@(_CssFiles)' != '' "/>
  </Target>
</Project>

Here I’ve created one target, CompressJsAndCss, and I have included AfterTargets="CopyAllFilesToSingleFolderForPackage" which causes it to be executed after CopyAllFilesToSingleFolderForPackage. Inside this target I do two things, gather the files which need to be compressed and then I compress them.

1. Gather files to be compressed

<ItemGroup>
  <_JavaScriptFiles Include="$(_PackageTempDir)\Scripts\**\*.js" />
  <_CssFiles Include="$(_PackageTempDir)\Content\**\*.css" />
</ItemGroup>

Here I use an item list for both JavaScript files as well as CSS files. Notice that I am using the _PackageTempDir property to pickup .js & .css files inside the temporary folder where the files are written to be packaged. The reason that I’m doing that instead of picking up source files is because my build may be outputting other .js & .css files and which are going to be published. Note: since the property _PackageTempDir starts with an underscore it is not guaranteed to behave (or even exist) in future versions.

2. Compress files

I use the Packer task to compress the .js and .css files. For both sets of files the usage is pretty similar so I will only look at the first usage.

<Packer InputFiles="%(_JavaScriptFiles.Identity)"
        OutputFileName="@(_JavaScriptFiles->'$(_PackageTempDir)\Scripts\%(RecursiveDir)%(Filename)%(Extension)')"
        Mode="JSMin"
        Verbose="false"
        Condition=" '@(_JavaScriptFiles)' != ''" />

Here the task is fed all the .js files for compression. Take a note how I passed the files into the task using, %(_JavaScriptFiles.Identity), in this case what that does is to cause this task to be executed once per .js file. The %(abc.def) syntax invokes batching, if you are not familiar with batching please see below. For the value of the output file I use the _PackageTempDir property again. In this case since the item already resides there I could have simplified that to be @(_JavaScriptFiles->’%(FullPath)’) but I thought you might find that expression helpful in the case that you are compressing files which do not already exist in the _PackageTempDir folder.

Now that we have added this target to the .wpp.targets file we can publish/package our web project and it the contained .js & .css files will be compressed. Note: Whenever you modify the .wpp.targets file you will have to unload/reload the web project so that the changes are picked up, Visual Studio caches your projects.

In the image below you can see the difference that compressing these files made.

You can download the entire project below, as well as take a look at some other resources that I have that you might be interested in.

Resources

这篇关于结合使用Microsoft AJAX Minifier和Visual Studio 2010 1单击发布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆