3

Most JavaScript minifiers "want" to put all of the generated, minified code on a single line, except for the license comments. However, it has been discovered that some JavaScript interpreters become unstable when lines are too long. (Also, if a need arises to inspect a minified file in a text editor, you better make sure your editor is up to the challenge!)

As an adaptation to the problems sometimes caused by ultra-long lines, many minifiers automatically limit the maximum line length to some arbitrary value, such as 10000 characters.

But why do it this way? Even minified code must have spaces here and there. If these spaces were replaced* with newline characters (\n), the size of the file would not grow, and all of the problems often attributed to super-long lines would probably go away. Additionally, splitting long lines in this manner might make it more feasible to perform other tasks, such as "diffing" different builds of the same minified project.

So my question is this: Are there minifiers that provide a way to do this? Or, alternatively: Are there build tasks that can be used to automatically replace spaces with newlines, without disrupting the preserved (license) comments?

I'm using Grunt to build my project, so I would prefer answers targeting this environment, but I'm interested in all possible solutions.

Edit:

* wherever it is safe to do so without breaking semantics

Sharky
  • 549
  • 5
  • 14
  • 1
    I think you need to be careful about where you put newlines. Javascript inserts implicit semicolons in some cases on a newline (if the line could be a fully valid line), so just replacing spaces with newlines could potentially break the code. See http://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi – Herms Jun 11 '14 at 19:44
  • Per this, requirejs with uglify2 allows you to set the max line length. http://stackoverflow.com/questions/20083717/limit-line-length-with-requirejs-uglify – Jonathan M Jun 11 '14 at 19:45
  • Per this, grunt has a max-line-len option. https://www.npmjs.org/package/grunt-minified – Jonathan M Jun 11 '14 at 19:47
  • @Herms: What I've heard about that phenomenon is that the implicit semicolon is only inserted if the token on the next line would result in a parsing error without it. If this is the case, I would guess that the code's semantics could not be altered by inserting newlines where spaces appear. – Sharky Jun 11 '14 at 19:48
  • @Sharky See the link I posted in my comment. It provides the actual rules. It's not really that simple. – Herms Jun 11 '14 at 19:49
  • @JonathanM: Yes, I alluded to this feature in my question. However, I am seeking to insert newlines based on where spaces appear, rather than where the line length exceeds some arbitrary value. – Sharky Jun 11 '14 at 19:51
  • 1
    Also, consider the performance impact. Newlines require extra processing by the interpreter (to determine if it has to insert a ;). If you replace every space with a newline you're greatly increasing the amount of times this processing is needed. Also, properly-minified javascript shouldn't have many spaces anyway, and the ones it has are most likely to be inside string constants you don't want to change. – Herms Jun 11 '14 at 19:54
  • Oh, the string constants point is a really good one! But I'm not convinced performance would be impacted, since newlines may not be treated differently from whitespace until a parsing error is encountered (which would never happen so long as the minifier is properly inserting semicolonss). Do you know of any empirical tests that demonstrate performance issues related to newlines where ASI never happens? – Sharky Jun 11 '14 at 20:00
  • On that note, I wonder if some of the tricky minimizer replacements I've seen, such as `!0` for `true`, impact performance. Perhaps an interesting topic for another question. :-) – Sharky Jun 11 '14 at 20:03
  • After seeing (and independently testing) that `return "something"` would not have the desired effect if a newline was used instead of a space, it is easy to concede that my previous comment ("What I've heard...") conveys an inaccurate rumor, and that this is a complex problem. (Thanks, Herms.) Still, since minifiers already provide the option of breaking long lines, they have undoubtedly already figured out the rules of when it's safe to do it. – Sharky Jun 11 '14 at 20:12
  • @Sharky, I think you may be thinking about the max-line-len option wrong. It doesn't limit the input or output. It just makes sure the max line length is not greater than the specified length. – Jonathan M Jun 11 '14 at 20:26
  • @JonathanM No, I get that. What I'm looking for is a different splitting trigger -- to split not because I've reached a specified line length, but rather, split simply because I've reached a point where I _can_, without penalty (such as lengthening the file or changing semantics). When a minifier inserts a line break just because it has exceeded (or is about to exceed) a line length, it can lengthen the file (ever so slightly). I have just verified that UglifyJS indeed _does_ lengthen the file in this manner. – Sharky Jun 11 '14 at 21:58

0 Answers0