【问题标题】:npm install dependencies of a git submodulenpm 安装 git 子模块的依赖项
【发布时间】:2014-02-17 06:08:29
【问题描述】:

我有一个带有 handlebars.js 作为子模块的 git 项目。我将在这里提供一个简单的示例 - 完整的项目更加复杂,其中包含与此处无关的 dojo 任务和部署步骤。

$ mkdir handlebarstest ; cd handlebarstest ; git init
$ mkdir src ; git add src
$ git submodule add https://github.com/wycats/handlebars.js.git src/handlebars.js

我们的package.json 没有提到handlebars.js,只是咕哝:

{
  "name": "handlebarstest",
  "version": "1.0.0",
  "dependencies": {},
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-clean": "~0.4.1",
    "grunt-run-grunt": "latest"
  }
}

在这个项目的历史中,我们的安装和构建过程是:

$ npm install   # install dependencies in package.json
$ grunt init    # run the 'init' task which initialises git submodules
$ grunt build   # run the 'build' task which compiles dojo etc.

已经完成了我们项目的全新克隆,比如在我们的构建服务器上,需要初始化 git 子模块,我们从 grunt 控制它,所以我们必须先安装 grunt,然后运行一个任务来初始化子模块,包括麻烦的把手.js。

我们执行 npm install 并安装 grunt,并安装 grunt init 获取 handlebars.js,包括其 package.json。所以我们问题的根源是当顶层npm install运行时package.json不可用。

我们的 Gruntfile.js 知道如何调用 handlebars.js 中的 Gruntfile.js:

/*jshint node:true */
module.exports = function (grunt) {
    /*jshint camelcase: false */
    var path = require('path');

    grunt.initConfig({
        clean: [ 'dist' ],
        run_grunt: {
            options: {

            },
            handlebars_build: {
                options: {
                    log: true
                },
                src: [ 'src/handlebars.js/Gruntfile.js' ],
                task: 'build'
            },
            handlebars_amd: {
                options: {
                    log: true
                },
                src: [ 'src/handlebars.js/Gruntfile.js' ],
                task: 'amd'
            }
        }
    });

    // var handlebarsLink= grunt.registerTask('handlebarsLink', function () {
    //  var done = this.async(),
    //      child = grunt.util.spawn({
    //          cmd: 'npm',
    //          args: [ 'link', 'src/handlebars.js' ]
    //      }, function (error) {
    //          if (error) {
    //              grunt.warn(error);
    //              done(false);
    //              return;
    //          }
    //          done();
    //      });

    //  child.stdout.on('data', function (data) {
    //      grunt.log.write(data);
    //  });
    //  child.stderr.on('data', function (data) {
    //      grunt.log.error(data);
    //  });
    // });
    var submodules;
    if (grunt.file.exists(__dirname, '.git')) {
        submodules = grunt.registerTask('submodules', function () {
            var done = this.async(),
                child = grunt.util.spawn({
                    cmd: 'git',
                    args: [ 'submodule', 'update', '--init', '--recursive' ]
                }, function (error) {
                    if (error) {
                        grunt.warn(error);
                        done(false);
                        return;
                    }
                    done();
                });

            child.stdout.on('data', function (data) {
                grunt.log.write(data);
            });
            child.stderr.on('data', function (data) {
                grunt.log.error(data);
            });
        });
    }
    var init = submodules ? [ 'submodules'/*, 'handlebarsLink'*/ ] : [];
    grunt.registerTask('init', init);
    grunt.registerTask('default', 'build');
    grunt.registerTask('build', init.concat([ 'clean', 'run_grunt:handlebars_build', 'run_grunt:handlebars_amd' ]));

    grunt.loadTasks(path.join(__dirname, 'grunt'));
    grunt.loadTasks(path.join(__dirname, 'src', 'intern', 'tasks'));
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-run-grunt');
};

运行 grunt 失败,因为它递归到了 handlebars.js,但它的 package.json 中的模块依赖项尚未安装。

Running "run_grunt:handlebars_build" (run_grunt) task
--> starting  "src/handlebars.js/Gruntfile.js"
--> reporting "src/handlebars.js/Gruntfile.js"
  |  >> Local Npm module "grunt-contrib-clean" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-concat" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-connect" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-copy" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-requirejs" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-jshint" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-uglify" not found. Is it installed?
  |  >> Local Npm module "grunt-contrib-watch" not found. Is it installed?
  |  >> Local Npm module "grunt-saucelabs" not found. Is it installed?
  |  >> Local Npm module "es6-module-packager" not found. Is it installed?
  |  Loading "metrics.js" tasks...ERROR
  |  >> Error: Cannot find module 'underscore'
  |  Loading "publish.js" tasks...ERROR
  |  >> Error: Cannot find module 'underscore'
  |  Loading "version.js" tasks...ERROR
  |  >> Error: Cannot find module 'async'
  |  Warning: Task "clean" not found. Use --force to continue.
  |  
  |  Aborted due to warnings.
  |  
--> failed "src/handlebars.js/Gruntfile.js" (304ms)
--> failed handlebars_build @ "src/handlebars.js/Gruntfile.js"

Warning: 1 gruntfile failed and completed 0 (308ms)
 Use --force to continue.

解决方案可能是:

  1. 以某种方式在我们的顶级package.json 中使用npm link 来做 在npm install 之后使用脚本挂钩的一些聪明的东西 完成的。这似乎是不可能的,因为 handlebars.js/package.json 直到顺利才能使用 在npm install 完成之后。
  2. 在前面放置一个手动步骤 run_grunt:handlebars_build 递归到 src/handlebars.js 并运行 npm install 在该目录中。这似乎比我更手动 会期待。
  3. run_grunt:handlebars_build前面加一个步骤 将来自 src/handlebars.js/package.json 的依赖项安装到 项目的顶级 node_modules 目录,然后可能是 在src/handlebars.js 中运行 Gruntfile.js 时拾取(这个 可能需要没有 node_modules 目录 src/handlebars.js - 我对 npm 和 node_modules 的了解不是 很棒)。
  4. 放弃尝试构建 handlebars.js 作为我们的一部分 项目的构建,删除 src/handlebars.js 子模块 项目,只需在其位置添加构建文件作为普通文件。这 会很遗憾,因为您失去了跟踪 通过 git 子模块方法智能地获取项目的版本。

我们将不胜感激就最佳前进方向提出建议。

【问题讨论】:

  • 我想我想念你为什么要“建造”车把?您说“智能地跟踪项目的版本”,但我不确定您的意思。您如何跟踪版本?为什么?除此之外,您是仅在客户端上使用 Handlebars,还是在预编译步骤中使用 Handlebars?如果仅在客户端上,也许将该依赖项切换到 Bower 之类的东西会更好?
  • @jakerella 通过“跟踪版本”我只是意味着我们可以一次提供项目的特定版本,没有其他原因.. 基本上 package.json 的“依赖”行会给出什么我们,但在这种情况下通过 git 子模块修订进行管理。这是一个预编译步骤。我们的grunt build 需要运行 Dojo 构建过程,该过程收集构建目录中的文件(包括把手及其 AMD 部件)并将它们准备为“dist”网络应用程序。也许鲍尔对我们来说是正确的前进方向,我会尝试的。谢谢你的提示。
  • 嗯...好吧,所以如果它作为构建依赖项是必要的,那么我想我不明白为什么你不能使用 npm 和package.json 文件包含它。抱歉,我确定我遗漏了什么,只是不确定是什么。

标签: git gruntjs handlebars.js npm


【解决方案1】:

这可能对遇到这个问题的人有所帮助,就像我在研究类似问题时所做的那样:

我的解决方案使用grunt 插件grunt-run 在子模块目录中运行npm install(将其依赖项安装到它自己的node_modules 目录中:在您的情况下为src/handlebars.js/node_modules/)。

就我而言,之后我需要在子模块内使用grunt 任务编译 TypeScript 文件。我使用插件grunt-submodule 解决了这个问题。

>> Local Npm module "grunt-contrib-clean" not found. Is it installed?`

如果在错误的工作目录中执行grunt 似乎会出现错误 - 如果您之前已设法安装依赖项。

示例:

只有子模块使用grunt-contrib-clean 来清理其构建工件。您已经安装了子模块要求(在其目录中),但您在父目录中运行 grunt clean。节点模块在这个地方是未知的。

希望对你有帮助,

马库斯


这些任务当然是在 grunt 内运行的,并集成到我的构建/开发生命周期中。

参考资料:

【讨论】:

    【解决方案2】:

    为确保在安装主仓库的依赖项时安装子模块的依赖项,您需要修改主 package.json。

    假设您的子模块名为“common”并且位于src/common 下,并且它的package.json 在src/common 中,那么,

    您应该运行npm install --save file:src/common,它会将依赖项添加到您的package.json(或者您可以自己添加,只需将dependencies 的key:value 附加到您的"common": "file:src/common", 键)

    之后运行npm install,会在主模块和子模块中安装所有依赖。

    这些步骤也将有助于解决持续部署环境中的问题。

    【讨论】:

    • 这个答案比较有用,应该是公认的答案
    猜你喜欢
    • 2013-08-26
    • 2019-12-03
    • 2017-08-13
    • 2016-03-14
    • 2017-04-14
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多