How to read an external file list with grunt - javascript

I'm trying to concatenate and then babelify and uglify files with Grunt.
I'd like to read an external file list, from a file where the files are written one for each line, newline separated.
I'm trying to use the following GruntFile.js, but Grunt says (after I added the src=['<%= jsFiles.toString().split("\n") %>'] line):
Running "browserify:dist1" (browserify) task
Warning: An error occurred while processing a template (Invalid or unexpected token). Use --force to continue.
Where is the error?
This is the GruntFile.js
module.exports = function(grunt) {
grunt.initConfig({
jsFiles: grunt.file.read('scripts/s.list'),
env: {
prod: {
NODE_ENV: 'production'
}
},
browserify: {
dist1: {
options: {
transform: [
['babelify', {presets: ['es2015']}]
]
},
src: ['<%= jsFiles.toString().split("\n") %>'],
dest: '/WebContent/js/libs/s.bundle.js'
},
},
uglify: {
my_target1: {
files: {
'/WebContent/js/libs/s.bundleuglified.js': ['/WebContent/js/libs/s.bundle.js']
}
},
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-env');
grunt.registerTask('default', ['release']);
grunt.registerTask('release', ['env', 'browserify', 'uglify']);
};
Edit: I added a backslash to \n and the error has gone, but the babelify task gives me an empty file...
Edit2: I was able to read the file list using the following two lines at the beginning of the GruntFile.js
const jsFiles = grunt.file.read('scripts/s.list');
const jsFilesArray = jsFiles.toString().split("\n");
and then
src: jsFilesArray.slice(0, jsFilesArray.length-1),
because the last element was '' and it gave the error Warning: must provide pattern” as Beniamin H suggested.
Edit3: I found that the babelify task was reading the files in alphabetical order, so I had to first concat them, as explained here, and then babelify and uglify

You don't need to use any '<%= %>'. The file is read synchronously into jsFiles property and it can be used immediately. You may want to specify encoding for grunt.file.read to get a string: https://gruntjs.com/api/grunt.file#grunt.file.read

Related

Grunt watch pattern.indexOf is not a function

I'm trying to use Grunt's grunt-contrib-watch plugin to watch some files and then run the tasks, just what it was made for, this is my Gruntfile.js
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
dist: {
files: {
'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss',
/*'bower_components/foundation-sites/dist/foundation.min.css': 'bower_components/foundation-sites/scss/foundation.scss'*/
}
}
},
uglify: {
dist: {
files: {
'static/javascript/main.min.js': 'static/javascript/main.js'
}
}
},
watch: {
files: [
'<%= sass.dist.files %>',
'<%= uglify.dist.files %>'
],
tasks: [
'sass',
'uglify'
]
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['watch']);
};
When I run it, it runs over and over and over again, and when I stop it, I see I have this message:
Running "watch" task
Waiting...
Warning: pattern.indexOf is not a function
I really don't know what's the problem. Does anybody know what happens here?
UPDATE:
Apparently, the problem is because of the way I call the files, because I changed it to: 'static/stylesheets/sass/*.scss' and it worked well, but I would like to know why the other way doesn't work, because I think is a more useful way to do it.
grunt-contrib-watch expects either a single pattern string or an array of pattern strings as the value of its files config. However, the templates you are using in your config evaluate to objects. Your watch.files value evaluates to the following:
files: [
{ 'static/stylesheets/main.min.css': 'static/stylesheets/sass/main.scss' },
{ 'static/javascript/main.min.js': 'static/javascript/main.js' }
]
When the pattern matching tries to run it fails because there is no indexOf method on an Object. Due to the fact that grunt-contrib-watch runs forever, there is an infinite loop of the trying and failing to build the list of watched files.
You would normally configure your watch files with something like the following:
files: [
'static/**/*.scss',
'static/**/*.js'
]
But the above will cause issues in your case because your minified JS file is in the same folder as your source JS file. You could probably get around this by adding '!static/**/*.min.js' to your files array, but a better solution would be to put all of your compiled files into a separate folder.
Extract the values from the object:
watch: {
files: [
'<%= sass.dist.files.values() %>',
'<%= uglify.dist.files.values() %>'
],

Grunt jade error

Whenever I run grunt jade I get an error:
Warning: pattern.indexOf is not a function Use --force to continue.
Now here is my jade task:
jade: {
options: {
pretty: true
},
all: {
files: {
expand:true,
cwd: 'src/static/jade',
ext: "html",
src: ['src/static/jade/**/*.jade', '!src/static/jade/_includes'],
dest: 'build/'
}
}
}
So basically I am trying to take the jade files in src/static/jade (including subdirs, except _include) and put them in build, keeping the directory structure. I have tryed commenting the expand line, however it gives me:
Warning: Unable to read "src/static/jade" file (Error code: EISDIR). Use --force to continue.
Perhaps I am going about this the wrong way. How should I fix this?
Your initial issues is that files should be an array of objects, not just an object: files: [{...}].
But then you have other troubles with your file definition:
if you specify cwd, your src should not repeat it
your ext needs a starting .
your ! pattern needs to specify files instead of a dir
So you need:
files: [{
expand:true,
cwd: 'src/static/jade/',
ext: ".html",
src: ['**/*.jade', '!_includes/**/*.jade'],
dest: 'build/'
}]

Error when trying to use grunt-contrib-uglify: "src files were empty"

I have the following Gruntfile.js:
module.exports = function(grunt) {
var config = {
pkg: grunt.file.readJSON('package.json'),
/* Some other tasks... */
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
def: {
files: {
'out/src.js': 'out/src.min.js'
}
}
}
};
grunt.initConfig(config);
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', [/* <other-tasks>, */ 'uglify:def']);
};
Folder structure is as follows:
project
|
+-out (folder)
+-Gruntfile.js
Important: I run grunt from the project folder.
When running grunt, there is a task before uglify:def which is responsible for generating src.js into project/out.
When I run grunt I can see src.js being generated into project/out, but when Grunt runs uglisy:def I get the following error:
Running "uglify:def" (uglify) task.
Destination out/src.js not written because src files were empty.
No files created.
What am i doing wrong?
Log
When running with --verbose I get:
Running "uglify:def" (uglify) task
Verifying property uglify.def exists in config...OK
Files: [no src] -> out/src.js
Options: banner="/*! My Pack 2015-07-19 */\r\n", footer="", compress={"warnings":false}, mangle={}, beautify=false, report="
min", expression=false, maxLineLen=32000, ASCIIOnly=false, screwIE8=false, quoteStyle=0
>> Destination out/src.js not written because src files were empty.
>> No files created.
I've a configuration like the following, and it works fine for me.
// uglify javascript
uglify: {
dev: {
options: {
mangle: true
},
files: {
'js/dest.min.js': 'js/source.js'
}
}
},
Probably you confused the destination with the source. Try to switch them.
It were happening due to, you are not registering above given tasks.
OK, lets start with concatenation in grunt:
concat: {
css: {
src: ['./assets/css/*.css', './assets/css/**/*.css'],
dest: './dist/css/style.css'
},
js: {
src: ['./assets/js/*.js', './assets/js/**/*.js'],
dest: './dist/js/script.js'
}
},
so, this concat is supposed to collect all css files from above given url / directories and concatenate to given destination in one place and so with js.
this will be simple concatenated style.css and script.js at dest destination directory.
but it won't work, till you not register this concat task inside below line:
grunt.registerTask('default', ['concat', 'cssmin', 'uglify']);
So, till concat will not concatenate those files in dest directory, how the uglify will collect and work!
Conclusion: task won't get execute till you not mention them inside grunt.registerTask function.
My problem was that the path to my source file was incorrect. So it wasn't so much that the file is "empty" but that it can't be found.

Grunt - Concat multiple JS files and watch for changes

Still a bit of a newbie with Grunt, so please bear that in mind with your answers. I am trying to setup a task in Grunt that will concat any JS files within a directory called "custom", into a single file called custom-concat.js, however after running grunt watch (which runs fine without error), nothing is happening when I try and make changes to any of the files within my "custom" directory (i.e. console just sits at "waiting...." even after I make changes to any JS files within "custom" directory). Clearly there is something wrong with my concat task, but I can't seem to see what the problem is. Can anyone see where the problem lies? Full gruntfile below:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
//pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';',
},
dist: {
src: ['scripts/custom/**/*.js'],
dest: 'scripts/custom-concat.js',
},
},
uglify: {
build: {
src: 'scripts/custom-concat.js',
dest: 'scripts/custom.min.js'
}
},
less: {
options: {
paths: ["css"]
},
files: {
"styles.css": "less/styles.less"
}
},
watch: {
scripts: {
files: 'scripts/**/*.js',
task: ['concat', 'uglify:build']
},
styles: {
files: 'css/less/**.less',
task: 'less'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['concat', 'uglify']);
};
As far as I see, there are three small issues with your watch task:
The correct attribute for watch is taskS not task
If you want to run the tasks of watch, directly at the beginning, use options { atBegin: true }
Your watch task monitors the script folder. However, this folder will also contain your concated and uglified files. So this task will run into an infinite loop. You should probably only watch the scripts/custom folder
So your watch task should probably look something like this:
watch: {
scripts: {
files: 'scripts/custom/**/*.js',
tasks: ['concat', 'uglify:build'],
options: {
atBegin: true
}
},
styles: ...
}
Github grunt-contrib-watch

