Common practice with .js and .css file minification is to create .min.js and .min.css files. The problem is Shake FilePatterns will match both minified and non-minified files with this scheme with a pattern like //*.js. The docs seem to recommend making unique extensions for each like reg.js and min.js but I'm not sure this is a path I want to take. How can this be worked around in Shake?

Edit: The problem is with using getDirectoryFiles:

js <- getDirectoryFiles "" ["//*.js"]
let jsMins = map (-<.> "min" <.> "js") js
need jsMins

There's a target for "//*.min.js that works just fine but getDirectoryFiles "" ["//*.js"] starts picking up the generated .min.js files.

有帮助吗?

解决方案

I can think of two alternative approaches:

Post process getDirectoryContents

Call getDirectoryContents then filter out the values you don't care about. Something like:

xs <- getDirectoryFiles "" ["//*.js"]
need [x -<.> "min.js" | x <- xs, takeExtensions x == ".js"]

If you are running this code outside of a rule, e.g. in an action, then it is 100% correct. If you are running the code in a rule then the rule will run once, new files will appear, and then the rule will run again (which is also a lint violation, and not great build hygine). I suspect you are running outside of a rule, so this approach is probably a good one.

Write an Oracle

If you are inside a rule, you can define an Oracle which is like getDirectoryFiles, but skips the min files.

newtype JsFiles = JsFiles () deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
addOracle $ \(JsFiles _) -> fmap (\x -> takeExtensions x == ".js") $ getDirectoryFiles "" ["//*.js"]

Now you can use askOracle $ JsFiles () in your rule, and it will only change when new non-min files are added.

其他提示

There are several approaches to writing different generating rules for .js vs .min.js:

  1. If you aren't ever generating .js or .css files, only using existing source files, and thus don't need //*.js rules, then just make your minimisation pattern be //*.min.js and it will work.

  2. If you are generating .js (e.g. from CoffeeScript files), then if you are generating the .min.js and .js files in different directories you can distinguish the patterns at that level, e.g. dist/*.min.js, decafinate/*.js.

  3. Use ?> patterns, for example:

    (\x -> takeExtensions x == ".js") ?> \out -> ...

    Note that takeExtensions (with the trailing s), that will only match files whose complete extension is .js, so won't match myfile/test.min.js.

If solution 1 works, use that (it's simplest). If solution 2 naturally falls out (e.g. that matches what you wanted to do anyway) it can be easier to have more restrictive patterns, but option 3 "just works" everywhere so is probably what I'd do.

Note that p *> a is defined as (p ?==) ?> a (plus a lot of extra plumbing for good error messages!), so ?> isn't anything special and works happily with your existing rules. I usually find about 5-10% of my rules use ?> patterns.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top