export/module.exports的用途是什么?

Kev*_*ers 15 angularjs browserify

今天我为我的AngularJS项目采用了Browserify,但有些东西对我来说非常不清楚.在所有示例和博客文章中我都看到过这样的内容:

/app.js:

require('./messages');
angular.module('sling', ['sling.messages']);
Run Code Online (Sandbox Code Playgroud)

/messages/index.js:

exports = angular.module('sling.messages', [])
    .controller('MessagesListCtrl', require('./MessagesListCtrl'));
Run Code Online (Sandbox Code Playgroud)

/messages/MessagesListCtrl.js:

module.exports = function() {
    // ...
});
Run Code Online (Sandbox Code Playgroud)

当然,这有效,但为什么这样呢?我已经像这样实现了它并且工作得非常好,并且对于AngularJS项目感觉更正常:

/app.js:

require('./messages');
angular.module('sling', ['sling.messages']);
Run Code Online (Sandbox Code Playgroud)

/messages/index.js:

angular.module('sling.messages', []);
require('./MessagesListCtrl');
Run Code Online (Sandbox Code Playgroud)

/messages/MessagesListCtrl.js:

angular.module('sling.messages').controller('MessagesListCtrl', function() {
    // ...
});
Run Code Online (Sandbox Code Playgroud)

换句话说,我完全跳过exports/module.exports,只使用require基本上包含控制器,服务,过滤器等的文件.

我这样做了吗?我的意思是一切正常,但我以后会遇到麻烦吗?

How*_*ett 33

如果您想在浏览器中使用CommonJS模块(即NodeJS模块),那么使用Browserify的主要原因(也是唯一的)理由是.CommonJS模块通过具有隐式"模块"范围而不在全局范围内.您可以通过扩充每个模块具有的"exports"对象来选择从模块范围(通常是模块的入口点或主要功能)公开的内容.

所以'真正的'CommonJS模块看起来像这样.

文件A:

// a.js

function doSomething() {
  console.log("I am doing something");
}

module.exports = doSomething
Run Code Online (Sandbox Code Playgroud)

档案B:

// b.js

doSomething();
// Exception - attempt to call a non-existent function
Run Code Online (Sandbox Code Playgroud)

文件C:

// c.js
var doSomething = require('a');
doSomething();
// logs "I am doing something"
Run Code Online (Sandbox Code Playgroud)

在没有模块范围的浏览器中,a.js将使用doSomething函数扩充全局范围,因为它被声明为全局范围.Browserify通过将每个捆绑模块包装到函数包装器中,并将"exports"对象作为此包装器的参数提供给包含的模块来解决此问题.

输入AngularJS.你可以在这里使用两种方法,其中我假设你没有使用require('angular')是第一种:

  1. Browserify转换的捆绑脚本之前,将AngularJS作为index.html中可用的硬编码脚本包含在内.
  2. Shim AngularJS,以便它附加到导出对象而不是窗口(使用类似browserify-shim的东西),然后使用require像任何其他模块一样导入它.

我倾向于选择第二种方法,因为使用Browserify为您提供模块范围,然后将项目的主要依赖关系视为全局窗口,这有点奇怪.

但是,AngularJS已经拥有自己的依赖注入驱动模块系统.声明angularJS组件时,您将它们附加到本身已附加到angular对象的模块对象.这意味着exports在Angular的情况下,angularJS模块文件的对象本质上是多余的,因为只要文件执行,那么angular对象将使用您的模块和组件进行扩充.

你仍然需要'需要'文件,否则Browserify不会捆绑它们,它们永远不会执行,它们永远不会angular用你的模块扩充对象.但你并不需要添加任何东西到出口角,因为angular对象是你的出口.

那么为什么我花了这么多时间来解释CommonJS模块和导出是如何工作的呢?因为希望您使用Browserify 的另一个原因是允许您在浏览器应用程序中使用NPM上托管的模块.这些模块中的大多数是非角度commonJS模块,这意味着它们的功能通过导出公开.在这种情况下,重要的是在需要时捕获变量中的导出,例如我在c.js上面做的.类似地,如果你编写一些模块并将它们发布到NPM,那么你的用户会希望你将模块的入口点添加到你exports声明为main的文件的对象中package.json.

  • 谢谢你的详细解答!我实际上放弃了Browserify,只是使用bower,gulp和concat(+ sourcemaps).很简单,做我需要的. (2认同)