Nodejs:将index.js用于EXPORTS的好习惯?

时间:2016-05-24 15:07:24

标签: javascript node.js iojs

我看到一些我继承的代码的模式。每个目录都有自己的JS文件,但也有一个index.js实际上从其他JS文件中导出项目。

我认为这样做是为了让你可以准确看到你要导出的内容,因为主要的导出是在index.js中,而主要的代码是在其他js文件或文件中。

这是对的吗?这种模式叫什么?

我应该继续使用这种模式。

5 个答案:

答案 0 :(得分:6)

我们说我有以下目录结构:

MyApp
├── app.js
├── test.js
├── package.json
├─┬ controllers
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
└─┬ views
  ├── index.js
  ├── signIn.js
  └── signOut.js

将以下代码放在index.js个文件中......

// index.js
module.exports = {
  signIn: require('./signIn')
, signOut: require('./signOut')
};

...允许您require整个目录,如...

// test.js
describe('controllers', () => {
  // ~/controllers/index.js
  const controllers = require('./controllers');

  it('performs a sign-in', () => {
    ...
  });
  it('performs a sign-out', () => {
    ...
  });
});

另一种方法是单独require每个文件。

不需要在目录中包含index.js。您可以require目录中没有index.js的文件。

// app.js
const signOut = require('./controllers/signOut.js')

但是,随着应用程序的增长,这会变得乏味。我使用像require-directory这样的包,因为在目录中输入每个文件也很乏味且容易出错。

// index.js
module.exports = require('require-directory')(module);

/*

This yields the same result as:

module.exports = {
  signIn: require('./signIn')
, signOut: require('./signOut')
, ...
};

*/

答案 1 :(得分:2)

其他答案提供了很多很棒的信息,但是为了尝试专门回答你的问题'我应该继续使用这种模式吗',我会说不,至少在大多数情况下。

问题是,这种模式需要额外的努力,因为你必须维护那些额外的index.js文件。根据我的经验,努力比简单地编写一个目录更长import语句的努力更大。此外,通过使用index.js等模块,您可以获得与require-dir无法获得相同的功能。

所有这一切,如果你要创建一个将被大量人员使用的库,如大型编程部门或公共NPM模块中的关键模块,那么index.js的努力变得更有道理。只要您有足够的人使用您的模块,您的用户将(累积地)从添加它们中节省更多时间,而不是丢失维护它们。

答案 2 :(得分:1)

ES6 CommonJS模块语法

鉴于这两种常见类型的结构......

MyApp
│ // files divided per type (controllers, components, actions, ...)
├─┬ actions
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
├─┬ components ...
├─┬ reducers ...
├─┬ pages ...
│ 
│ // files divided per component
├─┬ components ...
│ ├── index.js 
│ ├── SimpleComponent.jsx
│ ├── AnotherComponent.duck.jsx // redux "duck" pattern
│ ├─┬ ComplexComponent // large complex logic, own actions, stylesheet, etc.
│ ...
├─┬ pages ...
│ ├── index.js 
│ ├─┬ App
│ │ ├── index.js // not necessary here, matter of habit
│ │ ├── App.jsx
│ │ ├── actions.js
│ │ └── reducer.js
│ └─┬ Dashboard
├── another.js
...

您只需导入another.js中的文件

即可
import {signIn, signOut} from './actions'
import {App} from './pages'
import {ComplexComponent} from './components'

而不是(没有index.js个文件)

import {signIn} from './actions/signIn'
import {signOut} from './actions/signOut'
import {App} from './pages/App/App' //notice the redundancy here
import {ComplexComponent} from './components/ComplexComponent/ComplexComponent'

更多阅读

ECMAScript 6 modules
import - JavaScript | MDN
Babel transpiler - 现在将新导入内容添加到您的浏览器中
Structuring React projects
React Redux "Ducks pattern" - 组件的单一文件方法

答案 3 :(得分:0)

这个怎么样?

module.exports = {
  ...require('./moduleA'),
  ...require('./moduleB')
}

(moduleA.a 将被 moduleB.a 覆盖)

答案 4 :(得分:0)

我将直接深入探讨您关于是否使用此模式的问题(因为其他答案不足以解决此问题)。

假设代码中的每个目录都代表一个独立的模块(不依赖于另一个模块来工作)。使用此模式将带来以下优势:

  1. 更好、更有条理的导入
  2. 每个模块的内部/外部定义之间的分离(类似于在接口/API 上使用私有/公共)

这个问题:

  1. 保持不同模块的松耦合可能会很烦人(JS/TS 不是纯 OOP)
  2. 需要主动重构模块定义 - 更多循环依赖。
  3. 将更多代码加载到内存中(即使未使用) - 尽管我不确定这有多糟糕,因为在捆绑生产代码时通常会进行优化来解决此问题。

循环依赖是非常有问题的,使用 index.js 导入整个模块/目录将导入它的所有部分(在 index.js 中声明)所以如果你有:

-- moduleA 
├-- comp1A // needs comp1B
├-- comp2A     
└-- index.js // export both comp1/2

-- moduleB
├-- comp1B 
├-- comp2B // needs comp2A
└-- index.js // export both comp1/2

示例 - comp1A 需要来自 comp1B 的东西而 comp2B 需要来自 comp2A 的东西

导入特定文件时(没有 index.js - import something from './moduleB/comp1B'),您不会有循环依赖。

但是如果你使用 index.js (import something from './moduleB') 你将会有循环依赖。

我的建议是在正确的位置使用 index.js,并保持这些位置!将 index.js 与小模块一起使用将是完美的,但随着时间的推移它们会增长并且应该分开。 index.js 在 common/shared/utils/misc/core(当您想放置在整个项目中使用的未分类和不相关的代码时,无论您怎么称呼它)模块中使用是非常糟糕的。