Tuesday, June 30, 2015

How to serve SVG by default

With retina screens, TV and consoles, old, not so old, modern, and new devices, it makes no sense anymore to serve an image, unless this is a picture.
Logos, buttons, icons, everything that used to be that little png, today can simply be the very same image but served as SVG.

Forget about feature detection

Seriously, I've tried them all ... ! The read only property complete doesn't mean an SVG is supported. In order to be sure, we should draw such SVG into a canvas but even doing so, we cannot be sure the result is that such SVG will be shown at all.
There is only one way to do it right for various reasons: hold your chair, here it comes!

The inline onerror handler

To be sure that the browser will actually see something as meant and as soon as possible, we can use, trust, and recycle inline the onerror handler granting backward compatibility with pretty much every old browser we know.
<img src="image.svg" onerror="Image.onerror.call(this)">
That's truly it, unless you want to name the handler differently or set it on the global scope, same way we are supposed to set basic CSS inline per each page we serve, we could set basic JS too in the header and without needing a network connection at all
<!DOCTYPE html>
<html lang="en">
  <head>
    <script>Image.onerror=function(){if(/\.svg$/.test(this.src))this.src=this.src.slice(0,-3)+'png'};</script>
Bonus for such method is that we could always use it directly as DOM Level 0 onerror in case we need it, and we might also do eventually more with the event object, using as example Image.onerror.call(this,event) per each inline invoke.

But why an inline error in 2015?

Because around 95% of surfing browsers support SVG these days, and it makes zero sense to serve any other decoration or icon as png these days.
Accordingly, only if you would like to support old browsers too, you might decide to use above technique, if you don't care you can simply stick serving SVGs as Image src too.

The inline onerror handler is also the fastest possible way to react to problems instead of using async, defer scripts, or even DOMContentLoaded: the onerror will beat any other technique granting best compatibility!

The technique is indeed meant as "gracefully degraded" experience, so that old browsers will still show the icon as png and don't bother serving 2X icons there, none of these browsers support retina displays.

SVG Hints

