Grunt source file relative path - javascript

Why must the leading slash be removed in the source file paths in order for Grunt to properly locate the files? The gruntfile is in the main project older along with the "includes" folder that contains the JS files.
module.exports = function(grunt) {
var SiteMasterHeaderArray = [
"/includes/js/knockout/knockout-3.4.0.js",
"/includes/js/common/common.js"
];
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
dest: {
files: {
'dest/SiteMasterHeader.js': SiteMasterHeaderArray
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};
The destination file isn't written because (at least it appears this way to me) that Grunt is searching some other location for these files due to the "/" in the file path. Remove the slash and the function works perfectly.

A leading / means it's an absolute path and it's looking for it, starting from the root directory. Without that, it's searching for a relative path from where Gruntfile.js is.
If you'd like paths to be relative to a different folder than Gruntfile, please see grunt.file.setBase or the --base cli option. More information here.

Related

Will uglify include a file twice if a wildcard selector is used

Given my grunt uglify settings below; will the file manager.js be included twice in the resulting file foo.js? Or is uglify smart enough to figure out to not to include manager.js twice?
...
uglify: {
options: {
compress: true,
},
build: {
files: {
'dist/foo.js': [
'js/manager.js', // Other files depend on this - must be included first
'js/*.js', // Does this mean manager.js will be included twice?
],
}
}
},
Folder structure:
./js/manager.js
./js/bar.js
./js/baz.js
If uglify grabs the file twice, any recomendations how I can avoid this without having to manually add each javascript file?
Short Answer
Given my grunt uglify settings below; will the file manager.js be included twice in the resulting file foo.js?
No, the content of js/manager.js will be first in the resultant file, (i.e. dist/foo.js), and will NOT be included twice using your current uglify Task configuration.
Or is uglify smart enough to figure out to not to include manager.js twice?
Yes sort of, however it's actually grunt that works this out before passing an Array of unique file paths to uglify.
Long Answer
Excerpts from the grunt documentation for Globbing patterns read:
Also, in order to simplify otherwise complicated globbing patterns, Grunt allows arrays of file paths or globbing patterns to be specified. Patterns are processed in-order, with !-prefixed matches excluding matched files from the result set. The result set is uniqued.
The pertinent part here being: The result set is uniqued
The following code example is also given in the documentation:
// Here, bar.js is first, followed by the remaining files, in alpha order:
{src: ['foo/bar.js', 'foo/*.js'], dest: ...}
To prove the points mentioned in the documentation, let's assume we have the following five source .js files stored in the js/ directory. The pseudo content for each file is provided below the filename:
manager.js
console.log('manager.js')
a.js
console.log('a.js')
bar.js
console.log('bar.js')
baz.js
console.log('baz.js')
quux.js
console.log('quux.js')
If we run grunt using the files listed above and your current uglify Task configuration the resultant output is:
foo.js
console.log("manager.js"),console.log("a.js"),console.log("bar.js"),console.log("baz.js"),console.log("quux.js");
As you can see:
console.log("manager.js") appears first and only once (i.e. the result set has been uniqued).
The remaining files (i.e. those found via the glob pattern 'js/*.js') have been added in alpha order.

Grunt.js Unable to read file (Error code: EISDIR)

My folder structure is as follows
static/
js/
default/
main.js
lib/
someplugin.js
vendor/
jquery.js
tinyMce.js
Inside main.js I have the following code
#import '../lib/vendor/jquery.js';
#import '../lib/vendor/tinyMce.js';
#import '../lib/someplugin.js';
// ... more code ...
Every time I run grunt I'm getting the follwing error:
Warning: Unable to read "/PATH_TO_MY_APP/static/js/lib/vendor" file (Error code: EISDIR).
If I remove the tinyMce.js import line, grunt runs fine. So the problem must be with tinyMce, right? Wrong, if I cut all the content of tinyMce.js and paste it inside jquery.js (after jquery.js own content), grunt will run ok.
Here is my Gruntfile.js:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
import: {
options: {},
default: {
expand: true,
cwd: 'static/js/default/',
src: '**/*.js',
dest: 'static/js/stage/default/',
ext: '.js',
}
}
});
grunt.loadNpmTasks('grunt-import');
grunt.registerTask('default', ['import']);
};
I've read the docs of the plugins I use, but I found no option that may help. :(
instead import all your files in the main.js
why you don't let grunt do this?
you can use concat and uglify for this:
see: Grunt concat all package.json dependencies
have you tried just use that cwd:
'static/**/*.js',
also can you share your gruntfile.js? so I can have a better look.
I hope that helped you.

Grunt target subdirectories only

