Small warning on developping with minified javascript: highlightjs language sample
Today javascript is a full language with its build and development tools. This means you don't need anymore to abuse of minified versions of the libraries and just need to let your build handle it for you.
To show one pitfall of using directly a minified version I'll take an example using highlight.js library.
Highlight.js is a great library to prettify code samples on your website. It is relatively easy to use and easy to extend in term of styling but also code itself. However it has one pitfall: the source bundle is not that natural to use and you tend to import a minified bundle with some built-in language support.
This is great and works fine until you need to extend the library itself. Assume you want to implement a custom language for your dsl or your specific configuration file, you'll check out the documentation and see you need to do something like:
{
case_insensitive: true,
keywords: 'repeat until',
contains: [
{
className: 'mykey',
begin: '[a-z]',
end: ' ',
relevance: 0
}, // probably other rules with value and expression matching using class "expression" and "value"
]
}
Indeed, this is a very small and probably not working language but it is enough to get the idea. In very few words (don't hesitate to read the documentation for more details), here is how it works:
- case_insensitive is about the matching case for the expressions, here we ignore the case.
- keywords define the langauge keywords (will use hljs-keyword class), you can also define literal using the object syntax.
- contains define the matching rules, in previous snippet it is relatively simple (a key starts with a letter and ends with a space), but it can be very complex with nested rules (a contains rule can have another contains array). All the game there is to match the tokens of your language to add a class hljs-${className}, for instance hljs-mykey with our sample rule. Goal of course being to style differently each part of the language.
- relevance is used in language detection mode ("auto") to find the most adapted language to the content you passed in the highlight.js block. 0 means more or less "ignore". This is useful for simple languages matching potentially too much random texts.
Then hljs (highlight.js handler) allows you to register the language with a name to allow you to bind it to your code snippet....here we are? Not exactly, don't forget we imported the minified version of highlight.js so you code all that sample and nothing happens, you still get a single big block of string instead of a tokenized sample with blocks using our custom classNames.
Side note: in some other library case you would just get a bunch of errors without a clear explanation.
If you check your highlight.js you will realize you can find registerLanguage calls but no className, no begin, no end etc...The minification process destroyed all "API" names (don't start to cry if you are a backend developer and keep in mind there are potential configuration to avoid that on the build you control ;)). Now the game will be to either migrate to the non-minified version or to guess which was the process. In highlight.js case it is not too hard, here is a matching you can guess after having formatted the minified version to make it readable:
- begin -> b
- end -> e
- contains -> c
- className -> cN
- ...
What does it mean? That we need to adjust our code to be aligned on that new "API":
?{
cI: true,
k: 'repeat until',
c: [
{
cN: 'mykey',
b: '[a-z]',
e: ' ',
r: 0
}
]
}
Of course I would recommand you to add in comments the name of the actual keys if you still want to use the minified version.
With that language definition your language will work properly but your code is seriously less readable and maintainable (I let you guess the errors are rarely that explicit).
To avoid such pitfalls it is important to use a build tool able to minify after having processed the whole application. This means it will minify highlight.js for you but in the same phase your application too with the same rules making the final application light but also consistent. There is no free lunch so doing that you will sometimes need to exclude some keywords yourself from the minification when they are part of the "API" or expected by consumer or meta code but this will at least ensure your code is readable. This is crucial if you are providing a library which will likely be consumed from plain sources and it is important for the lifecycle of your application (maintenance) if you develop an end product.
So think twice before importing a minified dependency! Happy js development!
From the same author:
In the same category: