Использование глобальной переменной для установки пути вывода сборки в Grunt

У меня есть пара ворчливых задач, и я пытаюсь разделить глобальные переменные для этих задач, и у меня возникают проблемы.

Я написал несколько пользовательских задач, которые устанавливают правильный путь вывода в зависимости от типа сборки. Кажется, это все настраивает правильно.

// 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 из командной строки, он без проблем выводит правильный путь.

Однако, если у меня есть такая задача: clean: {release: {src: global.outputPath}}

Выдает следующую ошибку: Warning: Cannot call method 'indexOf' of undefined Use --force to continue.

Кроме того, мои константы в задаче setOutput установлены в верхней части моего Gruntfile.js

Есть предположения? Я что-то здесь делаю не так?


person ThePuzzleMaster    schedule 26.03.2013    source источник
comment
Я думаю, это может быть связано с тем, что global.outputPath установлен вне grunt.initConfig ({}), в то время как я пытаюсь получить доступ к переменной внутри grunt.initConfig ({})   -  person ThePuzzleMaster    schedule 27.03.2013


Ответы (3)


Итак, я был на правильном пути. Проблема в том, что модуль экспортирует до того, как эти глобальные переменные будут установлены, поэтому все они не определены в последующих задачах, определенных в задаче 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\") %>"]
  }
}

Не стесняйтесь вмешиваться, если у вас есть лучшее решение. В противном случае, возможно, это может помочь кому-то другому.

person ThePuzzleMaster    schedule 27.03.2013
comment
Мне нравится идея глобальной установки целевого каталога сборки. Альтернативой является определение отдельных правил для каждого процесса только потому, что место назначения отличается. (например: sass:dev, coffee:dev, sass:dist, coffee:dist). Это больно и не очень СУХОЕ. Спасибо, что поработали над этим! - person SimplGy; 23.08.2013
comment
Меня смущает бит, в котором вы устанавливаете global.Outputpath равным grunt.option('target'), если он определен, а затем устанавливаете grunt.option('target') на значение global.Outputpath. Какие у вас там намерения? - person SimplGy; 23.08.2013
comment
Аааа. Глядя на это сейчас, лучше всего было бы поместить возврат в первую строку этой функции, если бы параметр (цель) был установлен во время выполнения. В противном случае я устанавливаю global.Outputpath на grunt.option (target), чтобы, если они передают цель во время выполнения, она отменяет все значения по умолчанию. - person ThePuzzleMaster; 24.08.2013
comment
О, теперь я понимаю! Вы хотите, чтобы люди могли указывать это извне. Прохладный! - person SimplGy; 24.08.2013
comment
Я знаю, что это очень старый проект, но я работал над старым проектом и безуспешно пытался использовать grunt.config. Ваш ответ спас меня ... спасибо! - person gonzofish; 26.07.2016

У меня есть способ сделать это, позволяющий указать путь вывода, используя такие значения, как --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)
person SimplGy    schedule 23.08.2013
comment
Ваш Gruntfile - это coffescript? Ссылка на настройку / как пожалуйста :) Хороший совет кстати - person oligofren; 26.06.2014

Это старый вопрос, я просто подумал бросить свои 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' или что-то еще, что вы использовали для ключа :)

person nidalpres    schedule 01.06.2017