Edit working version and explanation
I want to concat files from different server into my destination folder using grunt, and grunt-concat and with something like that:
concat: {
options: {
separator: ';'
},
dist: {
src: ['dev.staticcontent.com/media/clientcontent/library/*.js', 'js/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
each time I tried, I received no error from grunt, but my dist/marketing-home.js file is empty... Like it didn't find anything.
Console:
C:\Project\My>grunt
Running "jshint:files" (jshint) task
>> 1 file lint free.
Running "concat:dist" (concat) task
File dist/marketing-home.js created.
Running "uglify:dist" (uglify) task
Done, without errors.
New Version
After the help of Kris, I was able to do it without passing through the web using grunt-exec and doing using COPY or XCOPY shell command.
ex.
exec: {
copy : {
cmd: function () {
var path = "\\\\dev-server123\\WebSites\\Static_Contents\\Media\\clientcontent";
return "copy dist\\*.min.js " + path + " /y";
}
}
}
Doesn't look like concat task handles absolute paths or files from remote locations. However I was able to get it to work using curl task combined with the concat task.
EXAMPLE:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
curl: {
'download/jquery.js': 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
},
concat: {
js: {
src: ['download/jquery.js'],
dest: 'output/test.js'
},
}
});
grunt.loadNpmTasks('grunt-curl');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['curl', 'concat']);
};
DEMO DIRECTORY STRUCTURE:
I used this Node Module Package for CURL. https://github.com/twolfson/grunt-curl, there may be better ones out there. But this one seemed to work fine.
Related
I am new to grunt and task runners in JS, so this might seem a simple question but I have been unable to find exact working answer.
I have :
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: '\n\n'
},
dist: {
// the files to concatenate
src: ['scripts/app.js', 'scripts/constant.js'
],
// the location of the resulting JS file
dest: 'scripts/custom.js'
}
},
This task collects all my custom file together. What I want is to do similar thing for all my vendors file. Finally I should end up with two js only custom.js having my concatenated-minified code and vendor.js having concatenated-minfied libraries.
How do I write grunt configuration for this. Do I need to make two different tasks. If I write the above code twice with different input files, it seems to run the last code.
grunt-contrib-concat can be configured to utilize multiple-targets.
For further documentation on this subject refer to multi-tasks and Task Configuration and Targets in the grunt documentation.
Gruntfile.js
For your scenario you need to configure your concat task similar to this (Note: the new custom and vendor targets):
module.exports = function(grunt) {
grunt.initConfig({
concat: {
options: {
separator: '\n\n'
},
custom: {
src: ['scripts/app.js', 'scripts/constant.js'],
dest: 'scripts/output/custom.js'
},
vendor: {
// Modify the src and dest paths as required...
src: ['scripts/vendor/foo.js', 'scripts/vendor/baz.js'],
dest: 'scripts/output/vendor.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('concatenate', [
'concat:custom', // <-- Targets in a task are called using a colon separator.
'concat:vendor'
]);
};
Running concat
Using the example gist provided above you can run the concat task via the CLI by typing the following command:
$ grunt concatenate
Configuring Options
If you require different configuration options for both the custom and vendor targets you will need to move the options object inside their respective targets. As explained here.
Note: Using the example gist provided the options specified will apply to both targets.
I am trying to use grunt replace to change the names of files and add a random number to the file to prevent caching of images, css and js files.
So I am running the following code
module.exports = function replace(grunt) {
var randomVersion = ((new Date()).valueOf().toString()) + (Math.floor((Math.random() * 1000000) + 1).toString());
var replace = {
options: {
variables: {
'randomVersion': randomVersion
},
overwrite: true
},
files: [{
src: './target/dist/index.html',
dest: './target/dist/index.' + randomVersion + '.html'
}]
};
console.log(randomVersion);
grunt.config.set('replace', replace);
};
but all I get back is a "Destination is not defined
Can anyone shed any light on this?
Thanks
I am not completely certain about what your code is trying to achieve, but I will proceed to answer according to my understanding.
First, are you trying to use the grunt-replace library? If so, I think this is incorrect. This library is for replacing values within the contents of source files, and not the file paths themselves.
It looks to me that what you want to do is to copy your source index.html file to a file path with a unique identifier in it. You may be trying to wrap this in a custom task, but doing so is not necessary.
The following is a sample Gruntfile.js of how I would achieve this task. Note that this solution requires the installation of the grunt-contrib-clean and grunt-contrib-copy libraries.
module.exports = function (grunt) {
grunt.initConfig({
clean: {
dist: ['./target/dist/index.*.html']
},
copy: {
dist: {
src: './target/src/index.html',
dest: './target/dist/index.<%= Date.now() %>.html'
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('default', ['clean', 'copy']);
};
There are a few things about this solution that are worth pointing out:
The index.html file is not in the /dist folder because it is not
intended for distribution, but is, rather, a source.
Before creating new versions of index.*.html, we will delete any
existing versions in the /dist folder so that we don't have an
accumulation of each version.
Instead of using a "random" number for our versions, we will use a
timestamp. This is helpful because each version will have a greater
number than the one before it.
I'm trying to use grunt-newer to watch files from a folder and if any is changed, trigger a custom task.
I have something like this in my Gruntfile.js:
grunt.initConfig({
watch: {
widgets: {
files: "/somepath/*.js",
tasks: ['newer:mycustomtask']
}
}
});
grunt.registerTask("mycustomtask", ["description of my task"], function() {
console.log("me has been triggered");
});
Whenever I run "grunt watch", I have this output:
Running "watch" task
Waiting...
File "/somepath/WidgetA.js" changed.
Running "newer:mycustomtask" (newer) task
Fatal error: The "newer" prefix is not supported for aliases
I googled but didn't found anything about this. Anyone knows how could I implement this? I need to now in my "customtask" which files have been changed
If you reference a task (inside watch or concurrent e.g.) which is either not installed or not configured you get this error output.
This happens often when you copy-paste a watch config from a different project.
I came across a similar requirement and the solution I ended up with is roughly as follows. Let's assume that the project structure is:
Gruntfile.js
package.json
src/
config.js
data.js
tasks/
customtask.js
Here, the src directory contains data which will be monitored by watch, while the definition of the custom task is stored in tasks/customtask.js. For the purpose of this example, this task will only print the file names of the changed files:
var fs = require('fs');
var path = require('path');
module.exports = function(grunt) {
grunt.registerMultiTask('customtask', function() {
var done = this.async();
if(!this.files){ done(); return; }
this.files[0].src.forEach(file_name => {
console.log(file_name);
});
done();
});
};
Now, Gruntfile.js looks like:
module.exports = function(grunt) {
const files = ['src/config.js', 'src/data.js'];
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
customtask: {
release: {
src: files
}
},
watch: {
data: {
files: files,
tasks: ['customtask:release']
},
options: {
spawn: false
}
}
});
grunt.loadTasks('tasks');
grunt.loadNpmTasks('grunt-contrib-watch');
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('customtask.release.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
grunt.registerTask('build', ['watch:data']);
};
here, it specifies that:
the files of interest are ['src/config.js', 'src/data.js']
that our customtask operates in principle on these files (in case it would be invoked directly)
that watch is supposed to observe these files and launch customtask:release whenever something changes
grunt.loadTasks('tasks') loads all "tasks definitions" from the directory tasks, i.e., here only the customtask
grunt.registerTask('build', ['watch:data']) defines a "shortcut" for watch:data
Finally, in order to invoke customtask only for the changed files, this example uses the strategy employed in the documentation in the section "Compiling files as needed". In loose terms, it assembles all changed files in an object the keys of which are then used to modify the src property of the customtask on-the-fly.
Running grunt build then initiates the "watch". If one runs in another terminal window for example touch src/*.js, the output is:
Running "watch:data" (watch) task
Waiting...
>> File "src/config.js" changed.
>> File "src/data.js" changed.
Running "customtask:release" (customtask) task
src/config.js
src/data.js
where the last two lines come from customtask...
You just need to have a config entry (even an empty one) for your task:
grunt.initConfig({
mycustomtask: {
},
watch: {
widgets: {
files: "/somepath/*.js",
tasks: ['newer:mycustomtask']
}
}
});
This is relevant to any Grunt task which has a source file and a destination (output file).
When I run grunt in my command line, I don't want Grunt to write anything to file, I just want to view (return) the output to my console, be it Bash, CMD or any CLI.
Lets take uglify for example.
module.exports = function(grunt) {
grunt.initConfig({
uglify: {
options: {
mangle: true,
sourceMap: true,
},
build: {
src: 'js/foo.js',
dest: 'js/foo.min.js' <-- Don't need this.
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};
Instead of Done, without errors, when successful, I want to view the uglifed code in the console.
For context, I need this for a command line application which won't need anything written to disk. I just need to use the output on the fly (I'm trying to avoid writing to file and re-reading from the CLI).
You could write directly to /dev/stdout ( not on windows tough ):
build: {
src: 'js/foo.js',
dest: '/dev/stdout'
}
I want to run a local sync daemon.
It should watch src directory and copy any changed file to dst directory. There are many subdirectories in src, so the relative paths should be preserved. All necessary subdirectories in dst are already created.
I want to filter for *.js files only.
I've found a grunt-sync tool. The documentation is so short that I even don't know if it fits me. Here's my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
sync: {
main: {
files: [{
cwd: src,
src: ['**/*.js'],
dest: dst
}]
}
}
});
grunt.loadNpmTasks('grunt-sync');
grunt.registerTask('default', 'sync');
};
When I run grunt, I see no watch task. Grunt freezes for several seconds, then copies all files and exits. And I want a watch-sync daemon.
I created a tool called duplicate which will do what you want (though a year later), it copies all matching files when start, and keep watching if there would be any changes.
It's not written as a Gulp or Grunt plugin because it doesn't need to be, but of course you may easily run it in a Gulp or Grunt task.
Check out https://github.com/vilic/duplicate
Probably a bit late but.. I had the same question. What I´ve done is to combine both tools.. grunt-sync and grunt-contrib-watch..
module.exports = function (grunt) {
grunt.initConfig({
sync: {
main: {
files: [{
cwd: src,
src: ['**/*.js'],
dest: dst
}]
}
},
watch: {
jsxfiles: {
files: ['**/*.js'],
tasks: ['sync:main'],
} //this means that when any of the pattern files changes, the sync task will be run...
}
});
grunt.loadNpmTasks('grunt-sync');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', 'watch'); //run the watch task isntead of just the sync once..
};
I hope this is helpful
KR Jon