_reference.js的故事

本文乃译文,英文原版点这里
在Visual Studio中开发web项目的时候,_reference.js 文件是高效使用Intellisense(智能提示)的一个很关键的文件。在某种程度上,有无这个文件,是高效Intellisense和完全没有Intellisense的区别。
_r1

本文将介绍_references.js文件背后的故事,它如何工作?又是如何诞生的?

新的JavaScript编辑器

就在Visual Studio 2010发布后不久,JavaScript编辑器的所有权从ASP.NET & Web Tooling团队(我曾经是其中一员)移交到了新成立的Client Platform团队。

这个新团队将为Visual Studio 2012开发一个全新的现代化的Javascript编辑器,它将与即将面世的基于HTML/JavaScript的Windows 8 Store Apps的开发体验保持一致。

VS 2010中现有的旧的JavaScript编辑器即将从VS退休,但会在WebMatrix中获得新生,并继续开发和更新。

随着新编辑器的工作逐渐展开,我们决定重新设计其中的部分功能。其中就包括Intellisense。

Intellisense的三种类型

JavaScript的智能提示有多种实现方式,我们讨论过如下3种方式:

  1. Intellisense自动引用项目里的所有.js文件。
  2. Intellisense只引用当前HTML文件引用的那些.js文件。
  3. 用户手动指定引用哪些文件。

自动引用所有.js文件可能会带来很多潜在的问题。你可能会得到关于某些.js文件的智能提示,然而这些文件却根本没有加载。就好比在C#里,你并没有使用using来import某个类型,却得到了这个类型的智能提示。这会导致运行时错误。

自动引用所有.js文件还会带来别的附加问题。比如性能,需要分析的文件越多,Intellisense的负担越大,这会影响用户体验。还有.js文件的加载顺序问题,新的编辑器会加载执行所有代码,所以以正确的顺序运行每个js文件,是影响准确性的一个重要因素。

然而对于#2,捆绑(Bundling)、压缩(Minification)和JavaScript动态加载等技术,让所有IDE都很难静态的分析出Intellisense应该引用哪些.js文件,这几乎是不可能的。结果可能导致完全没有Intellisense,这可能比加载太多Intellisense更糟糕。

最后,让用户自己指定Intellisense引用的文件,可以解决性能问题,也可以让IDE不去解析HTML文件。问题是这完全依赖于用户,增加了用户的负担。

综上,每种实现方式各有优劣。

显式引用和隐式引用

我们认为新编辑器应该使用#2和#3的组合。既自动引用<script>指向的.js文件,也允许用户手动显式添加“三斜杠式引用”。三斜杠语法如下,可以添加至任意.js文件的顶部:

/// <reference path="../app/respond.js" />

在Visual Studio解决方案浏览器里,拖动一个.js文件到另一个打开的.js文件,会自动插入一条三斜杠式引用到文档的顶部。添加引用之后,Visual Studio就会启用被引用文件的智能提示。

全局引用_reference.js

显式添加引用的缺陷在于,你可能需要在你的每个js文件反复添加某个引用,比如添加jQuery。这很不友好,尽量减轻用户的负担是非常重要的。因此全局引用缓存就很必要了,也就是_references.js.

打开这个文件,默认情况下该文件必须在应用程序根目录下的/scripts/目录中,这是个命名约定(ASP.NET MVC严重依赖约定)。包含在/scripts/_references.js文件中的项会自动添加至全局Intellisense。我们只需要这一个文件,它的内容类似如下:

/// <reference path="modernizr-2.6.2.js" /> 
/// <reference path="jquery-1.10.2.js" /> 
/// <reference path="bootstrap.js" /> 
/// <reference path="respond.js" />

只是一堆引用而已。这也是唯一一个在任何时候都会默认被加载到Intellisense的文件。用户现在只需要修改这个全局文件。用户的负担被减至最低。

修改命名约定

有些人不喜欢目录名/scripts/或者不喜欢文件名_references.js. 这非常正常,Visual Studio提供了自定义的方法。

我们假设有人喜欢使用/js/globals.js做为全局引用文件。– 不是针对某个特定的项目,而是通用配置。

按CTRL+Q打开“快速打开”输入框,然后输入javascript ref并从下拉菜单中选择这个选项:

_r2

在弹出的设置窗口中,下拉菜单选择Implicit (Web) :

_r3

Implicit (Windows)选项针对Windows Store apps,对web项目没有任何效果。反过来也一样。

在列表的底部,可以找到一个引用指向/Scripts/references.js:

_r4

现在你应该明白路径的语法了,很容易添加一个新的路径:~/js/globals.js. 如果你愿意,你可以添加任意多条路径。如果路径指向的文件不存在,Visual Studio 会自动忽略而不会有任何副作用。

波浪符加前斜杠 (~/) 表示网站的根目录.

全自动

新的编辑器已随着Visual Studio 2012一起发布, 但在开发Visual Studio 2013的时候, 我们决定改进这个流程。

开发人员仍然需要手工维护这个文件,这不是很方便。开发人员会经常增加,修改或者重命名JavaScript文件,但却总是忘记更新_references.js。

最好能够自动更新这个文件,因此所有.js文件自动被加 Intellisense。然而,如前文所述,可能会有性能问题和文件顺序问题,所以必须允许用户关闭自动更新功能,特别是出问题的时候。

我们不想增加一个VS的设置项,因为Visual Studio并没有针对单个项目的设置,而自动更新恰恰是项目级的配置。因此我们引入了一个新的三斜杠语法:auto-sync。

格式如下,它必须在每个_references.js文件的最顶部:

/// <autosync enabled="true" />

这条新的auto-sync 注释就是启用自动同步引用的语句。每当一个.js文件被添加,删除,移动或重命名,_references.js文件会自动更新。

在解决方案浏览器里,右键点击_references.js文件,会给出两个新的选项:

_r5

第一个是 Auto-sync JavaScript References。点击这个菜单时,会添加一条3斜杠auto-sync注释到文件顶部,如果你没有手动输入的话。非常方便,并且每个项目只需要设置一次。

第二个菜单是 Update JavaScript References。它会把当前项目里所有的.js文件添加到_references.js文件。它只会更新一次,并不会启用auto-sync.

有了这两个命令,你可以自由选择:自动同步或者在有兴趣的时候更新一次。

必须说明的是,启用_references.js的自动更新后,被引用的文件有可能排序不正确,从而引入bug,虽然可能性很低。就我个人而言,我已经在很多项目里使用了它,却没有遇到过任何问题。但以防万一,如果你真的遇到了麻烦,现在你知道怎么关闭它了。

所以伴随着Visual Studio 2013,我们最终把JavaScript Intellisense的3种方案都实现了。

生成_references.js文件

如果你的项目里还没有_reference.js文件,但你安装了Web Essentials 2013, 那么很容易添加一个。右键点击 /Scripts/ 目录,然后点击 Add,弹出的子菜单中选择—_references.js Intellisense 文件即可。

_r6

通过这种方式添加的_reference.js文件,会自动启用auto-sync。

这就是_references.js诞生及衍变的故事。它一直有改进的空间所以我们的工作永远没有完成。工作还在继续…

Leave a Reply

Your email address will not be published. Required fields are marked *