Node.js:如何通过require()将全局变量传递给被插入的文件?

12

我已将gulpfile.js拆分成几个文件,并放在一个名为/gulp的文件夹中,以更好地组织代码。但现在我想要传递一个名为debug(布尔)的变量到这些文件中,以切换包含的gulp命令的行为(最终我将使用命令行参数,但现在我只想用一个变量来实现它)。

我使用的设置方式是,在看到yeoman angular/gulp套件中的一个方法后,使用了一个名为require-dir的npm模块(它会加载/gulp文件夹中的所有*.js文件,其中每个文件都有一组gulp任务被设置)。

gulpfile.js:

var gulp = require('gulp'),
  run = require('run-sequence'),
  debug = true;

require('require-dir')('./gulp');

gulp.task('default', ['build', 'server', 'watch', '...']);

这会加载类似于...

gulp/build.js:

var gulp = require('gulp'), 
  plumber = require('gulp-plumber'),
  ...;

gulp.task('build', function () {
  console.log(debug);
});

当我运行gulp命令时,它会执行default任务,加载build.js文件并运行buildgulp任务。但不幸的是,debug返回undefined。

我该怎么做才能让它工作呢?

我尝试使用module.exports()和node的require()方法,但我无法弄清楚如何在包含的文件中声明gulp任务,以便可以从主gulpfile.js文件中运行它(按照所需的顺序)。

有人能提供一些帮助吗?谢谢

3个回答

10

通常的模块方式,只需将gulp/build.js文件从未实际导出任何内容更改为一个可正常需要的模块即可:

module.exports = function(debug) {
  "use strict";

  var gulp = require('gulp'), 
      plumber = require('gulp-plumber'),
      ...;

  gulp.task('build', function () {
    console.log(debug);
  });
};

然后在您的主文件中调用它:

...
var loadGulp = require('require-dir/gulp');
...
var debug = true;
loadGulp(debug);

1
理论上,在运行loadGulp()方法后,gulp任务应该已经被注册了,那么我就可以运行gulp.start('build')并且它会可用,对吗? - BuildTester1
1
正确。require('require-dir/gulp') 操作现在加载一个函数,运行该函数现在注册 gulp 任务,之后可以像其他任务一样调用它。 - Mike 'Pomax' Kamermans
有没有一种方法可以在导入时自动初始化 require 文件,这样我就不必调用函数了?例如:require('gulp/build.js'); 而不是 var build = require('gulp/build.js') - BuildTester1
2
...它仍然是JavaScript。require('./gulp/build')(debug);可以正常工作,但看起来很奇怪,所以您可能想将module.exports更改为返回一个对象{ loadTask: function(debug) { ... } };,这样您的主代码调用看起来像require('./gulp/build').loadTask(debug);。这样更加舒适,也更合理作为代码调用。 - Mike 'Pomax' Kamermans
很棒,require('./gulp/build').loadTask(debug); 看起来不错!感谢你的所有帮助! - BuildTester1

6

Node.js提供了一个名为global的单一全局变量,实际上,在所有模块中都是相同的实例(不像每个模块中不同的module)。 通过在global上设置值,它们变成真正的全局变量。额外的好处是,您不需要使用global.前缀访问全局变量。 只要您没有另一个名为foo的变量处于作用域内,global.foofoo是等效的。


这是一个非常糟糕的想法,特别是如果任何其他模块都要访问全局状态。您永远不应该污染全局状态,只需创建一个生成器函数,将您的参数传递给它,以获取实际需要运行的完全限定函数。 - Mike 'Pomax' Kamermans
虽然我完全同意尽可能避免使用全局变量,但有时它们是有用且合适的。话虽如此,在Node中知道如何使用它们还是很方便的。 - Andrew Miner
这不是那种时候。 - Mike 'Pomax' Kamermans
2
它们在某些情况下非常适用,例如一个变量可能在运行时改变或不改变,但在整个应用程序中都被使用。并非所有的应用程序都是Web应用程序,有时它们是工作程序,其特定要求可能与正常意识相分离。因此,这是正确的答案,而不是Mike基于他的理论“全局变量是邪恶的”所提出的教条主义答案。如果你懒得把所有东西放在全局范围内,那么全局变量就是邪恶的,但它们存在有其原因,有无数的理由为什么有时候需要它们。 - Sandwich

2
我创建了一个包含所有变量的对象,并将其导出为模块,这样我就可以在所有任务文件中使用它。例如: js/tasks/variables.js
module.exports = {
    myBool: true
};

js/tasks/sass.js

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    log = $.util.log,
    vars = require('./variables');

gulp.task('sass', function () {
    log('myBool: ' + vars.myBool); // logs "myBool: true"
    vars.myBool = false;
});

js/tasks/build.js

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    log = $.util.log,
    vars = require('./variables');

gulp.task('build', function () {
    log('myBool: ' + vars.myBool); // logs "myBool: false"
});

/gulpfile.js

然后你可以在任何地方获取/设置这些变量:

var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    runSequence = require('run-sequence'),
    vars = require('./js/tasks/variables'),
    requireDir = require('require-dir')('./js/tasks');

gulp.task('production', function(){
    runSequence('sass', 'build');
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接