Grunt not executing grunt-contrib-sass task

I have added the Sass task to my grunt process using the grunt-contrib-sass plugin. Here is my gruntfile:
module.exports = function ( grunt ) {
grunt.loadNpmTasks('grunt-contrib-sass');
/**
* Load in our build configuration file.
*/
var userConfig = require( './build.config.js' );
/**
* This is the configuration object Grunt uses to give each plugin its
* instructions.
*/
var taskConfig = {
/**
* We read in our `package.json` file so we can access the package name and
* version. It's already there, so we don't repeat ourselves here.
*/
pkg: grunt.file.readJSON("package.json"),
sass: {
dev: {
files: [{
expand: true,
cwd: 'css',
src: ['**/*.scss'],
dest: 'css',
ext: '.css'
}]
},
prod: {
files: [{
expand: false,
cwd: 'css',
src: ['**/*.scss'],
dest: 'css',
ext: '.css'
}]
}
},
};
grunt.initConfig( grunt.util._.extend( taskConfig, userConfig ) );
grunt.registerTask('default', [ 'sass:prod' ]);
grunt.registerTask('dev-build', [ 'sass']);
grunt.registerTask('sass', [ 'sass:dev' ]);
grunt.event.on('watch', function(action, filepath, target) {
grunt.log.writeln(target + ': ' + filepath + ' has ' + action);
});
};
I have Ruby 1.9.3 and the Sass Gem 3.3.2 installed and working from the command line and IntelliJ 13. But when I try to run grunt sass or apply a grunt watch to my scss files, I get the following trace output:
<c:\users\[proj_dir_path]>grunt sass --verbose
Initializing
Command-line options: --verbose
Reading "gruntfile.js" Gruntfile...OK
Registering Gruntfile tasks.
Registering "grunt-contrib-sass" local Npm module tasks.
Reading C:\Users\[proj_path]\node_modules\grunt-contrib-sass\package.json...OK
Parsing C:\Users\[proj_path]\node_modules\grunt-contrib-sass\package.json...OK
Loading "sass.js" tasks...OK
+ sass
Reading package.json...OK
Parsing package.json...OK
Initializing config...OK
Loading "gruntfile.js" tasks...OK
+ sass
Running tasks: sass
Running "sass" task
[About 500 more repeats of this]
Running "sass" task
Warning: Maximum call stack size exceeded Use --force to continue.
Aborted due to warnings.
To run the SCSS Gem, I have to execute the scss.bat command with the arguments. My best guess is that the Grunt Sass plugin is trying to execute the Ruby EXE with arguments while on my system I have to run it with the the bat. This is just my guess combing through the sass.js Task code. Has anyone else had a similar issues and is there any workaround or solve for this?
I think it is a recursion problem, the registered task is running itself in a loop.
mine works without
grunt.registerTask('sass', [ 'sass:dev' ]);
as it appears anything set in the initConfig is automatically a task. If removing that line doesn't work try renaming it
grunt.registerTask('my-sass', [ 'sass:dev' ]);
and running
grunt my-sass
Try changing -
grunt.registerTask('sass', [ 'sass' ]);
to
grunt.registerTask('sass', [ 'sass:dev' ]);
or
grunt.registerTask('sass', [ 'sass:prod' ]);

Categories