如何在多个grunt-browserify包中pipe理相对path别名?

这是很长的,但我需要代码示例来说明我的困惑。 之后我有兴趣回答以下几点:

  1. 如何使用require('module')而不是require('../../src/module')require('./module')
  2. 如何在spec/specs.js重复使用spec/specs.js而不重复工作? (并防止src/app.js运行,因为它是一个入口模块)。

我已经开始了几个基于浏览器的项目,并且喜欢browserify和grunt。 但是,每个项目都在我的开发/学习曲线中死去。 一旦我将testing添加到组合中,并且必须pipe理两个spec/specs.js包( app.jsspec/specs.js ),整个系统就会崩溃。 我会解释一下:

我使用grunt-browserify并设置我的初始目录:

 . ├── Gruntfile.js ├── index.js (generated via grunt-browserify) [1] ├── lib │  ├── jquery │  │  └── jquery.js [2] │  └── jquery-ui │  └── jquery-ui.js [3] ├── spec │  ├── specs.js (generated via grunt-browserify) [4] │  └── src │  ├── spec_helper.js (entry) │  └── module_spec.js (entry) └── src  ├── app.js (entry)  └── module.js 
  1. 使用一个条目文件( src/app.js )并执行代码遍历所有需要的模块。
  2. 使用browserify-shim别名jquery
  3. 只是别名jquery-ui没有垫片(需要你var $ = require('jquery') )。
  4. 使用spec/src所有帮助器和spec文件作为input模块。

我将通过我的configuration:

 browserify: { dist: { files: { 'index.js': ['src/app.js'] } } } // in app.js var MyModule = require('./module'); // <-- relative path required?! 

快乐

现在添加jquery:

 browserify: { options: { shim: { jquery: { path: 'lib/jquery/jquery.js', exports: '$' } }, noParse: ['lib/**/*.js'], alias: [ 'lib/jquery-ui/jquery-ui.js:jquery-ui' ] }, dist: { files: { 'index.js': ['src/app.js'] } } } // in app.js var $ = require('jquery'); require('jquery-ui'); var MyModule = require('./module'); 

快乐

现在添加规格:

 options: { shim: { jquery: { path: 'lib/jquery/jquery.js', exports: '$' } }, noParse: ['lib/**/*.js'], alias: [ 'lib/jquery-ui/jquery-ui.js:jquery-ui' ] }, dist: { files: { 'app.js': 'src/app.js' } }, spec: { files: { 'spec/specs.js': ['spec/src/**/*helper.js', 'spec/src/**/*spec.js'] } } // in app.js var $ = require('jquery'); require('jquery-ui'); var MyModule = require('./module'); // in spec/src/module_spec.js describe("MyModule", function() { var MyModule = require('../../src/module'); // <-- This looks like butt!!! }); 

伤心

总结:我如何…

  1. 使用require('module')而不是require('../../src/module')require('./module')
  2. spec/specs.js重复使用./index.js而不重复工作? (并防止src/app.js运行,因为它是一个入口模块)。

这些答案取决于你的项目的其余部分是如何设置的,但也许这是一个很好的起点。 此外,您将需要使用grunt-browserify的当前v2 beta来实际工作( npm install grunt-browserify@2 )。

1。

您可以使用aliasMapping为您的模块创build一些dynamic别名。 为了清楚起见,我们把所有的模块移到src/modules/ 。 然后,aliasMappingconfiguration可能是这样的:

 options: { aliasMappings: { cwd: 'src', src: ['modules/**/*.js'] } } 

让我们假设你在src/modules/magic/stuff.js有一个模块,那么你可以这样要求它,而不pipe在做需求的.js文件的位置:

 var magicStuff = require('modules/magic/stuff.js'); 

2。

不知道这个。 您的项目结构显示spec/index.js ,但您提到spec/specs.js 。 他们应该是同一个文件吗?

无论如何,你在说什么重复的工作? 因为./index.jsspec/index.js有不同的入口文件。 如果你正在寻找一种方法来在specs/包含./index.js ,那么也许你可以在运行testing之前复制它,而不是从头开始构build它。

