jNs 在 ASP.NET MVC 项目中的应用

最近做项目用到 ASP.NET Web Optimizatoin Framework,发现 Sea.js 的依赖加载在 Release 版本下不能很好的工作了——因为 Web.Optimizatoin 合并了所有脚本。同时由于写惯了 Java 
程序和 C# 程序,对于没有命名空间概念的 Sea.js 和 RequireJS 也感觉不爽。考虑了下,觉得模块管理其实并不复杂,所以将之前在《ASP.NET MVC4 捆绑(Bundle)技术下的 JavaScript》 中提到的 js-modular 的基础上进行了改进,最终产生了 jNs

jNs 是一个具有命名空间概念的 JavaScript 模块管理工具。与 Sea.js 和 ReqireJS 等模块管理工具不同,jNs 只管理模块的定义和使用,而不负责加载,非常适合发布合并 JavaScript 代码的 Web 项目,比如使用了 ASP.NET Web Optimization Framework 提供的 Script Bundle 功能的 ASP.NET 项目,以及使用 UglifyJS 压缩合并脚本的项目等。

jNs 托管在 git.oschina.net 上,其 README 中已经有详情的示例,所以这里就不废话了。这里主要说说在 ASP.NET MVC 项目里怎么使用。

第一,定义合理的脚本结构

下面展示了一个来自某个实际项目的脚本目录(有所精简),也许不是最好的结构,但我个人觉得很清晰(用方括号 []括起来的是目录)。

[Scripts]
  │ - jNs-1.0.0.js
  │ - jNs-1.0.0.min.js
  │ - jquery-2.1.3.js
  │ - jquery-2.1.3.min.js
  ├─[core]
  │   └─[co]
  │       │ - app.js
  │       │ - compatible.js
  │       │ - util.js
  │       ├─[app]
  │       │   │ - ajax.js
  │       │   │ - dialog.js
  │       │   │ - page.js
  │       │   └ - ui.js
  │       └─[util]
  │           │ - case.js
  │           │ - debug.js
  │           └ - format.js
  └─[page]
      ├─[home]
      │   └ - index.js
      └─[user]
          └ - index.js

其中有两个比较关键的主目录,一个是 core,一个是 page

core 是整个项目中需要使用到的模块,在 bunles 中配置成一个名为 ~/bundle/core 的 ScriptBundle。Release 版本下会被打包成一个合并的脚本文件。大部分的页面只需要引用 ~/bundles/core 就可以了,因为大部分的公用逻辑都在这里了。

但是仍然会有一部分页面比较特殊,需要有自己的脚本。那么这些脚本就按一定的路径保存在 page 目录下。

core 中的目录结构与模块的结构对应,这样查找脚本文件的时候就比较方便,比如示例中的结构对应的模块全称(含命名空间)就是:

co.app
co.app.ajax
co.app.dialog
co.app.page
co.app.ui
co.compatible
co.util
co.util.case
co.util.debug
co.util.format

这个结构看起来就像 Java 一样。不过与 Java 不同,目录不必与命名空间(或包)对应,文件名也不必与模块名相同——这似乎更像 C#。

还有一点需要注意的是,在同一个命名空间下,子级命名空间和模块名是可以相同的,这也算是 jNs 的特点之一吧。

有了合理的结构,还需要解决下面这个问题。

第二,保证 jNs.js 在模块定义之前加载

虽然一般认为在 ScriptBunlde 中 Include 的脚本会顺序加载,或者说在 Release 版本下按顺序合并,所以认为可以这样写配置:

// BundleConfig.cs
// 注意:这是错误的示例
public static void RegisterBundles(BundleCollection bundles)
{
    bunles.Add(new ScriptBundle("~/bundles/core")
        .Include("~/scripts/jNs-{version}.js").
        .IncludeDirectory("~/scripts/core/", "*.js", true)
    );
}

可惜事实不是。我阅读了它的源码,发现它使用了一个 Dictionary 来进行中间过程的处理,所以最终输出的顺序完全是不确定的。所以 jNs 有可能在某个模块文件之后加载,那么模块文件中的 jNs(...) 就会出错——因为还没定义。

不过很幸运,Web.Optimization 提供了 IBundleOrderer 接口来处理顺序的问题。我比较懒,所以不想直接去实现IBundleOrderer 接口,而是从 DefaultBundleOrderer 继承了个子类来处理顺序——不管 DefaultBundleOrderer 是怎么处理的,我只需要在它处理之后按输入的顺序重新排列一下就好了

public class AsIsBundleOrderer : DefaultBundleOrderer
{
    public override IEnumerable<BundleFile> OrderFiles(
        BundleContext context,
        IEnumerable<BundleFile> files
    )
    {
        var originalList = files.ToList();
        IEnumerable<BundleFile> orderFiles = base.OrderFiles(context, originalList);
        return orderFiles.OrderBy(f => originalList.IndexOf(f));
    }
}