Is it possible with Grunt to target only subdirectories? I have a javascript folder in my project and it contains a few .js files and within this folder I also have a few subdirectories.
MainDirectory
/javascript
global.js
modal.js
/subdirectory1
somescripts.js
/subdirectory2
otherscrips.js
So in my grunt config I am using concat to grab only the files in the javascript folder and ignore the subdirectories. So what I need is to copy the files in the subdirectory and ignore the files outside the subdirectory, in this case global.js and modal.js. Here is my copy code (Gruntfile.js):
copy: {
subdirs: {
expand: true,
dot: true,
cwd: 'javascript',
dest: 'app/assets/javascript',
src: '**/*.js'// I know this grabs files and subdirectories
}
}
I'm sure there is a way to do this but after Googling and reading Grunt docs I still cant figure out a proper solution. Any help would be appreciated. Thanks.
The basic approach would be to specify all files in the current and any subdirectories, then explicitly ignore all files in the current directory.
reference grunt globbing patterns
Change your src property to:
src: ['**/*.js', '!*.js'],

Gruntfile issue with grunt-contrib-requirejs

I'm configuring my Gruntfile and I'm stuck on something I feel should be possible but I'm not able to find the right configuration for it. I'm trying to copy my bower components to my dist on build with the grunt-contrib-requirejs module. The part I'm stuck on is keeping the folder structure in tact when copying to dist.
My app's basic structure, and dist/ should build the same way
Gruntfile.js
app/
- assets/
- bower_components/
- js/
- img/
- etc/
- index.html
Currently, I define each file in the copy module and it copy's them all over
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: 'app',
dest: 'dist',
src: [
'*.{ico,png}',
'.htaccess',
'partials/**/*',
// Bower Components
'assets/bower_components/requirejs/require.js',
'assets/bower_components/fastclick/lib/fastclick.js',
'assets/bower_components/jquery/dist/jquery.min.js',
'assets/bower_components/modernizr/modernizr.js'
]
}]
}
},
But I want to eliminate this and use the paths I've already defined in main.js to copy these files over. Less hardcoded stuff, more automation.
My require task
requirejs: {
dist: {
options: {
mainConfigFile: app + '/assets/js/main.js',
dir: dist + '/assets/js',
optimize: 'uglify',
paths: {
modernizr: 'empty:',
jquery: 'empty:',
fastclick: 'empty:'
}
}
}
},
This current configuration combined with copy moves them all over properly. If I could eliminate the paths property all together and use directory properties only that would be great. If I have to copy my paths from my main.js into here thats ok... if it's the only way to do it.
Let me know if you need any more info!
The JS files in your bower directory should be included in the optimized output of requirejs, as long as they are configured and referenced in your require js app. If they're not referenced as dependencies, I don't think they get included.
The ico, png, htaccess and other files may need to be copied over manually.
Depending on your partials, the text plugin and hbs plugin could compile those into the optimized file I think.
I think defining empty: in paths are for using network resources (e.g. when using CDNs instead of using local bower libraries), so the paths config is probably unnecessary

Grunt + require.js config for a simple website

I have the following simple structure for my website:
src
js
core.js
main.js
lib
jquery-1.8.2.js
require-2.1.1.js
require-text.js
templates
1.html
2.html
index.html
build
I want all js+lib files to be compiled into one build/js/main.js file and other files just to be copied to build folder. How to write grunt.js config for this task? It seems I should use grunt-contrib-require..
The second question is how to compile 1.html and 2.html (I use require text! plugin) into one line for each and include theese lines to build/js/main.js? This case there should be only two files into build folder - index.html and main.js.
Take a look at grunt-contrib-requirejs and see if it is helpful to you.
The Grunt Website offers a very good tutorial to get you started, this is what you will need:
grunt-contrib-concat - To put files together in one
grunt-contrib-copy - To copy files to your "build" folder
grunt-usemin - To use the compiled js file in your html
I am not sure how to put those html files together though, feels weird to do that but maybe you can find a plugin for it.
Your Gruntfile.js should reside at the root of the directory i.e ls should show src/ build/ Gruntfile.js
Contents of `Gruntfile.js specific for your requirements:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
js: {
src: [
'src/js/*', 'src/lib/*'
],
dest: 'build/js/combined.js'
}
},
uglify: {
js: {
files: {
'build/js/main.js': ['build/js/combined.js']
}
}
},
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['concat:js', 'uglify:js']);
};
I don't think require-js to be used here. Require-js is helpful when you need to load your js scripts in a specific order. If that being the case add the below code in your Gruntfile.js just below pkg: grunt.file.readJSON('package.json'), line
requirejs: {
compile: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
name: "path/to/almond", // assumes a production build using almond
out: "path/to/optimized.js"
}
}
}
You might consider adding grunt-require to the list that luschn put together. It uses r.js, has lots of options, and is pretty darn nice.

Categories