简单的回答:

最简单的是使用browserify的paths选项。 我用了几个月,取得了巨大的成功。 我甚至做了一个使用这个function的入门工具包: https : //github.com/stample/gulp-browserify-react-phonegap-starter

 var b = browserify('./app', {paths: ['./node_modules','./src/js']}); 

paths – 如果在正常的node_modulesrecursion步骤中找不到任何东西,则使用require.paths数组

如果你在src/js/modulePath/myModule.js有一个文件,这不会让你在任何地方编写require("myModule") ,而是从你的其他源文件中require("modulePath/myModule")

已弃用的选项?

这似乎不是这样!

Browserify模块parsingalgorithm镜像NodeJS中的parsingalgorithm 。 Browserify的paths选项因此是NODE_PATH envvariables行为的镜像。 Browserify作者(substack)在本SO主题中声称NODE_PATH选项在NODE_PATH被弃用,因此在Browserify中也被弃用,并且可能在下一版本中被删除。

我不同意这个说法。

请参阅NODE_PATH文档。 没有提到该选项已被弃用。 然而,还是有一个有趣的提到,这是在suback的索赔方向:

强烈build议您将您的依赖项本地放置在node_modules文件夹中。 他们将被加载更快,更可靠。

而这个问题已经在2012年发布在邮件列表上。

 Oliver Leics: is NODE_PATH deprecated? Ben Noordhuis (ex core NodeJS contributor): No. Why do you ask? 

如果在NodeJSparsingalgorithm中没有删除某些内容,我认为它不会很快从Browserify中移除:)

结论

您可以使用paths选项,也可以将代码放在node_modules如官方文档和Browserify作者推荐的 。

就我个人而言,我不喜欢把自己的代码放在node_modules因为我只是把这个文件夹放在我的源代码控制之外。 我现在使用paths选项已经有几个月了,根本没有任何问题,而且我的构build速度也相当不错。

node_modulesnode_modules里放一个符号链接的解决scheme可能很方便,但不幸的是我们有开发人员在这里使用Windows …

但是,我认为有些情况下,您不想使用paths选项 :当您正在开发在其他应用程序需要的NPM存储库上发布的库时。 你真的不希望这些库客户端必须设置特殊的构buildconfiguration,只是因为你想避免在你的lib中的相对path地狱。

另一个可能的select是使用remapify

这里关于别名和opts.paths / $NODE_PATH所有答案$NODE_PATH是很好,因为这个方法在node和$NODE_PATH中是模块系统的一个不推荐的部分,所以它可能随时停止工作。

您应该了解node_modulesalgorithm是如何工作的,这样您就可以用嵌套的node_modules目录很好地组织代码。

在browserify手册中有一节介绍避免../../../../../../ ..相对path问题。 可以概括为:

  • 把你的内部模块化代码放在node_modules/node_modules/app这样你就可以根据自己喜好selectrequire('yourmodule')还是require('app/yourmodule')
  • 如果您正在为非Windows平台开发,则可以使用符号链接,而这正是您所喜欢的。

不要使用opts.path / $NODE_PATH 。 它使你的项目:

  • 隐含地依赖于非显而易见的configuration或环境设置
  • 难以在节点和浏览器中工作
  • 由于在节点和浏览器中不build议使用数组path,所以易受模块系统中的更改影响

正如Sebastien Lorber所指出的,我认为最好的方式就是在通过pipe道调用browserify的过程中设置path。

但是,使用browserify的最新版本(截至目前,这是browserify@11.0.0 ),pathvariables存储了Browserify将用于其进程的唯一path。 所以设置pathvariables将排除说…您的节点的全局文件夹,据我所知。 因此,你需要一个Gulp任务,看起来像这样:

 gulp.task('reactBuild', function() { return gulp.src(newThemeJSX) .pipe(browserify({ debug: true, extensions: ['.jsx', '.js', '.json'], transform: [reactify], paths: ['../base_folder/node_modules', '/usr/lib/node_modules'] })) .pipe(gulp.dest(newThemeBuilt)) .on('error', function(error) { console.log(error); }); });