Following a couple of hints regarding SVGs
  1. inline support is not as good as image source support, hence feel free to include SVG via <img> but don't inline them in the wild
  2. SVG as Image sources cannot be styled via CSS (and are slightly faster to be rendered because of this too, it's a bit like ShadowDOM in action)
  3. thousands SVGs are slower than thousands PNGs when it comes to raw rendering performance
  4. gzip/deflate compression to serve SVGs will make them not too much heavier than PNGs but will scale any screen and resolution (better for the cache too)
  5. if you have a ViewBox property but you don't have width and height, the SVG might be rendered deformed in some browser (mostly WebKit based gotcha)
  6. if you use SVG external files as CSS url you won't have any possible fallback
  7. IE8, IE7, and IE6 works well with the suggested hint, but using png8 might improve even more the support (or actually with a fallback as GIF that would be universally recognized as such)
For now, I think that's pretty much it. Use it if needed, ignore it otherwise ;-)

What about CSP?

AFAIK CSP is incapable of granting well known inline handlers, even if you use correct sha, which is, for above code:
  • sha1-KQlMcC5gY2yF2YJLHmj92eDINwM=
  • sha256-fdsC+rLqqoTxcoa4lsSYSr9c4HaAmjb7eToXB2X/um8=
If you find a way to enable above goodness via CSP please share, thanks!

What About Web App Icons?

I've honestly no idea why these days we have to write this pile of crap:
<link rel="shortcut icon" type="image/png" href="/img/favicon-16x16.png" sizes="16x16">
<link rel="shortcut icon" type="image/png" href="/img/favicon-32x32.png" sizes="32x32">
<link rel="shortcut icon" type="image/png" href="/img/favicon-64x64.png" sizes="64x64">
<link rel="shortcut icon" type="image/png" href="/img/favicon-96x96.png" sizes="96x96">
<link rel="shortcut icon" type="image/png" href="/img/favicon-192x192.png" sizes="192x192">
<link rel="shortcut icon" type="image/png" href="/img/favicon-194x194.png" sizes="194x194">
instead of just this:
<link rel="shortcut icon" sizes="any" href="/img/favicon.svg">
Please complain with browsers vendors about such ridiculous nonsense, thank you!

Wednesday, June 24, 2015

Rethinking the $()

If any developer extends or modify native prototypes is doing it wrong ... unless you are Paul Irish?
( please bear with me Paul, this post has nothing against you or your snippet, it's rather on how developers react to whatever you propose since you are well known in the industry ;-) )

I am talking about his bling snippet, and the instant hype around it.

Nope, still doing it wrong

I haven't asked him directly but I believe Paul intent was simply to demonstrate that for a sketchy quick and dirty jQuery like functionality you really don't need to put 7 tools in your chain, a CDN, pick the right version or learn the whole API, you can just go with few lines of code.
The problem is the hype that will inevitably see developers start doing that in production or in their own libraries, using an obtrusive approach which is also not strictly necessary.

Did you know that queryAll returns an Array subclass?

The reason that snippets contains the following line:
NodeList.prototype.__proto__ = Array.prototype
is because querySelectorAll returns a NodeList collection, which is a static collection that does not extend nor inherit from Array.

W3C knows this has been inconvenient for just about everyone, so it's going to replace querySelector and querySelectorAll with query and queryAll, where latter one will return an Array subclass.
Elements is an ES6-style subclass of Array with two additional methods. It's the new NodeList / HTMLCollection.
Accordingly, the little snippet could be even smaller, and also more reliable in terms of results since these new methods not only return array like results, will also fix relative CSS selectors, meaning these are also more reliable/less surprise prone methods.
window.$ = document.queryAll.bind(document);

Node.prototype.on = window.on = function (name, fn) {
  this.addEventListener(name, fn);
}
 
Elements.prototype.on = Elements.prototype.addEventListener = function (name, fn) {
  this.forEach(function (elem, i) {
    elem.on(name, fn);
  });
};
If you are worried about query and queryAll compatibility, you can stop already since there is a poly for that, which will also normalize and fix much more, so nothing to lose.

Yet doing it wrong

No matter how small and pragmatic could be our snippet, we're playing dirty polluting both the global object and at least 2 prototypes. On top of this, add the usage of __proto__, which not only I'd like to not see anymore in favor of Object.setPrototypeOf, but it will also automatically break compatibility with IE < 11, and we realize that a little snippet, seen already as "cool one, will use it" from few developers, should probably stay confined in our browser console for debugging purpose and nothing else.
Accordingly, I think it would be wise not to start publishing libraries based on such snippet, and I also believe Paul would agree with me on this.

We still want the $ of jQuery without the jQuery.

Like the snippet says already, having a $ around is very handy indeed.
That could also be the only thing we need though, so that previous snippet could be simplified as such:
var $ = $ || (function (){
  function on(name, fn) {
    this.forEach(function (el) {
      el.addEventListener(name, fn);
    });
  }
  return function (css, parent) {
    var result = typeof css === 'string' ?
      (parent || document).queryAll(css) : [css];
    result.on = on;
    return result;
  };
}());
If we don't have queryAll or a polyfill in the page, we can simply use this line instead:
// change this
(parent || document).queryAll(css) : [css];

// with this
Array.prototype.slice.call(
  (parent || document).querySelectorAll(css), 0
) : [css];
The snippet gives us the ability to add listeners to window or any node simply doing this:
$(window).on('load', function () { /*...*/ });
See? No need to extend any global object, neither global prototypes ... Hoooorraaaaaay!

What else do we need?

Many already pointed out that having an off method would be handy too, I'd like to add on top the need for a dispatch method so that's also easy to dispatch events as well.
If we then consider that extendability could bring in basically anything else we think we might need, I can tell you I've already described the entire functionality of QueryResult, an utility already available via CDN with a deadly simple API you already know and a subclassing behavior which will gradually and natively integrate with modern browsers as soon as these will ship ES6 classes and subclassing in their engines.
So yes, we can have the $, and we can still have it in few lines of code, without being obtrusive, and via modern approaches such subclassing and queryAll.
Enjoy!

Wednesday, June 17, 2015

Quick Thoughts on WebAssembly

It's happening, all major browsers vendors apparently agreed on WebAssemply effort to bring .wasm files on the web.

I've read enough to give an instinctive, quick, probably premature, surely gut based, impression on this matter.
I'll cut the crap and throw the following bullets at you:
  1. bytecode is nothing new on the Web, it's actually what every Flash developer has been dealing for the last 15 years. On the non web side, LLVM has been one of the most successful target infrastructure "code", something every other non JS language has been hoping to find into the Web and JS platform as a target too. In few words, having an optimized universal language target, can bring only benefits for the entire programming ecosystem. Moreover, this means that JavaScript, or a (sub|super)set of it, will be most likely transpilable to LLVM. This means JS will gradually gain native-like horses power for all the things, including IoT devices. And this is huge!
  2. having all vendors and teams instead of being a proprietary format as it has been for the .swf before, means many more developers and engineers will be involved and happy to jump in. Beside the inevitable higher amount of consequential bikeshed, pattern that reminds me every time of the joke about "How many engineers does it take to change a light bulb?", we have proofs that sometimes this kind of effort works. For instance, the biggest release of ECMAScript since the third edition just got approved and most of the people involved were from all those browser vendors.
  3. asm.js will soon become a widely adopted intermediate target language, since every vendor agreed on .wasm which initial goal is to be compatible with asmjs code. This is huge for Web related performance!
  4. developers will finally be free to choose whatever language they want; transpiling to a more capable infrastructure than just JavaScript as another programming language, and with closer performance to what they expect from their original PL of choice
  5. it will take long time, in terms of cross platform compatibility, before we'll see real-world, full .wasm based applications, and my only hope is that .wasm won't slow down the Web, since this still needs extra attention and huge amount of improvements from every browser vendor
  6. we've got the proof that all people involved or not in Open Source still use "Closed Source" (private) channels to make decisions about "the destiny" of the rest of the world
  7. it might slowly cause the beginning of JS decline once available, since JS has been reforged to be backward compatible, but a fresh new general purpose intermediate language, that could be a better target for new programming languages too, might be a better idea, over a standard that inevitably carries on quirks trying not to break what's been developed for the last 20 years online.
I'm curious to see in 5 years what this little post spoiled, what misunderstood, and still I'm actually quite excited about this .wasm news.

I'm looking forward to see progresses, and contribute as I can!

JS

Monday, June 08, 2015

ipcc, or better, how to retrieve a country via IP

In case you haven't read my previous post about The European's Cookie Law Absurdity, I suggest to understand what is this about and eventually go on.
The TL;DR version is that I've created, tested, and pushed to npm a very basic script that holds in memory a list of IPs, both version 4 and version 6, and returns a country code or a simple isEU(ip) boolean.

Why ipcc

Most databases are based on tokens and APIs. These are all wonderful, accurate, and fast, but for the EU Cookie's law absurdity all you might need is a boolean flag like "is this IP from EU or not?".
Well, now you can have such flag via node.js, assuming your server has a good amount of RAM and a decent CPU. It takes indeed a little more to bootstrap a website if ipcc is included, mostly due static Arrays holded directly on the file, Arrays that need to be parsed and hold on RAM.
// require it once
var ipcc = require('ipcc');

// for any request
function isRequestFromEU(request) {
  return ipcc.isEU(
    request.headers['x-forwarded-for'] ||
    request.connection.remoteAddress
  );
}

// in case you want to know the country
function whereIsRequestFrom(request) {
  return ipcc.resolve(
    request.headers['x-forwarded-for'] ||
    request.connection.remoteAddress
  );
}
Don't worry, if you ask multiple times different things using the same IP you will receive always the same previous answer stressing the CPU.
You can also read more on how it works on ipcc Github repository.

Special Thanks

Not to whoever wrote the EU law, but to db-ip.com, a wonderful updated service that provides a free, not so accurate, but extremely useful version of its countries database.

Saturday, June 06, 2015

The European's Cookie Law Absurdity

This post is not yet another rant on how pointless the "cookie law" banner is, this is a technical walk through on why such banner is absolutely unnecessary and, in 99% of the cases, wrongly implemented (not due lack of competences from who serves a website, rather lack of common sense and logic from whoever wrote this law).

1st - Users's IP Should Be Resolved Upfront

This is the very first misunderstood point about this law, and nobody is talking about it. There are already 2 technical needs in order to succeed in the banner intent:
  1. if your visitor/user is not in Europe, you most likely don't want to show the pointless banner
  2. if your visitor/user is in Europe, you must provide awareness in the guessed visitor/user language
If you surf known giants websites and services from the U.S. you think this law doesn't exist. You might eventually realize this law exists only if you visit the very same website from Europe. Take ARM site as example, and its bottom left banner: it's so obtrusive it might cover part of the navigation or, in some case, even special promotions or events:
Please note that is not an ARM website problem only, many international websites that had to implement such banner didn't bother spending time optimizing this experience, potentially requiring the update of every static page they've served since 90's, they most likely did the simple "is that IP from Europe? throw this banner!".

How to pretend to recognize where a user comes from

If our website works differently accordingly with the user choice about cookies, we might want to resolve the user's IP upfront and synchronously, resulting in a delayed response, and for cheap hosts a more stressful operation, that might even make the server more vulnerable to DDoS attacks.
This operation has a cost even if performed asynchronously, this is why there are online services such MaxMind GeoIP which aim is to provide an always updated list of IP ranges capable to resolve as Countries or even City, without any limit.
These folks are mentioned here because I've used their DB in the past and they offer a less precise but free alternative that requires the right link, info, and copyright but doesn't cost and doesn't use network. I was using a CSV file already in 2004 and while the PHP4 script is outdated, you can easily see how simple it is. A proper database import from the CSV thought would give us better performance.

Where is Europe failing here?

Imagine that starting from tomorrow a European law decides that only cars that use bananas instead of petrol are allowed to go around but nobody knows where to find bananas because Europe didn't supply them. At that point, private bananas corporates will become rich at the expense of every car owner.
In a "unified EU country" where the antitrust already bothered every tech company in the world, the "unified government" keeps making laws that favorites private services and push backs its own citizens. You say NO? ... so, where is the IP2GeoLocation database/service every European tax-payer can access at no extra costs?

The language barrier

Let's assume I am Italian, which I am, and I don't speak English. I visit the ARM (or mostly any other) website and all I can see is a very disturbing pop-over that says something I don't understand, with an X on it that universally means close.

Have I just inadvertently given consent to throw my privacy in the trash bin, be under "big-brother" cameras, and have my picture shown everywhere on the Web as a meme that will ruin my life forever?
The correct answer is: I've no idea what I've just agreed on.

This problem exists for every tourist in this world. Not only websites that pretend to be smart are so dumb that we are automatically redirected in the German, Italian, English, or Russian version of the website, using the same IP rule of thumb (user comes from Russia, must be Russian), there is no way we can solve this problem if not implementing a "never change my country or language" in both our browsers and on the server.

This is yet another simple User Experience case where the App never fails: it doesn't change its behavior or language accordingly with the country you are ... you open the app you use daily, you find the app you use daily. Even Google search fails here, keeping redirecting me to French results and sites just because I took a train London-Paris that in 2 hours apparently made me a French citizen ... this is part of the daily WTF Tech people still need to figure out, and in all this mess glory, the only punished person is the humble user that simply went to her/his favorite website to read her/his country news.

Where is Europe failing here?

The analysis of the language barrier has probably never been done. Europe is not like U.S., we speak many different languages and we can travel freely within EU countries. A law that cannot be reasonably implemented in order to improve, instead of destroy, the User Experience, is a law that should be instantly banned, period.

2nd - a11n (Accessibility)

Second only because those lucky that don't surf from Europe won't have also this specific problem, accessibility is another topic that this law didn't apparently consider much.
Most popovers or banners are shown either asynchronously or in a position fixed at the top of the page and here is just a very basic list of problems we have already:
  1. if shown asynchronously, a person might be interrupted in the middle of the reading and with a "natural tabindex order" changed, due classic link or button to close the banner
  2. if styled on top through CSS, and such CSS has been loaded asynchronously following "best practices", the banner might be placed at the end of the page to either avoid z-index problems or simply as less relevant (eventually shown asynchronous) content. In this case a screen-reader might completely ignore such banner info until it reaches the end of the page (too late).
If I add the fact that both JavaScript or CSS could be disabled, specially for people behind a screen-reader that don't really care about downloading tons of KB of CSS since they won't benefit much from them, we can realize this law could make regular navigation harder, and again gaining no benefits for any user, not even those that with current status of the web already have difficulties we don't imagine.
I wonder if there's any screen-reader user representative in the EU group of politics that made this law, or I actually would like to know their opinion too hoping it's me missing or misunderstanding the great achievement this law did for them.
Update
Apparently it's about 3 years that UK Government knows this Cookie's law conflicts against the disability one, thanks to idea15 for the link.

3rd - Incompatible with the Web

Let's forget for a moment this law is called Cookie's Law, as if we're living in the 90's, but it targets any sort of client/side technology which aim is to store user preferences in order to improve a User Experience and even cross site, where needed ...
The easiest, most compatible way, to avoid per each single visited website that banner for the next visit is to store a cookie.
I honestly imagine the person that signed this law as such:

There are several technical reasons this law is incompatible with the way the World Wide Web works, and here is just a subset of this list:
  1. we cannot control iframes or any other externally embedded resource, so that even if our site doesn't directly use cookies at all, the sharing of an authorized third parts content, which is not under our control, will not allow the user to be informed about that page, but rather chose on our page, and every other page that use that very same embedded content, that such embedded content might contain cookies, even if it doesn't, and just to play safely. It's like telling users that "crystal meth is not the problem, that pusher that didn't inform you is"
  2. the size of a foreign content might be not suitable for any text, so that even if the embedded content should be responsible for the cookie warning, it might be unable to inform the user (as example, Facebook like or Twitter share or fave buttons)
  3. giving the ability to external content to inject a warning in case it's needed opens vulnerabilities to our site, so there's no solution here no matter how we analyze the problem (and the current law is again the wrong answer that does not solve any problem)
  4. if the user has disabled cookies because already aware or for any other reason, most websites will keep showing forever an explicit opt out unable to respect the user choice. Fall-backs are needed, but all of them might fail anyway (no localStorage, no sessionStorage, no IndexedDB, no WebSQL, what else ... a server side session?)
  5. apparently nobody provided a list of browsers, with their relative or minor versions, that should be supported. Developing for the Web and serving a Website means also being able to support target browsers. If the technical responsible for this law uses IE8 to verify such law, we need to know it so that we can eventually grant the ability to see and drop such info. Please remember that position fixed is buggy there. Lynx? These users might be the luckiest surfers ever these days ... should we protect them too? I'm sure they cannot wait for it ...
  6. taking this very specific blog platform as example, I cannot control redirects it does. I cannot control if only via JavaScript and some poor sniffing if the users agreed or didn't and I cannot change its content accordingly if not, again, via JavaScript. Most platforms should be in charge of this matter but truth is, these don't. It's apparently our fault as publishers through a platform that, yet apparently, doesn't care.
The list of incompatibilities with the real-web-world is much bigger than this one, but at least we have already a basic idea on how superficial the analysis of risks and problems has been done before shipping this law. We, EU citizens, pay for these kind of laws daily, isn't that great? Aren't we happy?

4th - If the consent is implicit, we need only an opt out

Imagine somebody throws at you a bucket of ice-water, and you scream NO after you're already wet and frozen. Now repeat this per every new person you meet on the street: how brilliant is this?
Best part of this "game", is that people you've met that heard your NO won't probably throw at you ice-water next time, but every new person they know, every friend of them, everyone they're linked to, or every person they mention, will repeat this procedure: throw at you a bucket of ice-water, waiting for you to scream after that NO.
This is the story of the current status of the cookie law: they didn't bother browsers which are already capable of giving incremental permissions while surfing, such Geo Location, File Uploads, or Full Screen, they bothered the entire Internet and everyone surfing it in Europe which has to repeat the same procedure over and over. In few words, this Europe's law is technically causing a Repetitive strain injury to all Internet users, and all of them receive that ice-water welcome by default!

How could this problem be solved once for all

Instead of repeating this absurdity check for each consent and eventually each user's country, browsers vendor could arbitrary allow a property/flag that mutates both their User Agent string and their Sent Header: first one for the JavaScript inspection, where any other read-only property on the global scope would do, the second one for every server request, where the page can be served accordingly and there's no need to retrieve the country.
Indeed we have a solution that would work regardless where you are, a solution that could be implemented as a form of respect for every user surfing the Internet in this world, or at least where this kind of law is enforced.

This would actually protect users and their privacy, this would not require third parts databases or solutions, this would not affect performance on the server, and this would not affect performance on the client, which does not have to download scripts and CSS and HTML and JS in order to confirm they simply want to surf the Internet.

Unfortunately, I believe this is not convenient for the Internet advertisement and data selling business behind most big players, or I couldn't explain any of this madness otherwise ... so Cookie's law it is, with the entire World Wide Web penalized if surfing from Europe, and all of this thanks to EU politics that with such law didn't protect more at all any citizen, they just bothered all of them instead, "ignoring" the real problem: congratulations!

As Summary

Same as I don't understand politics that well, and indeed I do something else for living, I assume politics don't understand technology that well neither.
I don't think we need a European referendum here, we rather need top-notch competence up there: this is objectively a silly law that is damaging more the Internet, instead of improving it, where everyone simply agrees to surf so that nothing has been fixed.
Please do EU citizen a favor and drop this law ASAP, creating one that solves the problem instead of showing poor analysis and lack of common sense.
Thank You!

I also would like to understand how come most famous social networks, where tracking our activity is all they live on and sell, do not even bother with this, at least not from UK!