GruntJS's documentation is pretty thrifty. There's a small section on creating a task, and one on creating a plugin.
If I want to create a new thing (rather than using an existing thing like jslint) then am I creating a task or a plugin?
A plugin is just a convention for creating reusable tasks and publishing them to npm. If you don't need to publish them to npm then you can do the same with
grunt.registerTask('alphabetize', 'description', function(arr) {
/// ...
});
You would write a task whether you create it in the gruntfile.js or encapsulate it in a plugin. In a plugin it would just encapsulate that task
module.exports(function(grunt) {
grunt.registerTask('alphabetize', 'description' function(arr) {
// ...
});
});
Think of a plugin as just another Gruntfile.js that's located in a different folder with it's own package.json. It does the same thing as the Gruntfile.js but in a more reusable way.
Related
I'm working on a Sails.js app using angular 1.5x for front end. Recently I began working with textAngular, which works good in development, however, for some reason running in production, which (I believe to be the issue) runs grunt concat and uglify, therefore minimizing all js, I get a js error regarding injecting into my angular module/app. If I remove all references to textAngular it will concat/uglify and run fine in production. I want to use textAngular, and don't believe it is an issue with those scripts per say. How should I go about troubleshooting this issue? Are there any concat or uglify options that might help me pinpoint or resolve the issue?
ADDITIONAL INFO:
The angular code for injecting textAngular:
var sangularApp = angular.module('sangularApp', ['datatables', 'textAngular']).
config(function($provide) { // provider-injector
$provide.decorator('taOptions', ['$delegate', function(taOptions) { // $delegate is the taOptions we are decorating
taOptions.toolbar = [
['pre', 'bold', 'italics', 'underline', 'strikeThrough','ol','insertLink', 'insertImage','html']
];
return taOptions;
}]);
});
Here is the error I get (when I run in production and the files are minified:
Error: [$injector:modulerr] http://errors.angularjs.org/1.5.0/$injector/modulerr?p0=sangularApp&p1=%5B%24injector%3Aunpr%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.5.0%2F%24injector%2Funpr%3Fp0%3Da%0Ad%2F%3C%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A1797%0APa%2Fo.%24injector%3C%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A20234%0Ad%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A18987%0Ae%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A19221%0Ak%2F%3C.invoke%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A19311%0Ad%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A18448%0Aj%2F%3C%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A18580%0Af%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A2243%0Aj%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A18357%0APa%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A20389%0A_%2Fg%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A9026%0A_%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A9329%0A%24%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A10%3A8641%0A%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A14%3A26564%0Afa.Callbacks%2Fj%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A2%3A7154%0Afa.Callbacks%2Fk.fireWith%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A2%3A7927%0A.ready%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A2%3A9741%0Ag%40http%3A%2F%2Fcutupcode.com%2Fmin%2Fproduction.min.js%3A1%3A1606%0A
This is a difficult question to respond to without some debugging information or console errors.
From what you've mentioned my suggestion would be to look back over your scripts and make sure that the additional library for textAngular has been included and that the injection of the library into your module is done correctly.
Minification and concatenation typically don't cause any issues for me when the library works fine without those tools applied.
I'm facing the following interesting problem:
I would like to create a Grunt task that is executed at various parts of the build/release process.
It's possible that one invocation makes some changes to files based on a pattern, e.g. replacing a version number or Git tag like #develop in some files.
A later invocation in the same build needs to "revert" the above changes back to their original values.
Based on the above I would need to find a way to track the changed files from the first invocation, so I can revert the changes in the second step. I can't use a pattern for the second step to avoid false positives.
Example:
Start a release - many steps as part of this, compile, uglify/minify, bump version number, create a git release branch.
Replace the version numbers of some dependencies, e.g. in bower.json - change them from #develop to #1.2.3
Some more steps, including Git commits
Replace the version numbers changed above from #1.2.3 back to #develop
Additional steps to clean up the release
The last step is difficult since I don't want to change any occurrences of #1.2.3 that I did not update in the previous step. For this I would need to store the list of changed files somewhere, either in memory, or in a temporary file in the project root, e.g. something like .grunt-replace. After reading the file in the last step, it could be deleted by the plugin.
Is anybody using a Grunt plugin like this? How would you solve this? Does Grunt have functionality that would support something like the above, or should I just use the Node.js file API?
Are there other patterns I should consider for keeping some kind of state between Grunt invocations?
You can use a file watcher to keep the grunt process alive and then keep track of state using events.
For instance:
var files = [];
module.exports = function(grunt) {
grunt.initConfig({
watch: {
files: ['orig.js'],
tasks: ['my-task']
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('my-task', function(){
// Execute some task
});
grunt.event.on('watch', function(action, filepath, project) {
//add file
files.push(filepath);
});
grunt.registerTask('default', ['watch']);
};
You can then keep track of which files have been changed and act accordingly.
I have to add though, that this is a bit of a hack. Your build flow shouldn't be stateful, you need to be able to build from scratch.
I am quite new with GruntJS and I wonder if it is possible to have a task that loads some RequireJs modules to process them and write the result within a JS file.
I describe my scenario:
I have a RequireJs based project with many files.
I would like to concatenate/minify/etc the project to deploy it and increase performances, etc.
The optimization works perfectly with the grunt-contrib-requirejs plugin.
The grunt-contrib-requirejs plugin works with a main.js file and I should need to generate it dynamically.
I would like to generate the main.js processing some RequireJS module of the project (call them fileA.js and fileB.js).
I would like to use the generated main.js to run the grunt-contrib-requirejs plugin.
So the task sequence would be something like:
Custom Task:
loads fileA.js and fileB.js
merge them together
write the result of the merging within a new JS file
grunt-contrib-requirejs task:
use the generated main.js file to optimize the project
Do you know how can I achieve this?
I don't have any kind of restrictions on the way/tools/libs to use.
You can load RequireJS in Grunt, as follows:
var requirejs = require('requirejs');
You can then fetch all the fileX.js files in your tree through Grunt:
grunt.file.recurse('js/modules/', function callback(abspath, rootdir, subdir, filename) {
if (filename === 'fileX.js') {
/* Do something here. */
}
}
Once you have all the modules you need you can use r.js to minify/concatenate them.
I'm trying to add a simple JS script to the server side of Meteor. Everywhere I read I'm told I should create an atmosphere package for the script-but that seems like a pretty round about way of doing it.
I am presently creating a local package to extend a feature on the app I'm using, and would like to use the script on the server side. Is there a way to simply REQUIRE a js file in meteor?
You can simple create server folder and add a js file to it.
Or you can use everywhere
if (Meteor.isServer)
{
//some servercode
}
more info about project structure http://meteortips.com/tutorial/structure-application/
The simple way to REQUIRE a js file in meteor is to put in the lib folder.
If it's required only by the front-end, then place it in the client lib folder (myproject/clinet/lib/requiredJSfile.js), if it's required by only the server, then place it in the server lib folder (myproject/server/lib/requiredJSfile.js).
If it will be used by both, put it in the root lib folder (myproject/lib/requiredJSfile.js).
You should do this, because the meteor rendering engine places the files from the lib folder on top of the inclusion list, meaning that when your actual meteor code runs it will be already available.
Check out this boilerplate for an example: https://github.com/matteodem/meteor-boilerplate
As a new user of Meteor it's not super clear here that, when creating a function to be included server-side you write it differently in Meteor.
Traditional .js function declaration would look something like:
function serverFoo(param1) {
console.log("serverFoo() param1="+param1);
return "bar";
}
The way to declare this function in Meteor:
Create a file "server/inc/server-globals.js".
var serverFoo = function(param1) {
console.log("serverFoo() param1="+param1);
return "bar";
}
I have my JavaScript organized as described here: https://stackoverflow.com/a/10816983/83897.
I have a JavaScript-heavy ASP.NET application that has multiple different pages (vs. being a single-page application). Each page has different dependencies, so I have a per-page .js file (page1.js, page2.js, etc.). Each has a require() call, declaring its dependencies:
require(['jquery', 'page1Module'], function($, module){
// page1 specific stuff here
});
This works fine. What I'm wondering is, how might the RequireJS build process work? I think I want a per-page "build" .js file (e.g. page1-build.js, page2-build.js, etc.)? Is there existing software I can leverage?
The process might look like this:
Compile all dependencies for a given script into one build.js file in a temporary directory.
Calculate an MD5 fingerprint for the compiled file.
Compare that fingerprint with the comparable file in public/assets.
Create an in-memory RequireJS manifest, mapping each module to the compiled file. Append this manifest to the compiled file.
Somehow make production use the build file.
EDIT: After some thought, I'm thinking the RequireJS optimization using node + r.js will just be part of a larger asset building process, where the asset building relies on some other, third-party library. The RequireJS optimization will simply be used for certain JavaScript dependencies (i.e. the JavaScript files for each page, including found dependencies), perhaps specified in some XML config.
You can create multiple optimized files by specifing the modules in the build profile:
{
modules: [
{
name: "main"
},
{
name: "page1",
include: ["dep1", "shim2"],
exclude: ["main"]
}]
}
Each entry will generate a optmized .js file.
More info here: How to use RequireJS build profile + r.js in a multi-page project