在Browserify和NPM中需要根路径(摆脱'../../../ ..'两个地方)

时间:2015-10-02 18:34:22

标签: javascript npm gulp browserify

我一直在寻找解决这个问题的方法,但到目前为止还没有运气 - 甚至使用awesome gist about better local require paths并阅读并重新阅读了Avoiding ../../../../..上的Browserify手册的条目,我似乎无法为这个问题找到一个有效的解决方案。

我有一个用Browserify构建的库,我正在尝试发布到npm,如果你想测试我在这里描述的内容,你可以find for yourself。问题是:我想将其发布到NPM而不使用require()调用中的相对路径,这就是我在使用Browserify时的工作方式。

请参阅使用Browserify的opts.paths我可以更改require()之类的内容

var Classy$Base = require('./base')
// and in another file
var Classy$Module = require('../../module')

var Classy$Base = require('classy/base')
// and in another file
var Classy$Module = require('classy/module')

哪个好极了!而且效果很棒!当我gulp bundle我恢复工作classy.bundle.js时,生活就会好起来。

那么我npm link和另一个项目(也使用Browserify),npm link classy-js,没有任何作用。我从require('classy-js')内部收到错误,说“无法从'node_modules / classy-js / src ...'中找到模块'classy / base'等等。”

我希望能够创建一个我可以require('classy-js')require('classy-js/classy/module')的库,并且可以访问库中所有其他有用的子模块,而不会牺牲库中的非相对路径自己的代码。

有没有办法可以做到这一点?

我尝试使用app-module-path但在使用时出现了Browserify错误,我尝试使用require-root来获得类似结果。

我也尝试过符号链接,并添加了一个npm postInstall脚本来自动生成符号链接,但也无济于事。

看起来这真的不应该那么难......

2 个答案:

答案 0 :(得分:0)

嗯,它可能不受欢迎,我不确定我是否已经在npm上看到过这样做的包,但我认为这样可行:

// Name of module. I.e. same value as the `name` prop in `package.json`.
var Classy$Base = require('classy-js/base')
// and in another file
var Classy$Module = require('classy-js/module')

回复:这部分:

  

那么我npm link和另一个项目(也使用Browserify),npm link classy-js,没有任何作用。

为了使这项工作与第一个建议一起使用,npm link classy-js 自身(几乎)。假设你有/somedir/subdir/classy-js。确保有/somedir/subdir/node_modules,然后导航到/somedir/subdirnpm link classy-js。请确保您没有来自/somedir/subdir/classy-js/node_modules的{​​{1}}和npm link,否则您将获得一个循环引用,以免搞砸模块解析。

答案 1 :(得分:0)

在我看来,我已经解决了这个问题,虽然答案真的很愚蠢。虽然JMM's answer可能有效,但我没有采取这种方式。

由于两个项目都在使用Browserify,我只需要通过执行require('classy-js')就可以在第二个项目中使用classy,并且它知道查看node_modules并找到它。但是,由于Browserify没有使用它在构建Classy捆绑时所做的opts.paths,因此它不知道如何解析require('classy/base')之类的路径。有了这个,我们就会收到一堆错误。

解决方案是一个npm postinstall脚本,它创建一个空的node_modules文件夹(Classy没有依赖项,只有devDependencies),符号链接node_modules/classysrc/classynode_modules/selfish(另一个顶层) src /中的-level模块到src/selfish。这样我们就不会混淆单独项目的opts.paths,我们更好的require()也会在节点中运行。

postinstall看起来像这样:

// package.json
...
  "scripts": {
    "test": "gulp test",
    "postinstall": "mkdir node_modules && node create-symlinks.js"
  },
...

create-symlinks.js看起来像

// create-symlinks.js
var fs = require('fs')

var c  = '../src/classy'
  , s  = '../src/selfish'
  , cd = 'node_modules/classy'
  , sd = 'node_modules/selfish'
  , e  = undefined

e = fs.existsSync(cd);
if (!e) {
  console.log('link', cd, 'to', c)
  fs.symlinkSync(c, cd, 'dir')
}

e = fs.existsSync(sd)
if (!e) {
  console.log('link', sd, 'to', s)
  fs.symlinkSync(s, sd, 'dir')
}

它感觉到hack-y和错误,但是它起作用并且它使用了与"更好的本地需求"中给出的符号链接建议类似的约定。要旨。就是这样。

在Classy中访问子模块时,只需将任何公共API子模块(如Classy $ Module)公开为顶级Classy对象的字段,就更容易了(读:可能)。所以现在而不是做

var Classy$Module = require('classy-js/module')

或类似的东西,它只是

var Classy$Module = require('classy-js').Module

虽然不完全理想,但仍然有效,并且足够好。"