Flattening of File Tree when using Grunt Copy Task - javascript

Not sure if I'm missing something but I have the following grunt setup for grunt-contrib-copy tasks.
copy: {
build: {
files: {
"server-dist/": "server/**/*.!(coffee)",
"client-dist/": "client/**/*.!(coffee)"
}
}
}
The client-dist copies as I expect recursively running through the file tree but the server-dist all sub-folders get flattened to the base folder. Any ideas why this is happening? Here is the i/o
server/
views/
errors/
404.jade
layouts/
base.jade
becomes
server/
errors/
layouts/
base.jade
the views folder gets completely blown out. One more thing...when I removed !(coffee) it works but I need to exclude coffee files since I have a grunt-coffee watch task running.

A followup to zacks comment:
copy: {
mytask: {
files: [
{expand:true, cwd:'dev-js/abc/', dest:'js/test/', src:['def.js']}
]
}
}
This copies the file ./dev-js/abc/def.js to ./js/test/def.js - at least on my 0.4.1 version. Zacks comment and the link included was very helpful, especially the fact, that basePath has been replaced.

Apparently the grunt-contrib-copy task has a sophisticated logic that's trying to automatically detect the base directory for copying source files (see related issue)
The solution is to explicitly specify the basePath option:
copy: {
build: {
files: {
"server-dist/": "server/**/*!(.coffee)"
},
options: {
basePath: 'server' // base directory in the source path
}
}
}
P.S. I'm not sure, however, why removing !(.coffee) changes the behaviour for you. I tried the same on my local machine and get the same results when specifying "server/**/*" instead of "server/**/*.!(coffee)" (i.e. the views folder is skipped)

Related

Gulp sass copies empty scss files to destination folder

I have a task:
gulp.task('compile_scss, function() {
return gulp.src('/admin_app/scss/*.scss')
.pipe(sass())
.pipe(dest('/admin_app/css/'))
});
When I am adding new empty ".scss" file to '/admin_app/scss/' and running task from above, empty ".scss" files is copied to destination folder. If file is not empty everything is ok: a valid css file( with ".css" extension) is compiled and no ".scss" files are copied. The problem is when I add new ".scss" file to "/admin_app/scss/" directory, a "watch" task is triggered, and because file is empty, it is copied to destination directory. As a result, a lot of unneeded garbage is dest folder. Why this happens and how can I get rid of it?
UPDATED
My "watch" and "default" tasks:
gulp.task('watch', ['compile_scss'], function() {
apps.forEach(function(appName) {
gulp.watch('/admin_app/scss/*.scss', ['compile_scss']);
});
});
gulp.task('default', ['watch']);
One way to solve this problem would be to simply filter the empty files.
Try something like this:
var filter = require('gulp-filter'),
gulp.task('compile_scss, function() {
return gulp.src('/admin_app/scss/*.scss')
.pipe(filter(function(a){ return a.stat && a.stat.size }))
.pipe(sass())
.pipe(dest('/admin_app/css/'))
});
There's also a plugin specifically for this purpose. You can use it like this:
var clip = require('gulp-clip-empty-files'),
gulp.task('compile_scss, function() {
return gulp.src('/admin_app/scss/*.scss')
.pipe(clip())
.pipe(sass())
.pipe(dest('/admin_app/css/'))
});
In addition: there seem to have been several reports of problems in gulp-sass and underlying libraries when compiling empty files. There is a Github issue for gulp-sass, reporting this should be solved in the 2.x versions of the plugin. If you're already running 2.x, the problem you are facing might be an issue introduced by solving the original problem.
If you add empty scss files in your sass folder, prefix them with underscore: _empty.scss.
See "Partials" here: http://sass-lang.com/guide#topic-4
You can create partial Sass files that contain little snippets of CSS
that you can include in other Sass files. This is a great way to
modularize your CSS and help keep things easier to maintain. A partial
is simply a Sass file named with a leading underscore. You might name
it something like _partial.scss. The underscore lets Sass know that
the file is only a partial file and that it should not be generated
into a CSS file. Sass partials are used with the #import directive.

Custom directory to include JS and CSS files

I have got a theme from themeforest which has a plugins/ directory with 20-30 directories inside that with js/ and css/ folders.
So I need to have a folder outside of the default sails js/ and styles/ called plugins/, which will then be included in the grunt build.
I tried to copy the usual jsFilesToInject and replicate it all with this:
var plugInJSFilesToInject = [
// All of the rest of your client-side js files
// will be injected here in no particular order.
'plugins/**/*.js'
];
Then specifing it in the sails-linker:devJs like so:
devJs: {
options: {
startTag: '<!--SCRIPTS-->',
endTag: '<!--SCRIPTS END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.ejs': require('../pipeline').jsFilesToInject,
'.tmp/public/**/*.html': require('../pipeline').plugInJSFilesToInject,
'views/**/*.html': require('../pipeline').plugInJSFilesToInject,
'views/**/*.ejs': require('../pipeline').plugInJSFilesToInject
}
},
And recieved this error when running sails lift:
------------------------------------------------------------------------
Aborted due to warnings.
Running "sails-linker:devJs" (sails-linker) task
Warning: Cannot read property 'indexOf' of undefined
This also needs to be done for a css/ directory, which is why I definitely need to have it outside of the js/ or styles directory.
I ended up just placing the plugins/ in the same jsFilesToInject array, because there is no reason why it can't go in there:
var plugInJSFilesToInject = [
// All of the rest of your client-side js files
// will be injected here in no particular order.
'js/**/*.js',
// Plugins go here
'plugins/**/*.js'
];

Grunt + Concat + Angularjs

