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
Related
I am new to grunt and task runners in JS, so this might seem a simple question but I have been unable to find exact working answer.
I have :
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: '\n\n'
},
dist: {
// the files to concatenate
src: ['scripts/app.js', 'scripts/constant.js'
],
// the location of the resulting JS file
dest: 'scripts/custom.js'
}
},
This task collects all my custom file together. What I want is to do similar thing for all my vendors file. Finally I should end up with two js only custom.js having my concatenated-minified code and vendor.js having concatenated-minfied libraries.
How do I write grunt configuration for this. Do I need to make two different tasks. If I write the above code twice with different input files, it seems to run the last code.
grunt-contrib-concat can be configured to utilize multiple-targets.
For further documentation on this subject refer to multi-tasks and Task Configuration and Targets in the grunt documentation.
Gruntfile.js
For your scenario you need to configure your concat task similar to this (Note: the new custom and vendor targets):
module.exports = function(grunt) {
grunt.initConfig({
concat: {
options: {
separator: '\n\n'
},
custom: {
src: ['scripts/app.js', 'scripts/constant.js'],
dest: 'scripts/output/custom.js'
},
vendor: {
// Modify the src and dest paths as required...
src: ['scripts/vendor/foo.js', 'scripts/vendor/baz.js'],
dest: 'scripts/output/vendor.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('concatenate', [
'concat:custom', // <-- Targets in a task are called using a colon separator.
'concat:vendor'
]);
};
Running concat
Using the example gist provided above you can run the concat task via the CLI by typing the following command:
$ grunt concatenate
Configuring Options
If you require different configuration options for both the custom and vendor targets you will need to move the options object inside their respective targets. As explained here.
Note: Using the example gist provided the options specified will apply to both targets.
I am trying to include a modular third-party library (PhysicsJS) into my webpack project. This library is AMD- and CommonJS-friendly, and has well-formed submodules that I want to access. However it is primarily structured for RequireJS, via its packages definition spec in require.config(), so the entry point isn't a standard index.js. Instead the entry point is physicsjs.js.
In other words, I can't seem to figure out how to configure webpack to resolve both the library's main file and its submodules. It just seems like if the library's entry point isn't index.js and it has submodules, you are out of luck, and I just can't believe that's correct, so I must be missing something.
So, how can the following statements be made to resolve?
require('physicsjs'); // entry point
require('physicsjs/bodies/rectangle'); // submodule
I have tried variations of this config:
resolve: {
modulesDirectories: [
'js/bower_components'
],
alias: {
'physicsjs': 'PhysicsJS/dist/',
// doesn't find physicsjs.js
'physicsjs': 'PhysicsJS/dist/physicsjs.js'
// doesn't find the submodules
}
},
The directory structure looks something like this:
+ js
- main.js
+ bower_modules
+ PhysicsJS
+ dist
- physicsjs.js // module entry point
+ bodies
- rectangle.js // desired submodule
+ lib
- MyModule.js
Note that PhysicsJS does have a minified version of the entire library, which I will use if there is no other alternative, but I would rather only load what I actually use.
Also, the submodules themselves use require('physicsjs'), so calling require('physicsjs/physicsjs') is not a solution.
The solution is to declare the alias twice, first as an exact match (using a trailing $) and then again as a normal match (no trailing $). So my config now looks more like this:
resolve: {
modulesDirectories: [
'js/bower_components'
],
alias: {
'physicsjs$': 'PhysicsJS/dist/physicsjs.js', // Exact match
'physicsjs': 'PhysicsJS/dist' // and again with a fuzzy match
},
},
How would you negate the cleaning of a particular folder using grunt-contrib-clean. Negating the match doesn't appear to work.
clean: {
plugins: [
'app/plugins/myplugin',
'!app/plugins/myplugin/assets'
]
}
I've tried a couple different negation patterns, such as:
'!app/plugins/myplugin/assets'
'!app/plugins/myplugin/assets/**'
as well as, reversing the positions in the array in case that mattered. Can't seem to hold onto the assets folder/contents on clean. The assets folder contains jQuery, AngularJS, and built Bootstrap (SASS), which I don't want to have to keep copying/building, seems a waste of time.
I quickly set up a folder structure like you're referencing and tried the following, that works for me:
clean: {
options: {
'no-write': true
},
plugins: ['app/plugins/myplugin/**/*', '!app/plugins/myplugin/assets/**']
}
The first wildcard selects all files inside the myplugin folder and all subfolders (but not the directory myplugin itself!), while the negation deselects the whole assets directory including all subfolders and files.
You should remove the options field for real testing, as no-write: true is only simulating a clean but doesn't actually delete files.
Hope that helps!
I wanted the ability to blow away all of bower_components except for require.js. Here is how I did it in my gruntFile:
/* all bower components except require */
applicationDistHome + '/bower_components/**/*',
'!' + applicationDistHome + '/bower_components/requirejs/**',
applicationDistHome + '/bower_components/requirejs/*',
'!' + applicationDistHome + '/bower_components/requirejs/require.js',
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)
This is my first time using Grunt and I'd like to have it combine all my js modules, each of which is wrapped in an immediately executing function, containing a 'use strict' declaration and put them into one file, wrapped up in only one immediately executing function, with only one 'use strict' declaration.
How is this normally done?
I figured this would be a common use case? Perhaps I'm going about things the wrong way? Should I be using one of the module loading formats (i.e. commonjs, amd) All these files will always be loaded together in the browser, so I actually wouldn't mind removing all the immediately executing functions if that's how people normally go about it. The important part is that the end result is somehow wrapped, passes lint and unit tests and contains the 'use strict' declaration.
(I should clarify, I do have it working, linting, unit-testing, concatenating, and minifying, it just feels like I'm doing something wrong when I see a bunch of unnecessary immediately executing functions in the final concatenated file.)
As of pull request 10, grunt-contrib-concat now has a footer option. Instead of an intro and an outro file, I would use a banner and a footer.
Gruntfile.js
concat: {
dist: {
src: ['src/my-lib.js'],
dest: 'dist/<%= pkg.name %>.js',
options: {
banner: ";(function( window, undefined ){ \n 'use strict';",
footer: "}( window ));"
}
}
}
In my opinion, this is more maintainable and allows for templating using other properties defined in your Gruntfile.
I usually do it like the jQuery team does it. You create an intro.js and outro.js and put everything else in between:
intro.js
;(function( window, undefined ){
'use strict';
outro.js
}( window ));
grunt.js:
concat: {
dist: {
src: [
'js/src/intro.js',
...
'js/src/outro.js'
],
dest: 'js/out/app.js'
}
}
Just want to add to #elclanrs answer that if you want to be able to keep your modules in separate files for easier debugging during development, you would obviously have to wrap them with intro.js and outro.js as well. Using the built-in concat task you'd have to write something like:
concat: {
events_debug: { // wrap the 'events' module in IIFE
src: [
'js/src/intro.js',
'js/src/events.js',
'js/src/outro.js'
],
dest: 'js/out/events.js'
},
callbacks_debug: { // wrap the 'callbacks' module in IIFE
src: [
'js/src/intro.js',
'js/src/callbacks.js',
'js/src/outro.js'
],
dest: 'js/out/callbacks.js'
}
// zzZZZ...
}
Which is very tedious and self-repeating. Perhaps you may want to create a custom task for mass-wrapping files, e.g.
wrap: {
html: {
intro: 'partials/intro.js',
outro: 'partials/outro.js',
src: 'js/*.js',
dest: 'out' // output directory
}
}
There was a question about this recently, see this thread:
Using grunt concat, how would I automate the concatenation of the same file to many other files?
I would recommend you to use my grunt plugin grunt-concat-deps since it automatically resolves your modules independent on your architecture.
PLUS: You don't need any explicit module configuration for the plugin as it relies on declarative and decentralized module definition in a YUIDoc style.
See here for further information: https://github.com/leoselig/grunt-concat-deps