在有 AsIsBundleOrderer 之后,再来看看正确的 Bundle 配置

public static void RegisterBundles(BundleCollection bundles)
{
    var bundle = new ScriptBundle("~/bundles/core")
        .Include("~/Scripts/jNs-{version}.js")
        .IncludeDirectory("~/Scripts/core/", "*.js", true);
    bundle.Orderer = new AsIsBundleOrder();
    bundles.Add(bundle);
}
时间: 2024-12-26 03:59:53

jNs 在 ASP.NET MVC 项目中的应用的相关文章

在 ASP.NET MVC 项目中使用 WebForm、 HTML

原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各的优点,我们可能需要同时使用ASP.NET MVC和WebForm.本文介绍了如何在ASP.NET MVC项目中使用WebForm.首先新建一个名为WebForms的文件夹用于存放WebForm,并添加一个Web窗体文件Demo.aspx作为演示. Demo.aspx就简单的输出一句话“It’s a

【转】在 ASP.NET MVC 项目中使用 WebForm

ASP.NET MVC和WebForm各有各的优点,我们可能需要同时使用ASP.NET MVC和WebForm.本文介绍了如何在ASP.NET MVC项目中使用WebForm. 首先新建一个名为WebForms的文件夹用于存放WebForm,并添加一个Web窗体文件Demo.aspx作为演示. Demo.aspx就简单的输出一句话"It's a WebForm." 关键步骤在于路由设置.如果你希望WebForms这个文件夹名作为URL的一部分,也就是普通WebForm应用程序的方式来访

ASP.NET MVC项目中App_Code目录在程序应用

学习ASP.NET MVC,如果你是开发ASP.NET MVC项目的,也许你去为项目添加前ASP.NET项目的APP_Code目录,在这里创建与添加的Class类,也许你无法在MVC项目所引用. 那这样说,是不是一没有作用了呢?非也. 从下面一步一步来学习. 创建一个model,名称:Machine using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Insu

在ASP.NET MVC项目中使用React

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:最近在开发钉钉的微应用,考虑到性能和UI库的支持,遂采用了React来开发前端. 目前我的项目是基于ABP框架的ASP.NET MVC/WEB API作为后端,AngularJS作为前端.但是发现钉钉官方的UI(SaltUI)是基于React封装的,另外AmazeUI的Touch版本也是React封装,也考虑到React性能更优,同时移动端网页的前端业务逻辑不会太复杂,就打算使用React来开

ASP.NET MVC 项目中 一般处理程序ashx 获取Session

1-在 aspx和aspx.cs中,都是以Session["xxx"]="aaa"和aaa=Session["xxx"].ToString()进行读写. 而在ashx中,Session都要使用context.Session,读写方法是这样的: context.Session["xxx"]="aaa"和aaa=context.Session["xxx"].ToString() 2-在ash

AngularJS2 + ASP.NET MVC项目

环境:VS2015, NodeJS:v 6.5, npm: v3.10, AngularJs 2 通过将ASP.NET MVC项目与Angualr 2官网上的quick start整合的过程中遇到些问题. 通过下面的若干配置最终向项目build成功.

ASP.NET MVC 3中的路由

准备发布新随笔,才发现草稿里还有几年前这篇烂了尾的,先放上来,有空再补完整吧-- (* 整理自<Pro ASP.NET MVC 3 Framework>学习笔记. *) 路由,正如其名,是决定消息经由何处被传递到何处的过程.也正如网络设备路由器Router一样,ASP.NET MVC框架处理请求URL的方式,同样依赖于一张预定义的路由表.以该路由表为转发依据,请求URL最终被传递给特定Controller的特定Action进行处理.而在相反的方向上,MVC框架的渲染器同样要利用这张路由表,生成

[转]在 ASP.NET MVC 4 中创建为移动设备优化的视图

原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾. 一方面,客户在其编写应用程序和网站的方法中强烈要求(或乐于要求)移动优先. 另一方面,同一些人又经常称赞 CSS 媒体查询和流体布局. 我所发现的矛盾在于经常利用 CSS 媒体查询和流体布局并未在其他内容之前优先处理移动方面,它不是一种移动优先的方法. 在本文中,我将介绍如何使用服务器端逻辑为给定设

百度Web富文本编辑器ueditor在ASP.NET MVC3项目中的使用说明

====================================================================== [百度Web富文本编辑器ueditor在ASP.NET MVC3项目中的使用说明] ----by 夏春涛 2014-02-20 ====================================================================== 运行环境: ueditor-v1.3.6-utf8-net,VS2010旗舰版+SP1,