-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speed up tasks by only running on changed files #50
Comments
I see what you mean. This shouldn't be that hard to achieve. From the top of my head, and as long as files can be processed without mixed side effects (like multiple files getting merged into a single file, which would become invalid if a single file has changed), we could leverage what is being discussed in #46. When specifying a list of files through an expression, while it was being expanded, we would store each I should also note that I'm not all that crazy with the sort of static exclusion rules I'm suggesting. I think it's fine to provide a few useful ones, but ultimately this should be as simple as declaring With all that said, I like your suggestion, and I think a lot of people will find it useful. 👍 |
Well, me and @satazor had a long talk today about several things in In fact, when talking about only running something on files that haven't changed, what we're actually doing, is saying that we only want the task to run on a set of files that match a set of criteria. What this criteria is, can be very heterogeneous, depending on the use case, so we needed a way to give the user that flexibility. This is where micromatch comes into play. We thought about creating a superset of minimatch, with enhanced exclusion features. Here's an example, consider the expression
micromatch.addFilter('my_filter', function (opt) {
// options are the attributes between parenthesis in the expression
// (in the example above, this would receive a { id: 'minify' })
return function (files, next) {
// remove files using whatever criteria
next(null, filtered_files);
}
}); The example above would allow me to do something like As for distributing these filters in the community, which we can support later, we can leverage the
Btw, sorry about the long post, just wanted to be thorough. Tell me what you think! Keep in mind that even though it might look a complex solution at first glance, if you take away the internals of how everything works, it is pretty simple for the user to use these features. |
Bellow I will describe another solution to the problem. In tasks that have a var lib = require('automaton-lib');
//... then, when calling a task
options: {
files: {
'tmp/src/': 'src/**/*',
'tmp/lib': ['lib/**/*', lib.file.excludeStale('minify') ]
}
}
lib.file.excludeStale = function (id) {
return function (files, next) {
// Implementation should return only changed files for the `id` group/identifier.
next(null, filtered_files);
};
} Advantages of this approach:
Disadvantages:
Also note that options: {
files: {
'tmp/src/': ['src/**/*', '!test/']
}
} Feedback on both proposals needed! |
I would try to implement it as a separate lib, this feature is useful outside automaton and not all tasks should be able to support or need this feature. |
I also like that solution, and think both solutions have its advantages and disadvantages. There is something though, that should also be pointed out as an advantage for the first solution, which is its ability to specify a rich pattern that consists both of inclusion and exclusion statements right in the string (big advantage in the sense that it can be used anywhere a string is allowed, ie. object keys). This renders As for the version issues and name conflict are non-issues, I think, since we have a solution for it, just requires implementation. I guess it mostly comes down to wether the complexity of implementation is worth the gain, as both strategies have disadvantages in terms of ease of use/flexibility. I agree this should be built into a separate lib, which is why we are considering creating it under the name Anyone else have any thoughts on the strategies? |
I do see the benefits with the first solution, but I think globbing patterns are far too confusing as they are, no need to make them even more so. So I would prefer the second one. (The Also, please don't do any magic with fetching filters from NPM and having version numbers in the pattern. This should be explicit. Like: How about a third solution, using underscore templates instead. That way you can get values. micromatch.addFilter('my_filter', function (opt) {
// options are the attributes between parenthesis in the expression
// (in the example above, this would receive a { id: 'minify' })
return function (files, next) {
// remove files using whatever criteria
next(null, filtered_files);
}
});
options: {
files: {
'tmp/src/': 'src/**/*',
'tmp/lib': ['lib/**/*', '<% filters.my_filter(val) %>']
}
} |
@marcooliveira We need to come up with a final decision on this. I'll need to work on |
Please note that for |
I've implemented this in: https://github.com/IndigoUnited/node-gloth Feedback welcome. We now need to decide if we want to be able to specify hooks also has strings like: 'some_hook!params_to_pass_to_hook' or to leave them as functions only. |
I don't know the best way to implement it, but from being involved in grunt early on, we've gotten that request a lot.
It makes sense too. It would be way faster to only execute on a changed file instead of everything.
Let's say you have a sass and coffescript task. You run Automaton, and it takes some time. You then change one of the CoffeScript files and run Automaton again. I now recompiles all Sass and CoffeScript files for this little change. This is extremely inefficient.
What it however should have done, somehow, is to only recompile the changed CoffeScript file.
This is a fairly common pattern, so it shouldn't require a lot of boilerplate in the task.
Related grunt issue: gruntjs/grunt#212
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered: