【问题标题】:Use Global Variable to Set Build Output Path in Grunt在 Grunt 中使用全局变量设置构建输出路径
【发布时间】:2017-06-01 12:21:05
【问题描述】:

我有几个繁重的任务,我试图在这些任务之间共享全局变量,但我遇到了问题。

我编写了一些自定义任务,根据构建类型设置正确的输出路径。这似乎设置正确。

// Set Mode (local or build)
grunt.registerTask("setBuildType", "Set the build type. Either build or local", function (val) {
  // grunt.log.writeln(val + " :setBuildType val");
  global.buildType = val;
});

// SetOutput location
grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
  if (global.buildType === "tfs") {
    global.outputPath = MACHINE_PATH;
  }
  if (global.buildType === "local") {
    global.outputPath = LOCAL_PATH;
  }
  if (global.buildType === "release") {
    global.outputPath = RELEASE_PATH;
  }
  if (grunt.option("target")) {
    global.outputPath = grunt.option("target");
  }
  grunt.log.writeln("Output folder: " + global.outputPath);
});

grunt.registerTask("globalReadout", function () {
  grunt.log.writeln(global.outputPath);
});

因此,我尝试在后续任务中引用 global.outputPath,并遇到错误。

如果我从命令行调用grunt test,它输出正确的路径没问题。

但是,如果我有这样的任务: 干净的: { 发布: { 源:global.outputPath } }

它会引发以下错误: Warning: Cannot call method 'indexOf' of undefined Use --force to continue.

另外,我在 setOutput 任务中的常量设置在我的 Gruntfile.js 的顶部

有什么想法吗?我在这里做错了吗?

【问题讨论】:

  • 我认为这可能与在 grunt.initConfig({}) 之外设置的 global.outputPath 有关,而我正在尝试访问 grunt.initConfig({} )

标签: javascript gruntjs


【解决方案1】:

所以,我走在正确的道路上。问题是模块在这些全局变量设置之前导出,因此它们在 initConfig() 任务中定义的后续任务中都是未定义的。

我想出的解决方案,虽然可能更好,是覆盖 grunt.option 值。

我的任务有一个可选选项 --target

工作解决方案如下所示:

grunt.registerTask("setOutput", "Set the output folder for the build.", function () {
  if (global.buildType === "tfs") {
    global.outputPath = MACHINE_PATH;
  }
  if (global.buildType === "local") {
    global.outputPath = LOCAL_PATH;
  }
  if (global.buildType === "release") {
    global.outputPath = RELEASE_PATH;
  }
  if (grunt.option("target")) {
    global.outputPath = grunt.option("target");
  }

  grunt.option("target", global.outputPath);
  grunt.log.writeln("Output path: " + grunt.option("target"));
});

initConfig() 中定义的任务如下所示:

clean: {
  build: {
    src: ["<%= grunt.option(\"target\") %>"]
  }
}

如果您有更好的解决方案,请随时加入。否则,也许这可能对其他人有所帮助。

【讨论】:

  • 我喜欢全局设置构建目标目录的想法。另一种方法是为每个进程定义单独的规则,因为目标不同。 (例如:sass:devcoffee:devsass:distcoffee:dist)。这是一种痛苦,而且不是很干燥。感谢您为此付出的努力!
  • 我很困惑你将global.Outputpath 设置为等于grunt.option('target')(如果已定义),然后将grunt.option('target') 设置为global.Outputpath 的值。你的意图是什么?
  • 啊。现在来看,如果在运行时设置了 option("target"),更好的方法是在该函数的第一行返回一个。否则,我将 global.Outputpath 设置为 grunt.option("target") 以便如果它们在运行时传入目标,它会覆盖所有默认值。
  • 哦,我现在明白了!您希望人们能够在外部指定它。酷!
  • 我知道这是超级旧的,但我正在处理一个旧项目并尝试使用 grunt.config 无济于事。你的回答救了我……谢谢!
【解决方案2】:

我有一种方法可以让您使用--dev 之类的值指定输出路径。到目前为止,它工作得很好,我非常喜欢它。我想我会分享它,因为其他人也可能喜欢它。

    # Enum for target switching behavior
    TARGETS =
      dev: 'dev'
      dist: 'dist'

    # Configurable paths and globs
    buildConfig =
      dist: "dist"
      dev: '.devServer'
      timestamp: grunt.template.today('mm-dd_HHMM')

    grunt.initConfig
        cfg: buildConfig
        cssmin:
            crunch:
                options: report: 'min'
                files: "<%= grunt.option('target') %>/all-min.css": "/**/*.css"

    # Set the output path for built files.
    # Most tasks will key off this so it is a prerequisite
    setPath = ->
      if grunt.option 'dev'
        grunt.option 'target', buildConfig.dev
      else if grunt.option 'dist'
        grunt.option 'target', "#{buildConfig.dist}/#{buildConfig.timestamp}"
      else # Default path
        grunt.option 'target', buildConfig.dev
      grunt.log.writeln "Output path set to: `#{grunt.option 'target'}`"
      grunt.log.writeln "Possible targets:"
      grunt.log.writeln target for target of TARGETS

    setPath()

通过此设置,您可以运行以下命令:

grunt cssmin --dist #sent to dist target
grunt cssmin --dev #sent to dev target
grunt cssmin --dev #sent to default target (dev)

【讨论】:

  • 你的 Gruntfile 是 coffescript?请链接到设置/操作方法:) 顺便说一句很好的提示
【解决方案3】:

这是一个较老的问题,我只是想投入 5 美分。

如果您需要可从任何任务访问配置变量,只需在您的主(您将始终加载的)配置文件中定义它,如下所示:

module.exports = function(grunt)
{
    //
    // Common project configuration
    //
    var config = 
    {
        pkg: grunt.file.readJSON('package.json'),

        options: // for 'project'
        {
            dist:
            {
                outputPath: '<%= process.cwd() %>/lib',
            },
            dev:
            {
                outputPath: '<%= process.cwd() %>/build',
            },
        },
    }

    grunt.config.merge( config )
}

然后您可以像这样简单地访问值:

  • 在配置文件中

... my_thingie: [ ends_up_here: '<%= options.dev.outputPath %>/bundle', ], ...

  • 在任务中

// as raw value grunt.config.data.options.dist.outputPath // after (eventual) templates have been processed grunt.config('options.dist.outputPath')

我在这里使用密钥 options 只是为了符合约定,但你可以使用任何东西,只要你记住不要注册名为 'options' 的任务或任何你用于关键:)

【讨论】:

    猜你喜欢
    • 2018-01-04
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多