javascript - 在 Browserify 和 NPM 中需要根路径(在这两个地方都去掉 '../../../..')

标签 javascript npm gulp browserify

我已经四处寻找解决这个问题的方法,但到目前为止运气不佳 - 即使使用 awesome gist about better local require paths并阅读和重新阅读 Browserify 手册中关于 Avoiding ../../../../.. 的条目,我似乎找不到解决这个问题的有效方法。

我有一个用 Browserify 构建的库,我正在尝试将其发布到 npm,您可以 find for yourself如果你想测试我在这里描述的内容。问题是:我想在调用 require() 时不使用相对路径将它发布到 NPM,这就是我使用 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具有相似的结果。

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

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

最佳答案

在我看来我已经解决了这个问题,虽然答案真的很愚蠢。虽然JMM's answer可能有用,我没有走那条路。

由于这两个项目都使用 Browserify,我可以通过 require('classy-js') 将 classy 要求到第二个项目中,它知道在 node_modules 中查找并找到它。但是,由于 Browserify 没有使用它在构建 Classy 包时使用的 opts.paths,它不知道如何解析像 require('classy/base') 这样的路径。仅此而已,我们会得到一堆错误。

解决方案是一个 npm postinstall 脚本,它创建一个空的 node_modules 文件夹(Classy 没有依赖项,只有 devDependencies)和符号链接(symbolic link) node_modules/classysrc/classynode_modules/selfish(src/中的另一个顶级模块)到 src/selfish。这样我们就不会弄乱单独项目的 opts.paths 并且我们更好的 require() 也可以在节点中工作。

安装后看起来像这样:

// 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')
}

感觉很乱,而且是错误的,但它确实有效,并且它使用与“更好的本地需求”要点中给出的符号链接(symbolic link)建议类似的约定。就是这样。

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

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

或者类似的东西,它只是

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

虽然不完全理想,但可以工作并且“足够好”。

关于javascript - 在 Browserify 和 NPM 中需要根路径(在这两个地方都去掉 '../../../..'),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32913650/

相关文章:

javascript - 从Django传递值到Ajax,如何识别变量类型?

node.js - 如何从 npm 发布的模块中导入流注解、类型和接口(interface)

javascript - meteor :ReferenceError:要求未定义

javascript - Browserify 需要目录中的所有文件

javascript - 让 Stylus 将导入的 CSS 合并到样式表中

javascript - 如何自定义货币过滤器以在 angularJS 中显示货币符号 '€' 或任何其他货币符号

javascript - 定位父窗口

javascript - 选项卡在 jQuery 中不起作用?

node.js - NPM 和 NVM 的区别

javascript - 具有 scss 的 node_module 上出现 Gulp 错误