Visual Studio 2010:发布缩小的 javascript 文件而不是原始文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2364644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Visual Studio 2010: Publish minified javascript files instead of the original ones
提问by salgiza
I have a Scripts folder, that includes all the .js files used in the project. Using the Ajax Minifier task, I generate .min.js files for each one. Depending on whether the application is running in debug or release mode, I include the original .js file, or the minified one.
我有一个 Scripts 文件夹,其中包含项目中使用的所有 .js 文件。使用 Ajax Minifier 任务,我为每个文件生成 .min.js 文件。根据应用程序是在调试模式还是发布模式下运行,我包含原始 .js 文件或缩小的文件。
The Scripts folder looks like this:
Scripts 文件夹如下所示:
Scripts/script1.js
Scripts/script1.min.js // Outside the project, generated automatically on build
Scripts/script2.js
Scripts/script2.min.js // Outside the project, generated automatically on build
The .min.js files are outside the project (although in the same folder as the original files), and they are not copied into the destination folder when we publish the project.
.min.js 文件在项目之外(尽管与原始文件在同一文件夹中),并且在我们发布项目时不会将它们复制到目标文件夹中。
I have no experience whatsoever using build tasks (well, apart from including the minifier task), so I would appreciate if anyone could advise me as to which would be the correct way to:
我没有任何使用构建任务的经验(好吧,除了包括 minifier 任务),所以如果有人能告诉我哪种是正确的方法,我将不胜感激:
- Copy the .min.js files to the destination folder when I publish the app from Visual Studio.
- Delete / Not copy the original js files (this is not vital, but I'd rather not copy files that will not be used in the app).
- 当我从 Visual Studio 发布应用程序时,将 .min.js 文件复制到目标文件夹。
- 删除/不复制原始 js 文件(这并不重要,但我宁愿不复制不会在应用程序中使用的文件)。
Thanks,
谢谢,
Edit:From the responses, I see that I missed some details, and that maybe I'm looking for the wrong solution to the problem. I'll add the following details to the question:
编辑:从回复中,我看到我错过了一些细节,也许我正在寻找问题的错误解决方案。我将在问题中添加以下详细信息:
- If possible, we'd rather not create copy scripts in the build process of the solution. Sure, we considered it, but we were using Web deployment projects up until now, and we'd rather start using the new Publish feature of VS2010 (which is supposed to replace these projects) than manually adding copy commands to the build task.
- The *.min.js files are not included in the project because they can't be in the Source control system (TFS at this moment). They are files generated during compilation, and it would be akin to including the 'bin' folder in the TFS (including the problems it would cause). Maybe we should create the min files in a different folder and treat it like 'bin'? (Is that even possible?)
- 如果可能,我们宁愿不在解决方案的构建过程中创建复制脚本。当然,我们考虑过,但直到现在我们都在使用 Web 部署项目,我们宁愿开始使用 VS2010 的新发布功能(应该替换这些项目),而不是手动将复制命令添加到构建任务中。
- *.min.js 文件不包含在项目中,因为它们不能在源代码控制系统(此时为 TFS)中。它们是编译期间生成的文件,类似于在 TFS 中包含“bin”文件夹(包括它会导致的问题)。也许我们应该在不同的文件夹中创建 min 文件并将其视为“bin”?(这甚至可能吗?)
采纳答案by Eamon Nerbonne
Edit (2012 October):ASP.NET 4.5 now includes Bundling and minification. The current version doesn't support dynamic javascript generation very well, but it's otherwise pretty usable and for instance does watch the filesystem to live changes as described below; before rolling your own compression, try that!
编辑(2012 年 10 月):ASP.NET 4.5 现在包括Bundling 和 minification。当前版本不能很好地支持动态 javascript 生成,但它在其他方面非常有用,例如确实观察文件系统以如下所述进行实时更改;在滚动您自己的压缩之前,请尝试一下!
Old answer:
旧答案:
Rather than implement this at build time, I suggest you do so at runtime. This has a number of advantages:
我建议您在运行时执行此操作,而不是在构建时执行此操作。这有许多优点:
- You can include debugging parameters that turn off the combining and minification to permit easier identification of errors. This also allows you to run with less difference between development and production environment.
- You gain some flexibility. I've twice been able to fix errors via a script-only fix that can go live directly. For simple but critical errors that's a nice option.
- It's quite a bit simpler to implement - you already have the expertise in implementing http responses, which applies nicely here.
- You can track the last-modified date of the scripts involved, and not only use that to set the appropriate ETags and whatnot (which IIS can do too), but rather set a far-future expiry date. Then, rather than linking the actual scipt (whether minified or not), you can link the script with some short token in the querystring - that way clients don't need to check whether the js has updated. When it has, the pages will link to a "new" script file that needs to be separately requested anyhow. (This is possible to do in build scripts, but trickier).
- A complex build process often has hidden costs. Not only does it take longer to run, but what happens when you want to update your build automation tool? When you switch IIS or windows versions? When you migrate to VS 2010? How easy is it to bring new developers up to speed?
- 您可以包含关闭组合和缩小的调试参数,以便更轻松地识别错误。这也使您可以在开发环境和生产环境之间的差异较小的情况下运行。
- 你获得了一些灵活性。我已经两次能够通过可以直接上线的纯脚本修复来修复错误。对于简单但关键的错误,这是一个不错的选择。
- 实现起来要简单得多 - 您已经拥有实现 http 响应的专业知识,这在这里非常适用。
- 您可以跟踪所涉及脚本的最后修改日期,不仅可以使用它来设置适当的 ETag 等(IIS 也可以这样做),还可以设置一个很远的未来到期日期。然后,而不是链接实际的 scipt(无论是否缩小),您可以将脚本与查询字符串中的一些短标记链接 - 这样客户端就不需要检查 js 是否已更新。当它有时,页面将链接到一个“新”脚本文件,无论如何都需要单独请求。(这可以在构建脚本中完成,但更棘手)。
- 复杂的构建过程通常有隐藏的成本。不仅运行时间更长,而且当您想要更新构建自动化工具时会发生什么?当您切换 IIS 或 Windows 版本时?当您迁移到 VS 2010 时?让新开发人员跟上进度有多容易?
This is the rough outline of the process I follow:
这是我遵循的过程的粗略轮廓:
- I specify two directories as containing only compressible css and js. At appdomain instantiation or shortly thereafter via a static constructor, a class finds the contents of those directories and creates a
FileSystemWatcherto watch for changes. - All files are read in order of filename (using prefixes such as
00_jquery.js10_init.jsetc. helps control order here). The list of filenames is stored for debug purposes. - All files are combined via string concatenation, then minified by YUI, then compressed via
GZipStream. A version specific token is computed either by newest last-modified date or by the hash of the result. - The result of the compression (byte array, filenames, and version-specific token) is stored in a static class variable (protected by a
lock). If the file system watcher detects an update, step 2 starts again and runs in the background until the compression completes - hence the locking. - Any page wishing to include the combined javascript (and/or css) calls the shared static variable. If we're in debug mode, that generates a script (or link) tag for each filename as stored in step two, otherwise, this generates a single script (or link) tag to a Uri that's handled by a custom
IHttpHandler. All Uri's include the version-specific token in the querystring - this is ignored both by the IIS static file handler and the custom http handler for the combined minified version, but makes caching easy. - In a custom IHttpHandler, when a request for the combined javascript (or css) is received, the Content-Encoding: gzip header is set, and a far-future Expiry date. Then the precompressed byte array is written directly to the http stream via
context.Response.OutputStream.
- 我指定两个目录只包含可压缩的 css 和 js。在 appdomain 实例化时或此后不久通过静态构造函数,类会查找这些目录的内容并创建一个
FileSystemWatcher以监视更改。 - 所有文件都按文件名的顺序读取(使用诸如
00_jquery.js10_init.js等前缀有助于控制这里的顺序)。文件名列表存储用于调试目的。 - 所有文件通过字符串连接组合,然后由 YUI 缩小,然后通过
GZipStream. 特定于版本的令牌由最新的最后修改日期或结果的散列计算。 - 压缩的结果(字节数组、文件名和特定于版本的标记)存储在静态类变量中(由 保护
lock)。如果文件系统观察程序检测到更新,步骤 2 将再次启动并在后台运行,直到压缩完成 - 因此锁定。 - 任何希望包含组合的 javascript(和/或 css)的页面都调用共享静态变量。如果我们处于调试模式,则会为第二步中存储的每个文件名生成一个脚本(或链接)标记,否则,这会生成一个指向由自定义
IHttpHandler. 所有 Uri 都在查询字符串中包含特定于版本的令牌 - IIS 静态文件处理程序和组合缩小版本的自定义 http 处理程序都忽略了这一点,但使缓存变得容易。 - 在自定义 IHttpHandler 中,当接收到对组合 javascript(或 css)的请求时,会设置 Content-Encoding: gzip 标头,以及未来的到期日期。然后将预压缩的字节数组通过
context.Response.OutputStream.
Using that approach, you won't need to fiddle with web.config options whenever you add or remove a script file; you can update scripts while the app is running and clients will request these on the very next page view - but you still will get optimal cache behavior since browsers won't even send an If-Not-Modified request due to the expiry header. Usually, compressing scripts should take a second or so and the compressed result should be so small that the memory overhead of the static variable is negligible (at most a few 100 KB for a truly large amount of scripting / css).
使用这种方法,无论何时添加或删除脚本文件,您都不需要摆弄 web.config 选项;您可以在应用程序运行时更新脚本,客户端将在下一个页面视图中请求这些脚本 - 但您仍将获得最佳缓存行为,因为浏览器由于过期标头甚至不会发送 If-Not-Modified 请求。通常,压缩脚本应该需要一秒钟左右,并且压缩结果应该很小,以至于静态变量的内存开销可以忽略不计(对于真正大量的脚本/css 最多只有几百 100 KB)。
回答by Daniel Lee
If you want to do Javascript minification via Visual Studio, this will get you started: http://encosia.com/2009/05/20/automatically-minify-and-combine-javascript-in-visual-studio/
如果您想通过 Visual Studio 进行 Javascript 缩小,这将使您开始:http: //encosia.com/2009/05/20/automatically-minify-and-combine-javascript-in-visual-studio/
Otherwise, I'd recommend a tool that can automatically combine and minify Javascript. The two tools that I have looked at are Justin Etheredge's Bundlerand Combres. I'm using Bundler in my current project and one of my work colleagues is using Combres. Bundler is a little bit simpler to use but it does less than Combres. With Bundler if debug is turned off in web.config then it doesn't minify and combine which means that you can debug the javascript in your dev environment.
否则,我会推荐一个可以自动组合和缩小 Javascript 的工具。我看过的两个工具是Justin Etheredge的Bundler和Combres。我在当前项目中使用 Bundler,我的一位同事正在使用 Combres。Bundler 使用起来稍微简单一些,但它比 Combres 做的少。使用 Bundler,如果在 web.config 中关闭调试,则它不会缩小和组合,这意味着您可以在开发环境中调试 javascript。
P.S. Bundler was renamed to SquishIt.
PS Bundler 更名为 SquishIt。
回答by James B
You probably want to take a look at Build Events, with which you can specify a command line to execute post-build. Your question is, additionally, similar to thesequestions.
您可能想看看Build Events,您可以使用它指定一个命令行来执行后期构建。此外,您的问题与这些问题类似。
For the actual copying, you can quite easily just make use of the COPYcommand.
对于实际复制,您可以很容易地使用COPY命令。
回答by flq
I am not quite sure whether this approach would be useful in this situation but I could imagine it... You can modify csproj files to e.g. influence what files should be included in a certain type of build.
我不太确定这种方法在这种情况下是否有用,但我可以想象……您可以修改 csproj 文件以影响某些类型的构建中应包含哪些文件。
With certain type I am referring to the Configuration Manager.
对于某些类型,我指的是配置管理器。
Debug and Release are the default ones but nothing stops you from making new ones. Based on the selected configuration you can have different files being part of the configuration and I suppose that you could publish different files that way. I have describds that strategy on my blog here : http://realfiction.net/go/130
Debug 和 Release 是默认的,但没有什么能阻止你制作新的。根据所选的配置,您可以将不同的文件作为配置的一部分,我想您可以通过这种方式发布不同的文件。我在我的博客上描述了该策略:http://realfiction.net/go/130
回答by Ivo
This article about "Automatically Minify, Combine, Compress, and Cache *.js and *.css Files in your ASP.NET Project" can maybe help you
这篇关于“在你的 ASP.NET 项目中自动缩小、合并、压缩和缓存 *.js 和 *.css 文件”的文章可能会对你有所帮助
http://www.codeproject.com/KB/aspnet/CssAndJavaScriptOptimizer.aspx?display=Print
http://www.codeproject.com/KB/aspnet/CssAndJavaScriptOptimizer.aspx?display=Print

