Maintaining folder structure while minifying using grunt - gruntjs

I have built an application using javascript. I have multiple .js files that are managed across multiple folders and sub-folders. I minified and uglified them using grunt-contrib-uglify. It does it pretty well. But my problem is that it iteratively goes through every .js file and minifies them but rather than maintaining folder structure,all of the minified js files are placed in a single destination folder.
For example:-
I have a JS folder.It has 5 sub-folders-
a,b,c,d,e
Each one is having 60-70 .js files . Now when I minify them, these all are minified and placed in a single JS-Min folder. But the folder structure is all gone.
Please suggest a way using which I can maintain the folder and sub-folder structure. I searched for it at grunt's official site,but to no solution.
My Gruntfile.js is as follows-
module.exports = function (grunt) {
grunt.initConfig({
requirejs_obfuscate: {
options: {
mangle: true,
dir: 'jsm',
salt: 'salt',
root: 'gruntfiles',
length: 6,
quotes: 'double',
concurrency: 2,
keepLinefeeds: false,
keepIndentations: false,
encodeStrings: true,
encodeNumbers: true,
moveStrings: true,
replaceNames: true,
variableExclusions: [ '^_get_', '^_set_', '^_mtd_' ],
}
},
jsObfuscate: {
test: {
options: {
concurrency: 2,
keepLinefeeds: false,
keepIndentations: false,
encodeStrings: true,
encodeNumbers: true,
moveStrings: true,
replaceNames: true,
variableExclusions: [ '^_get_', '^_set_', '^_mtd_' ]
},
files: {
src:'jsm/*.js' , // source files mask
dest:'jso/',
strings: true,
expand: true,
flatten: true,
ext: '.js'
}
}
},
uglify: {
mangle:{all:true},
squeeze: {dead_code:true},
codegen: {quote_keys: true},
files: {
cwd: 'js/',
src: ['*.js', '**/*.js'],
dest:'jsm/',
strings: true,
expand: true,
flatten: true
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-minified');
grunt.loadNpmTasks('grunt-encoding');
grunt.loadNpmTasks('grunt-requirejs-obfuscate');
grunt.loadNpmTasks('js-obfuscator');
grunt.registerTask('default', ['uglify','requirejs_obfuscate']);
};

Related

SAPUI5: Minify and Uglify files with Grunt

I'm trying to get one of my SAPUI5 apps minified on the Fiori launchpad. But I'm facing some troubles. My minified files seem to be going in a 'tmp' folder and are not seen in the Fiori launchpad. I do get some dbg files, but next to the normal files which aren't minified. So the minified files are not used, but the normal files are. I do have a minified component preload. Anyone have any advise on what I'm doing wrong?
This is my gruntfile.js, I'm using at the moment:
module.exports = function (grunt) {
'use strict';
// Project configuration.
grunt.initConfig({
uglify: {
options: {
mangle: true,
compress: {
drop_console: true,
dead_code: false,
unused: false
}
},
files: {
expand: true,
cwd: "<%= ref.staging%>",
src: ["**/*.js", '!test/**', '!test_local.html'],
dest: "<%= ref.process%>"
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('#sap/grunt-sapui5-bestpractice-build');
grunt.registerTask('default', [
'lint',
'clean',
'build',
'uglify'
]);
};
The build task from grunt-sapui5-bestpractice-build usually generates a Component-preload.js file inside your Dist folder. Which is in fact a minified version of your application. If you deploy the application to the FLP with a Component-preload.js present it loads this instead of all the single files.

Grunt: SASS creates unwanted .map file

I've got grunt to successfully compile SASS to CSS. The problem I'm having is it's creating a file within the CSS directory called something like master.css.map.
I tried writing sourceMap: false, which I found as being the solution for a LESS setup within the options section, whereas it doesn't make a difference.
sass: {
build: {
options: {
compress: false,
sourceMap: false
},
files: [{
expand: true,
cwd: 'sass/',
src: ['*.scss'],
dest: 'css/',
ext: '.css'
}]
}
}
Do I need to declare something else or is there a dependency that can stop the .map file from being made?
You need to write like this:
options: {
compress: false,
sourcemap: 'none'
}
Here's a link for further clarification.
Hope this helps.

How to configure sourceMaps for LESS using Grunt?

I'm using grunt 0.4.2 and grunt-contrib-less 0.9.0. I want my LESS to be compiled into CSS with support for source maps.
My LESS files are in public/less, and the main one is called main.less.
The compiling of public/less/main.less into public/css/main.css works, but source maps don't work.
What is wrong with my Grunt config below?
{
less: {
dev: {
options: {
compress: true,
yuicompress: true,
optimization: 2,
sourceMap: true,
sourceMapFilename: "public/css/main.css.source-map.json", //Write the source map to a separate file with the given filename.
sourceMapBasepath: "public/less", //Sets the base path for the Less file paths in the source map.
sourceMapRootpath: "/"//Adds this path onto the Less file paths in the source map.
},
files: {
"public/css/main.css": "public/less/main.less"
}
}
},
watch: {
styles: {
files: ["public/less/*"],
tasks: ['less'],
options: {
livereload: true,
nospaces: true
}
}
}
}
I don't want to have my CSS created in my /public/less folder; I want to put it into /public/css. Otherwise, I could use this other config, which works:
{
less: {
dev: {
options: {
compress: true,
yuicompress: true,
optimization: 2,
sourceMap: true,
sourceMapFilename: "public/less/main.css.map", //I DO NOT WANT THE CSS MAP HERE
sourceMapBasepath: "public/less", //Sets the base path for the Less file paths in the source map.
},
files: {
"public/less/main.css": "public/less/main.less"//I DO NOT WANT THE CSS HERE
}
}
},
watch: {
styles: {
files: ["public/less/*"],
tasks: ['less'],
options: {
livereload: true,
nospaces: true
}
}
}
}
I found the LESS site documentation to be more clear regarding params used by grunt-contrib-less.
LESS: Command Line Usage
http://lesscss.org/usage/#command-line-usage-installing-lessc
NPM: grunt-contrib-less
https://www.npmjs.org/package/grunt-contrib-less
File structure:
laravel/gruntfile.js
laravel/public/less/main.less
laravel/public/css/main.css
laravel/public/css/main.css.map
File 'main.css.map' note:
If you wish, you can rename to: main.css.source-map.json
I guess you have some server rule setup that doesn't server *.map files properly from the 'css' folder
Compression notes:
cleancss: true = will remove sourceMappingURL comment from main.css
yuicompress: true = will NOT remove sourceMappingURL comment from main.css
Gruntfile.js
less: {
dev: {
options: {
compress: true,
yuicompress: true,
optimization: 2,
sourceMap: true,
sourceMapFilename: 'public/css/main.css.map', // where file is generated and located
sourceMapURL: '/css/main.css.map', // the complete url and filename put in the compiled css file
sourceMapBasepath: 'public', // Sets sourcemap base path, defaults to current working directory.
sourceMapRootpath: '/', // adds this path onto the sourcemap filename and less file paths
},
files: {
'public/css/main.css': 'public/less/main.less',
}
}
},
watch: {
styles: {
files: ["public/less/*"],
tasks: ['less'],
options: {
livereload: true,
nospaces: true
}
}
},
laravel/public/css/main.css
.class{ compiled css here } /*# sourceMappingURL=/css/main.css.map */
laravel/public/css/main.css.map
{"version":3,"sources":["/less/main.less"], etc...
If you're still having trouble with it try setting the SourceMapURL to the full path, for example:
http://www.yourdomain.com/assets/css/styles.css.map
Obviously this is a bit of a pain as it's not relative, so when you move your site it will need to be changed. I had the same issue as you and this got it working for me.
Another point I discovered is that you cannot load the SourceMaps from the file system. It has to be from a web server. To get around the file system issue I believe you can inline the SourceMap.
This thread on GitHub has a lot of information.
https://github.com/less/less.js/issues/1050#issuecomment-25621390

Can I configure a grint-contrib-less task to compile into a parallel structure?

Currently we are using grunt-contrib-less to handle our LESS file compiling as a Grunt task. The less files are stored in a structure similar to this:
assets/
styles/
base.less
client/
client.less
device/
tablet.less
phone.less
We have the following for our Grunt config:
less: {
options: {
paths: 'assets/',
yuicompress: false,
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/',
src: [
'styles/**/*.less'
],
ext: '.css',
dest: 'assets/'
}
},
Currently this is installing all of the generated css files into the same directory as the original less file it came from. What we'd like to do is have them spit out into an /assets/css/ directory, but with the same relative structure. eg:
assets/
css/
base.css
client/
client.css
device/
tablet.css
phone.css
Is there a grunt-contrib-less configuration that can accomplish this?
An easier way to do this seems to be:
less: {
options: {
paths: 'assets/',
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/styles/',
src: [
'**/*.less'
],
ext: '.css',
dest: 'assets/css'
}
},
I was able to achieve the desired effect wit the following Gruntfile.js
var path = require('path');
module.exports = function(grunt) {
grunt.initConfig({
less: {
options: {
paths: 'assets/',
yuicompress: false,
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/',
src: [
'styles/**/*.less'
],
ext: '.css',
dest: 'assets',
rename: function(dest, src) {
return path.join(dest, src.replace(/^styles/, 'css'));
}
}
},
});
grunt.loadNpmTasks('grunt-contrib-less');
}
Explanation
Although it is not in the grunt-contrib-less docs there are a bunch more features available for files objects. I didn't realize there were this many until I was working on answering this question. The link for the docs on them is under resources.
Resources
Configuring tasks - Building the files object dynamically

jshint grunt exported options

Hi I'm trying to achieve the following. I'm using grunt for jshint validating.
Somewhere in a file I have used:
var logger = function () {
// some ode
}
Because logger is never actually used jshint correctly shows me the following error.
W098: 'logger' is defined but never used.
I could set unused to false and it would work perfectly. But I actually want the option to take place in other files and warn me about unused variables. So the unused option is not gonna work for me.
I also saw that I could use a inline comment like this:
* exported EXPORTED_LIB */
But I would actually prefer to avoid cluttering my files with such comments. Is there any chance I can specify an exported options in my grunt file like I can for example for globals.
Heres the jshint part of my gruntfile:
jshint: {
// global options
options: {
camelcase: true,
curly: true,
eqeqeq: true,
forin: true,
immed: true,
indent: 4,
latedef: true,
newcap: true,
noarg: true,
nonew: true,
plusplus: false,
quotmark: 'single',
undef: true,
unused: true,
strict: true,
maxparams: 4,
maxdepth: 4,
trailing: true,
maxlen: 120,
browser: true,
node: true
},
server_logger: {
src: [BASE_PATH_SERVER_LOGGER, '/**/*.js'].join(''),
options: {
browser: false
}
},
client_logger: {
src: [BASE_PATH_CLIENT_LOGGER, '/**/*.js'].join(''),
options: {
node: false,
devel: true
}
}
}
Thanks for your time.
Best regards
Playerwtf
UPDATE: I made an issue on jshint github repository here
This was recently fixxed and works now as I would expect it.
github-issue
As an example I use it like this in my gruntfile
client_logger: {
expand: true,
cwd: BASE_PATH_CLIENT_LOGGER,
src: '**/*.js',
options: {
node: false,
devel: true,
globals: {
logger: true,
expect: true,
it: true,
describe: true,
beforeEach: true,
afterEach: true
},
exported: ['logger']
}
}
But the npm module was not yet updated. If you want this to work you will have to manually copy the newest version from the jshint github repository and replace the one in the current module or wait until it is updated.
i think you can exclude files in your src-files, so you could exclude your logger file from your basic linting (i suppose the logger file is logger.js here), and lint the logger file separatly with the unused-flag turned off.
read more about that here -> "! at the beginning of a pattern will negate the match"
you could set the cwd (and leave the join stuff). see more about that in the docs: Building the files object dynamically
jshint: {
// global options
options: {
... your global options here
},
server_logger: {
options: {
browser: false
},
files: [{
cwd: BASE_PATH_SERVER_LOGGER,
src: ['/**/*.js', '!logger.js']
}]
},
client_logger: {
options: {
node: false,
devel: true
},
files: [{
cwd: BASE_PATH_CLIENT_LOGGER,
src: ['/**/*.js', '!logger.js']
}]
},
lint_logger: {
options: {
unused: false
},
files: [{
src: ['logger.js']
}]
}
}
not 100% sure if that works, but i think it should at least lead you into the right direction. if you need to specify a path and not only a file for excluding you could put your logger-file in a separate folder an just exclude that folder!

Resources