ASP.NETMVCBundlingandRequireJS-创新互联
方式一 Bunding+RequireJS混用
先来看看一个老外的做法,他大体上是这样做的:
为绥化等地区用户提供了全套网页设计制作服务,及绥化网站建设行业解决方案。主营业务为成都网站设计、成都网站建设、绥化网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!Bundling部分
App_Start/BundleConfig.cs:
bundles.Add(new ScriptBundle("~/bundles/test").Include( "~/Scripts/jquery-{version}.js", "~/Scripts/q.js", "~/Scripts/globalize.js"));
RequireJS配置部分
在ASP.NET MVC项目中,我们一般是在_Layout母版页中添加js引用
@if (!HttpContext.Current.IsDebuggingEnabled) { }
个人点评:很不优雅的实现方式,说好的模块化呢?而且并没有提供完整的应用程序解决方案。
老外原文地址:ASP.NET MVC Bundling and Minification with RequireJS
方式二 RequireJS.NET
但是随后我就发现了一个插件RequireJS.NET
什么是RequireJS.NET?
RequireJS.NET让每一个C#程序员可以来构建JavaScript代码,不需要具备高级的js编程技能就可以来理解和使用。
在ASP.NET MVC中使用RequireJS的优势:
让JavaScript代码更加可复用
可靠的对象和依赖关系管理
适用于大型复杂的应用
异步加载JavaScript文件
个人点评:安装这个安装那个,而且比较死板,我完全可以自己写代码实现它的功能,而且更加灵活,想怎么改怎么改。
RequireJS.NET的使用请参考:Getting started with RequireJS for ASP.NET MVC
我的实现方式
接下来,我将隆重推出我的实现方式。我的做法是:抛弃ASP.NET MVC自带的Bundling功能,因为它太傻瓜、太粗暴了,但是可以将RequireJS and R.js 很友好的集成在ASP.NET MVC项目中来。虽然RequireJS看上去在单页应用的场景下用起来非常方便,但是在应用程序场景下也是同样适用的,只要你愿意接受它的这种方式。
使用技术: using RequireJS and R.js
目录结构如下:
由于在ASP.NET MVC项目中,有模板页_Layout.cshtml,那么我可以把一些公用调用的东西直接放到模板页中,这里我通过Html的扩展方法进行了封装
css的调用:
js的调用:
@RenderSection("scripts", required: false)
RequireJsHelpers:
using System.IO;using System.Text;using System.Web;using System.Web.Mvc;namespace Secom.Emx.WebApp { public static class RequireJsHelpers { private static MvcHtmlString RequireJs(this HtmlHelper helper, string config, string module) { var require = new StringBuilder(); string jsLocation = "/themes/default/content/release-js/";#if DEBUG jsLocation = "/themes/default/content/js/";#endif if (File.Exists(helper.ViewContext.HttpContext.Server.MapPath(Path.Combine(jsLocation, module + ".js")))) { require.AppendLine("require( [ \"" + jsLocation + config + "\" ], function() {"); require.AppendLine(" require( [ \"" + module + "\",\"domReady!\"] ); "); require.AppendLine("});"); } return new MvcHtmlString(require.ToString()); } public static MvcHtmlString ViewSpecificRequireJS(this HtmlHelper helper) { var areas = helper.ViewContext.RouteData.DataTokens["area"]; var action = helper.ViewContext.RouteData.Values["action"]; var controller = helper.ViewContext.RouteData.Values["controller"]; string url = areas == null? string.Format("views/{0}/{1}", controller, action): string.Format("views/areas/{2}/{0}/{1}", controller, action, areas); return helper.RequireJs("config.js", url); } public static string StylesPath(this HtmlHelper helper, string pathWithoutStyles) {#if (DEBUG) var stylesPath = "~/themes/default/content/css/";#else var stylesPath = "~/themes/default/content/release-css/";#endif return VirtualPathUtility.ToAbsolute(stylesPath + pathWithoutStyles); } } }
再来看下我们的js主文件config.js
requirejs.config({ baseUrl: '/themes/default/content/js', paths: { "jquery": "jquery.min", "jqueryValidate": "lib/jquery.validate.min", "jqueryValidateUnobtrusive": "lib/jquery.validate.unobtrusive.min", "bootstrap": "lib/bootstrap.min", "moment": "lib/moment.min", "domReady": "lib/domReady", }, shim: { 'bootstrap': { deps: ['jquery'], exports: "jQuery.fn.popover" }, "jqueryValidate": ["jquery"], "jqueryValidateUnobtrusive": ["jquery", "jqueryValidate"] } });
在开发环境,我们的css文件肯定不能压缩合并,不然无法调试了,而生产环境肯定是需要压缩和合并的,那么我想要开发的时候不合并,一发布到生产就自动合并
那么有两种方式,一种呢是单独写一个批处理脚本,每次发布到生产的时候就运行一下,一种呢是直接在项目的生成事件中进行配置,如果是debug模式就不压缩合并,如果是release模式则压缩合并
if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\release-js\build-js.js"if $(ConfigurationName) == Release node "$(ProjectDir)themes\default\content\build\r.js" -o "$(ProjectDir)themes\default\content\release-css\build-css.js"
自动构建
批处理自动合并压缩脚本build.bat:
@echo off echo start build js node.exe r.js -o build-js.js echo end build js echo start build css node.exe r.js -o build-css.js echo end build css echo. & pause
因为我的js文件是和控制器中的view视图界面一一对应的,那么我需要一个动态的js构建脚本,这里我使用强大的T4模板来实现,新建一个文本模板build-js.tt,如果你的VS没有T4的智能提示,你需要安装一个VS插件,打开VS——工具——扩展和更新:
T4模板代码如下:
<#@ template debug="false" hostspecific="true" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Configuration" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".js" #>({ appDir: '<#= relativeBaseUrl #>', baseUrl: './', mainConfigFile: '<#= relativeBaseUrl #>/config.js', dir: '../release-js', modules: [ { name: "config", include: [ // These JS files will be on EVERY page in the main.js file // So they should be the files we will almost always need everywhere "domReady", "jquery", "jqueryValidate", "jqueryValidateUnobtrusive", "bootstrap", "moment" ] }, <# foreach(string path in System.IO.Directory.GetFiles(this.Host.ResolvePath(relativeBaseUrl+"/views"), "*.js", System.IO.SearchOption.AllDirectories)) { #>{ name: '<#= GetRequireJSName(path) #>' }, <# } #>], onBuildRead: function (moduleName, path, contents) { if (moduleName = "config") { return contents.replace("/themes/default/content/js","/themes/default/content/release-js") } return contents; }, })<#+ public const string relativeBaseUrl = "../js"; public string GetRequireJSName(string path){ var relativePath = Path.GetFullPath(path).Replace(Path.GetFullPath(this.Host.ResolvePath("..\\js\\")), ""); return Path.Combine(Path.GetDirectoryName(relativePath), Path.GetFileNameWithoutExtension(relativePath)).Replace("\\", "/"); } #>
通过T4模板生产的构建脚本如下:
({ appDir: '../js', baseUrl: './', mainConfigFile: '../js/config.js', dir: '../release-js', modules: [ { name: "config", include: [ // These JS files will be on EVERY page in the main.js file // So they should be the files we will almost always need everywhere "domReady", "jquery", "jqueryValidate", "jqueryValidateUnobtrusive", "bootstrap", "moment" ] }, { name: 'views/areas/admin/default/index' }, { name: 'views/home/index' }, { name: 'views/home/login' }, ], onBuildRead: function (moduleName, path, contents) { if (moduleName = "config") { return contents.replace("/themes/default/content/js","/themes/default/content/release-js") } return contents; }, })
创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。
当前名称:ASP.NETMVCBundlingandRequireJS-创新互联
URL地址:http://cdiso.cn/article/ppeid.html