JavaScript 依赖管理

Posted

技术标签:

【中文标题】JavaScript 依赖管理【英文标题】:JavaScript dependency management 【发布时间】:2011-03-13 06:28:18 【问题描述】:

我目前正在维护大量的 JS 文件,并且依赖问题越来越严重。现在我将每个函数都放在一个单独的文件中,并且我手动维护一个数据库来计算函数之间的依赖关系。

这我想自动化。例如,如果我有函数 f

Array.prototype.f = function() ;

在另一个函数 g 中被引用

MyObject.g = function() 
    var a = new Array();
    a.f();
;

我希望能够检测到 g 正在引用 f。

我该怎么做?我从哪里开始?我是否需要实际编写一个编译器,或者我可以调整 Spidermonkey 吗?其他人已经这样做了吗?

非常感谢任何让我入门的指针

谢谢 多克

【问题讨论】:

您想生成一个图表来显示哪些函数被哪些其他函数调用?这就是我目前正在尝试做的事情,我想知道您是否正在尝试解决与我相同的问题。 :) @AndersonGreen 你在寻找类似Code2Flow的东西吗? 【参考方案1】:

我写了一个工具来做这样的事情:http://github.com/damonsmith/js-class-loader

如果你有一个 java webapp 并且你用 java 风格构建你的 JS 代码,这是最有用的。如果您这样做,它可以检测您的所有代码依赖项并将它们捆绑在一起,同时支持运行时和解析时依赖项。

【讨论】:

【参考方案2】:

您是否尝试过使用像 RequireJS 或 LabJS 这样的依赖管理器?我注意到没有人在这个帖子中提到它们。

来自http://requirejs.org/docs/start.html

在 main.js 中,您可以使用 require() 来加载您需要的任何其他脚本 需要运行:

require(["helper/util"], function(util) 
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
);

您也可以嵌套这些依赖项,因此 helper/util 可以在其内部需要一些其他文件。

【讨论】:

【参考方案3】:

JSAnalyse 使用静态代码分析来检测 javascript 文件之间的依赖关系: http://jsanalyse.codeplex.com/

它还允许您定义允许的依赖项并在构建期间确保它,例如。当然,它不能检测到所有依赖项,因为 javascript 是动态解释语言,它不是类型安全的,就像已经提到的那样。但它至少让您了解您的 javascript 依赖关系图并帮助您控制它。

【讨论】:

【参考方案4】:

如果有一个工具可以自动为您检测这些依赖项并选择它们的加载方式,那就太好了。不过,今天最好的解决方案有点粗糙。我为我想要添加到列表中的特定需求创建了一个依赖管理器 (Pyramid Dependency Manager)。它具有一些关键功能,可以解决一些独特的用例。

    处理其他文件(包括为视图插入 html...是的,您可以在开发过程中分离视图) 当您准备好发布时,在 javascript 中为您组合文件(无需安装外部工具) 对所有 html 页面都有一个通用的包含。当依赖项被添加、删除、重命名等时,您只需更新一个文件

一些示例代码来展示它在开发过程中是如何工作的。

文件:dependencyLoader.js

//Set up file dependencies
Pyramid.newDependency(
    name: 'standard',
    files: [
    'standardResources/jquery.1.6.1.min.js'
    ]
);

Pyramid.newDependency(
name:'lookAndFeel',
files: [
    'styles.css',
    'customStyles.css',
    'applyStyles.js'
    ]
);

Pyramid.newDependency(
name:'main',
files: [
    'createNamespace.js',
    'views/buttonView.view', //contains just html code for a jquery.tmpl template
    'models/person.js',
    'init.js'
    ],
    dependencies: ['standard','lookAndFeel']
);

HTML 文件

<head>
    <script src="standardResources/pyramid-1.0.1.js"></script>
    <script src="dependencyLoader.js"></script>
    <script type="text/javascript">
        Pyramid.load('main');
    </script>
</head>

它确实需要您维护一个文件来管理依赖项。我正在考虑创建一个程序,该程序可以根据头文件中的包含自动为您生成加载程序文件,但由于它处理许多不同类型的依赖项,因此将它们维护在一个文件中实际上可能会更好。

【讨论】:

【参考方案5】:

正如@bobince 已经建议的那样,对 JavaScript 程序进行静态分析是一个几乎不可能破解的问题。 Google Closure compiler 在某种程度上做到了,但它也依赖于来自 JSDoc cmets 的外部帮助。

我有一个similar problem 查找在以前的项目中应该连接 JS 文件的顺序,并且由于有大量 JS 文件,手动更新包含顺序似乎太乏味了。相反,为了我的目的,我坚持使用某些构成依赖项的约定,并基于此并使用简单的regexp :) 我能够生成正确的包含顺序。

该解决方案使用topological sort 算法生成dependency graph,然后按照它们应包含的顺序列出文件以满足所有依赖关系。由于每个文件基本上都是使用MooTools 语法的伪类,因此对于我的情况,只有三种方式可以创建依赖项。

    当一个类扩展了其他类时。 当一个类实现了其他类时。 当一个类使用 new 关键字实例化某个其他类的对象时。

这是一个简单的,对于一般用途来说绝对是一个破碎的解决方案,但它对我很有帮助。如果您对该解决方案感兴趣,可以查看code here - 它使用 Ruby。

如果您的依赖关系更复杂,那么也许您可以使用 cmets 和一些本地语法手动列出每个 JS 文件本身中的依赖关系,例如:

// requires: Array
// requires: view/TabPanel
// requires: view/TabBar

然后读取每个 JS 文件,解析出所需的 cmets,并构建一个依赖关系图,它将为您提供所需的包含顺序。

【讨论】:

【参考方案6】:

虽然理论上您可以编写一个静态分析工具来检测其他文件中定义的全局变量的使用情况,例如 MyObject 的使用情况,但您实际上无法跟踪 prototype 扩展方法的使用情况。

JavaScript 是一种动态类型语言,因此任何工具都无法知道a,如果从g 函数中传递出来,是一个Array,所以如果f() 被调用它有一个依赖。它只会在运行时确定哪些变量包含哪些类型,因此要找出您需要一个解释器并且您已经让自己成为一个图灵完备的问题。

更不用说 JavaScript 中完全无法进行静态分析的其他动态方面,例如通过方括号表示法获取属性、可怕的 eval 或超时字符串或事件处理程序属性。

我认为这真的有点不适合。您可能最好手动跟踪依赖项,但通过将相关功能分组到模块中来简化它,这将是您的依赖项跟踪的基本单元。好的,您将引入更多技术上需要的功能,但希望不要太多。

为每个模块命名也是一个好主意,因此每个调用的去向非常清晰,从而可以轻松地手动控制依赖关系(例如,通过顶部的 // uses: ThisModule, ThatModule 注释)。

由于内置原型的扩展更难跟踪,因此请将它们保持在最低限度。扩展例如。 Array 将 ECMAScript 第五版方法(如 indexOf)包含在尚未拥有它们的浏览器上是一件好事,因为它是所有脚本都将使用的基本修复。向现有原型添加全新的任意功能是值得怀疑的。

【讨论】:

感谢您的回答...那我将采取不同的路线。

以上是关于JavaScript 依赖管理的主要内容,如果未能解决你的问题,请参考以下文章

如何管理客户端JavaScript依赖项? [关闭]

php 管理wordpress中的Javascript依赖项

javascript Bower - 管理你的客户端依赖关系

JavaScript 依赖管理:npm vs. bower vs.volo [关闭]

JavaScript 依赖管理:npm vs. bower vs.volo [关闭]

使用clean RVM的链轮JavaScript依赖关系管理工具