Setup:
A Gruntfile with the following task:
concat: {
build: {
files: {
'build/app.js': [
'src/.js',
'src//.js',
'!src/vendors/'
],
}
}
A lot of angular modules, with its controllers, services, and so on, with a structure like this:
a/
a.js // Module declaration like: angular.module('a',[])
a-controller.ks // Which sets a controller in its root module definition like: angular.module('a').controller()...
Issue:
The task concatenates all the js files it finds in the build folder to a single app.js file, and it does this fine, but messes up with the order of files when concatenating.
For instance, it concatenates first the controller file instead of the main folder file containing the module declaration, triggering the following error:
Module xxxx not available!
I suppose the issue lies in the way concat builds up the files and that is done by the grunt core and specifically the minimatch library, and the possibility it treats dashes to be first than letters, but I don't know how configure to change that behavior, and even know if that is possible.
Question:
So, the question is: How can I make Grunt/Grunt-concat to process dashed f first than the others in the same folder so the ordering is maintained?
Thanks
Update 1:
After digging more, It seems that it has nothing to do with the ordering inside a folder, but Grunt/Core sending the root files to the end and putting them the leaf ones first.
Just specify the order you want to concat your files, placing them in order, what I mean is, first add your single files that should be concatenated at start, after your full folder that does not need to have an order, and finally your final files, something rougth like this:
grunt.initConfig({
concat: {
js: {
src: ['lib/before.js', 'lib/*', 'lib/after.js'],
dest: 'bundle.js',
}
}
});
You will have to specify to the grunt-concat task the order you want your files built. For my projects, I typically keep a folder structure where controllers go in a app/controllers folder, services in services, and etc, but names can vary. I also keep an app.js that declares my app module and specifies the config handler for it. I use a config like this for grunt-uglify but the same can be done for concat with little to no changes:
uglify: {
development: {
files: {
'public/scripts/app.js': [
'public/app/app.js',
'public/app/controllers/*.js',
'public/app/directives/*.js',
'public/app/services/*.js'
]
}
}
}
I just copy paste my answer, the detail you want on second picture, i hope help you.
you may consider this solution
Separate the module declaration to xxx.module.js
In grunt-contrib-concat modify the config like below :
place this outside grunt.initConfig
var clientApp = './app/';
grunt-contrib-concat config
dist: {// grab module first, state the second
src: [
clientApp+'**/*-controller.js',
clientApp+'**/*.module.js',
clientApp+'**/*.state.js',
clientApp+'**/*.js'
],
dest: 'dist/<%= pkg.name %>.js'
}
i use state to so i have to define state too before trying to navigate to any state. This is preview my code, the module declaration is declared fist before anything, then my state. even minified doesnt create any problem.
I hope this help you.
i follow this johnpapa's style guide, your problem might solve there if my solution not work

Grunt Browserify - set include, fallback path

Is there any way to create Grunt task for Browserify to use fallback path?
Eg.
require('./module.js)
Check if module.js is in current directory, if not there, check some other directory?
project1
|- dir1
|- mod1.js - has: require('./mod2.js')
|- bundle.js - has: require('./mod1.js') and require('./mod2.js')
project2
|- dir2
|- mod1.js
|- mod2.js
I already tried remapify, but it can only check one specific directory.
And I don't want to change require paths inside modules, everything should be done trough Grunt.
I want to override some app (dir2), so I want to get (copy to dir1) only modules which I need to change, and to leave all others in app directory.
Gruntfile is in project1. Modules are CommonJS. I'm using grunt-browserify.
I know this is a little old now but it would be good to have an answer.
So, I asked myself a very similar question a couple of days ago and ended up doing basically what you want to do.
Using browserifyOptions from grunt-browserify like:
// Using grunt-browserify
grunt.loadNpmTasks("grunt-browserify");
grunt.initConfig({
browserify : {
options : {
browserifyOptions : {
// keep in mind that paths are relative to Gruntfile.js
paths: ["./first/path", "./second/path", "./and/so/on"]
}
},
dist : {
files: { "./path/to/dist.js" : "./path/to/src.js" }
}
},
});
And you will now be able to do:
var myModule = require("myModule");
opts.paths is an array of directories that browserify searches when
looking for modules which are not referenced using relative path. Can
be absolute or relative to basedir. Equivalent of setting NODE_PATH
environmental variable when calling browserify command. - Browserify
Theoretically, it should follow the paths in order, the only problem I've had is that it looks through native node modules (util, fs, etc..) before even searching those paths.
What the quote is saying is that if you do:
var myModule = require("./myModule");
Browserify will look for the module following the relative path. When you remove the relative path:
var myModule = require("myModule");
it can search through the stablished paths in the options.
Edit
I tested this and it works as expected. I have a module called myModule.js that is in "./current/directory", and I also have a module called myModule.js that is in "./modules/directory". Also, in current directory, I have the "src.js" that requires the module: require("myModule");. It looks in order through the paths and the first found is the one injected into bundle.js in this case.
grunt.initConfig({
browserify : {
dist : {
options : {
browserifyOptions : {
// keep in mind that paths are relative to Gruntfile.js
paths: ["./current/directory", "./modules/directory"]
}
},
files: { "./current/directory/bundle.js" : "./current/directory/src.js" }
}
},
});

Gulp doesn't copy all files as expected

I tried to create a gulpfile.js for my personal website project. I've never done this before but with a little 'trial and error' it now works in an acceptable way.
The only thing that doesn't work even after 1000 modifications is simple copying files and folders.
var files = {
data_src : [
'./files.json',
'data/**/*.*'
],
distribution_dest : '_distribution'
};
gulp.task('copy-data', function() {
gulp.src(files.data_src, { base: './' })
.pipe(gulp.dest(files.distribution_dest))
.pipe(notify({message: 'Data copied for distribution!'}));
});
This should copy all sub-folders and files to the gulp.dest. But it copies only half of them, some folders will be ignored even if I change their names etc. (no special characters, same subfolder structure as the once that got copied correctly ...) - nothing worked. I just can't see any pattern in this.
There is no error message while running gulp. Nothing that would help me find the error.
Why are some folders or files excluded from copying?
I use base to keep the folder / sub-folder structure; tried with and without 'base' -> no effects on the copying process.
I also changed the position of the 'copy-data' task in the run-list. Actually it's the first task to run. There seems to be no change in behavior no matter if it's the first or the last one.
gulp.task('default', function() {
gulp.run('copy-data', 'custom-sass', 'framework-sass', 'custom-js', 'framework-js', 'replace-tags', 'browser-sync');
... some watches ...
});
The structure of the data folder looks like these:
./data
|-doc
|---content
|---template
|-img
|---chart
|---icon
|---logo
|---pattern
|---people
|---photo
|---symbol
|-----brandklassen
|-----brandschutzzeichen
|-----gebotszeichen
|-----gefahrensymbole
|-----rettungszeichen
|-----verbotszeichen
|-----verkehrsrechtzeichen
|-----warnzeichen
|---wallpaper
/data/doc and all subfolders are ok.
/data/img/chart to /data/img/people are also ok.
Within /data/img/photo only 14 out of 21 images are copied.
/data/img/symbol with sub-folders and /data/img/wallpaper were ignored completely.
SOLVED IT MYSELF! The problem was caused by async operating tasks. Adding a return forced gulp to complete the copying process before continuing!
gulp.task('copy-data', function() {
return gulp.src(files.data_src, { base: './' })
.pipe(gulp.dest(files.distribution_dest))
.pipe(notify({message: 'Data copied for distribution!'}))
});
Now all images will be copied!

Categories

Resources