I've been working a lot with grunt lately and trying to get up to speed on all the awesome things I can do with it. What I am attempting to do is set a variable for a src, and one for a destination directory and run a copy task to move my initial build files (updated from another source) to production destination directory. I can get the copy to work with this simple example but it brings over the src directory /build/ to assets
assets/js/build/vendor-library
I'm trying to not copy over the directory name build. so the copy just has the following /assets/js/vendor-library/*
module.exports = (grunt) ->
grunt.initConfig
copy:
main:
expand: "true"
src: "build/vendor-library/*"
dest: "assets/js/"
grunt.loadNpmTasks "grunt-contrib-copy"
grunt.registerTask "default", "copy"
Add the flatten option.
module.exports = (grunt) ->
grunt.initConfig
copy:
main:
expand: "true"
flatten: "true"
src: "build/vendor-library/*"
dest: "assets/js/"
grunt.loadNpmTasks "grunt-contrib-copy"
grunt.registerTask "default", "copy"
Related
The source config example below processes files from src dir. There is src2 dir which also should be processed with the same tasks and putted to build2. What changes required in config.
module.exports = function (grunt) {
var saveLicense = require('uglify-save-license');
grunt.initConfig({
clean : {
build : {
src : ['build']
},
},
copy : {
files : {
cwd : 'src',
src : '**/*',
dest : 'build',
expand : true
}
},
...
Both grunt-contrib-copy and grunt-contrib-clean, like many other grunt plugins, allow multiple Targets to be specified in each Task.
For your scenario you can simply configure two Targets in the copy task (one Target to copy the src folder and another Target to copy the src2 folder).
You can also configure two Targets in the clean task (one Target to clean the build folder and another Target to clean the build2 folder).
Gruntfile.js
Your Gruntfile.js can be configured as ass follows:
module.exports = function(grunt) {
var saveLicense = require('uglify-save-license');
grunt.initConfig({
// The 'clean' task now includes two targets.
// named 'build1' and 'build2'
clean: {
build1: {
src: ['build']
},
build2: {
src: ['build2']
}
},
// The 'copy' task now includes two targets.
// named 'src1' and 'src2'
copy: {
src1: {
cwd: 'src',
src: '**/*',
dest: 'build',
expand: true
},
src2: {
cwd: 'src2',
src: '**/*',
dest: 'build2',
expand: true
}
}
// ...
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
// Registering the Targets in the Tasks....
grunt.registerTask('copySrc1', ['copy:src1']);
grunt.registerTask('cleanBuild1', ['clean:build1']);
grunt.registerTask('copySrc2', ['copy:src2']);
grunt.registerTask('cleanBuild2', ['clean:build2']);
grunt.registerTask('copyBoth', ['copy']);
grunt.registerTask('cleanBoth', ['clean']);
};
Running the Grunt Tasks
You'll notice that there are six calls to the .registerTask(...) function at the end of the snippet. Namely; copySrc1, cleanBuild1, copySrc2, cleanBuild2, copyBoth, and cleanBoth.
They allow you to run the following commands via your command line:
$ grunt copySrc1
(This will copy the src folder to the build folder)
$ grunt cleanBuild1
(This will clean the build folder)
$ grunt copySrc1
(This will copy the src2 folder to the build2 folder)
$ grunt cleanBuild2
(This will clean the build2 folder)
$ grunt copyBoth
(This will copy the src folder to the build folder and copy the src2 folder to the build2 folder)
$ grunt cleanBoth
(This will clean both the build and build2 folders)
Notes
You probably only need to keep the two .registerTask(...) functions as follows:
grunt.registerTask('copyBoth', ['copy']);
grunt.registerTask('cleanBoth', ['clean']);
However, I included the other four .registerTask(...) functions as they demonstrate how you can call a single Target inside a Task using the semicolon notation (:). For example:
grunt.registerTask('copySrc1', ['copy:src1']);
In the above snippet the ['copy:src1'] part simply runs only the Target named src1 inside the copy Task.
Whereas:
grunt.registerTask('copyBoth', ['copy']);
... does not reference any Targets in the copy task, (i.e. no semicolon notation is used), therefore all Targets will be run.
To further understand Tasks, Targets, you can read my answer to this post.
Hope that helps!
I created an javascript app using Oracle JET v2.0. Running
grunt build:release
creates release folder in the project root folder. How to change this to point to another path, for example outside project root?
If you're using the Yeoman generator, you can follow the Grunt flow in scripts/grunt/tasks/build.js. You'll see under if (target === "release")
that it runs a number of tasks in order.
Unfortunately the release folder name is hardcoded in many of those tasks' config files. So it might make more sense to add a task at the end of your build:release task to copy the built release into a new directory. You could add a target to the scripts/grunt/config/copy.js file named myFinalRelease:
module.exports = {
release:
{
src: [
"**",
"!bower_components/**",
"!grunt/**",
"!scripts/**",
"!js/**/*.js",
"js/libs/**",
"!js/libs/**/*debug*",
"!js/libs/**/*debug*/**",
"!node_modules/**",
"!release/**",
"!test/**",
"!.gitignore",
"!bower.json",
"!Gruntfile.js",
"!npm-shrinkwrap.json",
"!oraclejetconfig.json",
"!package.json"
],
dest: "release/",
expand: true
},
myFinalRelease:
{
cwd: 'release/',
src: ['**'],
dest: "myRelease",
expand: true
}
};
Then add that task:target as a copy step on the last line of the release section of scripts/grunt/tasks/build.js:
...
if (target === "release")
{
grunt.task.run(
[
"clean:release",
"injector:mainReleasePaths",
"uglify:release",
"copy:release",
"requirejs",
"clean:mainTemp",
"copy:myFinalRelease"
]);
}
...
To make this more robust, you should do some additional cleanup tasks if you're doing a lot of build:release'ing, because the myRelease folder won't get cleaned out unless you create tasks to do it. Or you might look into other Grunt plugins like grunt-contrib-rename.
If this is too much copying and too messy for your tastes, you could instead edit all of the hardcoded task configs to change the name of the release directory. You'll find the directory name shows up in these four files:
scripts/grunt/config/clean.js
...
release: ["release/*"],
...
scripts/grunt/config/uglify.js
...
dest:"release/js"
...
scripts/grunt/config/copy.js
...
dest: "release/",
...
scripts/grunt/config/require.js
...
baseUrl: "./release/js",
name: "main-temp",
mainConfigFile: "release/js/main-temp.js",
optimize: "none",
out: "release/js/main.js"...
...
I'm trying to use grunt-contrib-copy (version 0.4.1) to rewrite some strings inside a file during the build process. As a test I can copy the file, so it's not a permissions or location problem.
These are the options for the fileProcessor task (in Coffeescript syntax) to copy the file:
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
rename: (dest, src) ->
grunt.verbose.writeln src, " => ", dest + src.substring(0, src.lastIndexOf("/") + 1) + "foo.js"
dest + src.substring(0, src.lastIndexOf("/") + 1) + "foo.js"
]
I get the following output, everything worked as expected:
Running "copy:fileProcessor" (copy) task
Verifying property copy.fileProcessor exists in config...OK
test-25fd6a1c3a890933.js => target/js/foo.js
Files: target/js/test-25fd6a1c3a890933.js -> target/js/foo.js
Options: processContent=false, processContentExclude=[]
Options: processContent=false, processContentExclude=[]
Copying target/js/test-25fd6a1c3a890933.js -> target/js/foo.js
Reading target/js/test-25fd6a1c3a890933.js...OK
Writing target/js/foo.js...OK
Copied 1 files
So far so good. Clearly grunt-contrib-copy has no problem with the file itself. So I replace the the rename task with a process task, and use a simple regex to see if it works:
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
processContent: (content, src) ->
re = new RegExp("(angular)+")
content.replace(re, "foo")
]
Which produces the following output:
Running "copy:fileProcessor" (copy) task
Verifying property copy.fileProcessor exists in config...OK
Files: target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js -> target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js
Options: processContent=false, processContentExclude=[]
Options: processContent=false, processContentExclude=[]
Copying target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js -> target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js
Reading target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js...OK
Writing target/working/shared/scripts/bootstrap-25fd6a1c3a890933.js...OK
Copied 1 files
So grunt-contrib-copy finds the file I need to process, but the processing never happens. processContent remains set to the default false.
Looking in copy.js, when grunt.file.copy(src, dest, copyOptions) is called, copyOptions is an object with only two properties:
process, which is false, and
noProcess, which is an empty array.
So my process options are never passed along. Any ideas on why this could be?
your processContent is in the wrong place, it needs to be wrapped into options and moved one level higher. Also note that processContent is depreciated and replaced by process
fileProcessor:
files: [
expand: true
cwd: "target/js/"
dest: "target/js/"
src: ["**/test-*.js"]
]
options:
process: (content, src) ->
re = new RegExp("(angular)+")
content.replace(re, "foo")
I searched internet and it looks only me had this problem with grunt-contrib-copy.
project
gruntfile.js
->app
->img
->pic1.png
->pic2.png
Result I expected:
project
gruntfile.js
->app
->dist
->img
->pic1.png
->pic2.png
->img
->pic1.png
->pic2.png
In another word, just copy files in /project/app/img to /project/app/dist/img.
Here is my copy config, which is NOT working:
copy: {
main: {
src: ['*.*'],
expend: true,
cwd: 'app/img/',
dest: 'app/dist/img/'
}
},
Here is error message:
Warning: Unable to read "download.png" file (Error code: ENOENT). Use --force to continue.
(download.png is the name of picture file)
How should I config the copy option? Thank you!
It looks like you have a typo, it should be expand instead of expend. So the cwd property is being ignored. Try the following config instead:
copy: {
main: {
src: ['**/*'],
expand: true,
cwd: 'app/img/',
dest: 'app/dist/img/'
}
},
The glob pattern *.* is probably not necessary as * will already match all files (unless you're specifically trying to match only files with a . in them.) Try using src: '*' to match all files within the single folder or src: '**/*' to match all files and folders within the cwd.
My directory structure looks like this:
-src/
-----pages/
----------...
-----...
-build
My gruntfile contains the following task:
copy: {
all:{
dest:"<%= builddir %>/",
src: ["src/**/*.{yaml,yml,py,html,htm,json,css}"],
rename:function(d, s){return d.replace("src/","");}
}
},
builddir: "build/<%= pkg.name %>-<%= pkg.version %>-<%= date %>",
When I run the copy task, it copies all the selected files into the directory containing the package name, version and build date, as expected, but it copies the entire src directory. while I only want to copy the contents of the src directory, so I'm trying to remove src/' from dest using therename`property, which doesn't work for some reason.
I've only started using grunt today, so I might be makiing a rookie mistake here.
Hmm... I think all you need is the cwd (current working directory) option. Unless you in fact want to flatten the files into a single directory.
copy: {
all:{
expand: true,
dest:"<%= builddir %>/",
src: ["**/*.{yaml,yml,py,html,htm,json,css}"],
cwd: "src/"
}
}
You'll need to set the flatten option, which removes the directory structure.
copy: {
all:{
expand: true,
flatten: true,
dest:"<%= builddir %>/",
src: ["src/**/*.{yaml,yml,py,html,htm,json,css}"]
}
}