Keeping web applications fast
Our applications not only need to be functional, they need to be fast.
But, to quote Donald Knuth,
premature optimization is the root of all evil (or at least most of it) in programming
The reasoning is that you should not waste your time optimizing code where it does not even matter. However, I believe there are some kinds of optimizations you should do right away, because
- they are either obvious and easy
- or they are very hard to do optimize later
This is an attempt to list some of those things:
On the server
...
Escape a string for transportation in a URL
To safely transport an arbitrary string within a URL, you need to percent-encode characters that have a particular meaning in URLs, like &
or =
.
If you are using Rails URL helpers like movies_path(:query => ARBITRARY_STRING_HERE)
, Rails will take care of the encoding for you. If you are building URLs manually, you need to follow this guide.
Ruby
In Ruby, use CGI.escape
:
# ✅ good
CGI.escape('foo=foo&bar=bar')
=> "foo%3Dfoo%26bar%3Dbar"
Do not ever use `URI.en...
Improving browser rendering performance
As the web is being used for more and more tasks, expectations rise. Not only should web pages offer rich interaction, they must be responsive in both size and interaction.
This imposes a paradoxon that needs to be solved by building performing applications. It's not enough any more to have your web site do crazy stuff, it is also required to do it crazy fast. This card is intended to give you an introduction to this emerging aspect of web development.
Read this introductory [performance study on Pinterest](http://www.smashingmagazine.com/...
Installing Node.js / npm under Ubuntu with nvm (with yarn)
I recommend install Node.js using nvm. This way you can have multiple Node versions in your ~/.nvm
. You also won't need to install global packages with sudo
anymore.
Node via nvm will automatically bring npm. yarn will automatically be available if corepack is enabled for node.
Installing nvm
DigitalOcean has a HOWTO for installing nvm on Ubuntu (16.04, [18.04](https://www.digitalocean.com/community/tutorials/how-to-...
Migrating legacy jQuery code to .on() and .off()
If you need to upgrade code that uses the old jQuery methods bind
, delegate
, live
, unbind
and die
, the attached article has examples how to migrate to the new on
and off
versions.
Bootstrap 4 is coming
What's new
- Moved from Less to Sass. Bootstrap now compiles faster than ever thanks to Libsass, and we join an increasingly large community of Sass developers.
-
Improved grid system. We’ve added a new grid tier to better target mobile devices and completely overhauled our semantic mixins.
Opt-in flexbox support is here. The future is now—switch a boolean variable and recompile your CSS to take advantage of a flexbox-based grid system and components. - Dropped wells, thumbnails, and panels for cards. Cards are a brand new co...
Flash-Free Clipboard for the Web
Unfortunately, Web APIs haven’t provided the functionality to copy text to the clipboard through JavaScript, which is why visiting GitHub with Flash disabled shows an ugly grey box where the button is supposed to be. Fortunately, we have a solution. The editor APIs provide document.execCommand as an entry point for executing editor commands. The "copy" and cut" commands have previously been disabled for web pages, but with Firefox 41, which is currently in Beta, and slated to move to release in mid-September, it is becoming available to Ja...
include_tags with the asset pipeline
You can include files from app/assets
or from the public
folder with javascript_include_tag
. The subtle difference that tells rails how to build the path correctly is a single slash at the beginning of the path:
<%= javascript_include_tag('ckeditor/config') %> # for assets/ckeditor/config.js
<%= javascript_include_tag('/ckeditor/ckeditor') %> # for public/ckeditor/ckeditor.js
This also applies to stylesheet_link_tag
.
Note that when you refer to a Javascript or stylesheet in /assets
you need to add it to [the list of asse...
Bootswatch: Paper
Free Bootstrap theme resembling Material Design.
Bootswatch offers Sass and Less files, so the theme can easily be integrated into your usual Rails application.
Implements only Bootstrap features which means that some Material stuff is missing, but also that you can easily use or replace the theme.
Does not come with extra JavaScript; some effects like button click ripples are implemented via CSS.
Also check out their other themes which can be used in a similar fashion.
Jasmine: Testing complex types for equality
Jasmine comes with two matchers that test for equality. The first is toBe
:
expect(first).toBe(second)
toBe
passes when first === second
. Unfortunately this is useless for non-primitive values because JavaScript is a horrible language.
However, Jasmine comes with another matcher toEqual
:
expect(first).toEqual(second)
This matcher behaves as a human would expect for types like the following:
- Arrays
- Objects
- Nested array/object constructs
- Regular expressions...
Mocking time in Jasmine specs
The easiest way to freeze or travel through time in a Jasmine spec is to use the built-in jasmine.clock()
.
- After
jasmine.clock().install()
you can use it to controlsetTimeout
andsetInterval
. - Using
jasmine.clock().mockDate()
you can mocknew Date()
(which returns the current time in Javascript)
While you can use SinonJS Fake timers, using the built-in Jasmine clock will save you an extra dependency.
Pierce through Javascript closures and access private symbols
If you are writing any amount of Javascript, you are probably using closures to hide local state, e.g. to have private methods.
In tests you may find it necessary to inspect a variable that is hidden behind a closure, or to mock a private method using Jasmine spies.
You can use the attached Knife
helper to punch a hole into your closure, through which you can read, write or mock local symbols:
klass = (->
privateVariable = 0
privateMethod = ->
...
JavaScript events: target vs currentTarget
tl;dr: Use event.currentTarget
unless you are absolutely certain that you need event.target
.
Since it hasn't been written down in this deck before, here it goes:
When working with JavaScript Event
objects, the DOM element that triggered the event is attached to them. [1]
However, there are 2 "opinions" on which element that would be:
- The element that the user interacted with (
event.target
), - or the element that the event listener is bound to (
event.currentTarget
).
Note that both can be, but not...
Material Design Lite
CSS (+ some Javascript) framework, implementing Google's material design for static web pages.
Can be used for plain websites without requiring a full blown Javascript framework, unlike the (also excellent) Polymer paper elements, or Angular material.
Prelimiary impression:
I would recommend against using it at this stage, for a couple of reasons:
- It is much less complete than you might expect from a CSS framewor...
How to disable auto-complete on login forms
Disabling auto-complete in login forms is probably a bad idea, since it encourages weak passwords.
If you are still forced to implement this (maybe due to legal or policy requirements), this is how:
Prevent browsers from saving the password in the first place. Disabling autocomplete does not improve security.
How to prevent password saving:
To prevent the browser from saving passwords (and usernames), you need to:
- copy username and password to hidden form fields before submitting the login form
- c...
SmartUnderline
SmartUnderline is an open-source JavaScript library which uses clever tricks to draw underlines in a more beautiful and readable way.
We've not yet put this into a project, but its effect is very pretty. Please update this card when you use it.
Copy & Paste & The Web | CSS-Tricks
Insanely detailled guide about controlling copy & paste behavior using web technology in 2015.
Note that you can now trigger a copy action through Javascript, no Flash required.
Testing regular expressions visually
Developing complex regular expressions quickly blows my mind. Here are some online regex editors that help you by highlighting matching text and capture groups:
- Ruby:
- Javascript:
Reverse-proxying web applications with Apache 2.4+
Note: Making a reverse proxy with nginx is much more straightforward.
A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:
- Expose a local service that you cannot directly reach over the internet
- "Change" the domain or path of a web application by rewriting them on the fly
- Instantly change servers that respond to a name or ...
Manually trigger a delegated DOM event
When you register a delegated event using on
(or the deprecated delegate
/ live
), it is somewhat hard to manually trigger these events manually, e.g. for testing.
After trying jQuery's trigger
to no avail, I had success by using native Javascript methods to create and dispatch an event. For instance, to trigger a mousedown
event:
element = $('...').get(0);
event = new MouseEvent('mousedown', { view: window, cancelable: true, bubbles: true }...
sessionStorage: Per-window browser storage
All major browsers (IE8+, FF3.5+, Safari 4+, any Chrome) support sessionStorage
, a JavaScript storage object that
- survives page reloads and browser restores,
- but is different per new tab/window (in contrast to
localStorage
which is shared across all tabs).
MDN says:
The
sessionStorage
object is most useful for hanging on to temporary data that should be saved and restored if the browser is accidentally refreshed
Demo
Example usage:
Customizable date (and time) picker: Rome
Datetime picker that offers:
- simple UI without a specific framework
- several of customization options
- allows custom date/time validations
Localization happens via moment.js (which is a Dependency anyway).
However, you won't be happy trying to customize it too much:
- It does not support full custom templates, you can only set classes of its elements. If you require extra containers, you are out of luck.
- It offers only a few events, and you can not distinguish if users pick a date, switch to another month, or click outside of the p...