/dev/nikc/blog

Kuolleiden purjehduskenkien seura

Sep 19th 2017

The day the .dev gTLD died

13:26

Few things are as "fun" as an untouched development environment rendered non-working after coming back from a week-long holiday. A brief but intense session of searching for the broken cog in the machine ensued, finally unveiling the issue; we use a .dev TLD in our local environments.

It turned out that on Sep 16th @lgarron added .dev to the static HSTS list1 in the Chromium project, forcibly telling the Chrome Canary2 browser to only request anything on a .dev website using https and only https.

While I'm a big fan of HSTS, the usefulness of the exercise eludes me, seeing how .dev isn't available for public consumption, but wholly reserved by Google for private use. (It could of course also be a sign that it's on its way into public use. Also, it really shouldn't have ever been assigned, but whatever.)

It could of course be just me (or us, really) who's clueless, as its use was "considered harmful" already in 2015.

1 chromium/src/net/http/transport_security_state_static.json

2 AFAIK the list is used by many browser vendors and thus other browsers are bound to follow suit at some point

Dec 8th 2015

Native CSS Variables Are Golden

12:38

If you read Philip Walton's blogpost Why I'm Excited About Native CSS Variables, you, just like me, would also be, or at least you should be, excited about native CSS Variables.

Until now I have been using postcss-custom-properties, but never before realised how much gold we're still missing out on when we can't utilise media queries, inheritance and the cascade in combination with CSS variables.

Native CSS variables today are available only in Firefox. They are under development for Chrome and Chrome Canary has them as an experimental feature1. IE Edge is considering them2. Safari seems to have some interest and is showing recent related work but the feature is absent from the WebKit Feature Status page. Opera is keeping quiet.

The specification is currently at the Candidate Recommendation stage. Make your voice heard and wake up all the browser vendors.

1 Enable Experimental Web Platform features in Chrome by going to chrome://flags/#enable-experimental-web-platform-features and clicking the Enable link

2 Vote for CSS Variables at UserVoice

3 Cleanroom implement Custom Properties

Shorts

  • A consequence of easily installable modules is that they inadvertently eat up quite a bit of disk space. Using find and du it's easy to find the biggest culprits:

    find $PROJECTS_HOME -name "node_modules" -prune -exec du -sh {} \;

    (0) #

Sep 3rd 2015

Complement Git Stash With Commit And Soft Reset

11:01

One of my favourite Git tools is the stash. However, it doesn't always quite fit the bill. E.g. you notice you need to amend a commit in your history, but stashing everything would lead to solving umpteen unrelated conflicts during a rebase update. Instead I like to store everything irrelevant for the amend as a stash-commit, then stash what I need to bring along.

The Three Step Workflow

  1. git commit -am "stash", i.e. commit everything (you want to stash) into a stash-commit
  2. do your work, usually involves rebasing and/or working in other branches
  3. git reset HEAD^, i.e. reverse the stash-commit from stage 1

Stash Can Do That

The same effect (or very similar) can be achieved with stash save --patch, but I find a stash-commit is often quicker and simpler. Personally, I also like that my stash-commit remains in the branch, whereas stashes are global.

Stashes are also much too easy to forget, and even if you have the option to name them when using stash save, I rarely do, which leads to not remembering what's been stashed if it's more than minutes ago.

Shorts

May 4th 2015

URLs Need Due Diligence

11:25

Considering how central the URL is to the World Wide Web, it should really be blatantly obvious that it needs proper attention during the design process of any new website. It's not always easy, and I for one have certainly at times been guilty of poor URL design, but making changes later can be a tall mountain to climb.

URL Design is a complex subject. I can’t say there are any "right" solutions — it’s much like the rest of design. There's good URL design, there’s bad URL design, and there’s everything in between — it’s subjective.

URL Design

What I especially liked in the article is the notion that URLs are for humans. SEO is useful, not the least because it employs a whole industry, but really the human you're trying to attract to your website should always be at the centre. But all other things aside, the absolute most important attribute about a URL, is and always has been is that it works, and that it keeps on working.

What makes a cool URI?
A cool URI is one which does not change.
What sorts of URI change?
URIs don't change: people change them.

Cool URIs don't change

Having revisited older posts in this blog, it's unfortunate to see so many dead external links. Luckily there are projects like the Internet Archive that make internet archaeology possible.

So do the internet a favour: keep your URLs alive, and donate to the Internet Archive project to mitigate the consequences of dying URLs.

Shorts

Mar 5th 2015

Sujuvampaa kirjautumista mobiilissa

12:15

PA bloggaa mobiilisovelluksien sisäänkirjautumispoluista: Älä kompastu kynnykseen – 30 vinkkiä mobiilin sisäänkirjautumispolun suunnitteluun.

Vaikka juttu onkin suuntautunut natiiveihin sovelluksiin, on lähes kaikki käyttötapaukset sovellettavissa myös verkossa.

Feb 21st 2015

Host aliases and tab completion for SSH

13:02

Despite being a relentless tinkerer, for some bizarre reason instead of using the proper mechanics I've resorted to aliases for hosts I log in to frequently. Thankfully, the mental strain of remembering all the hosts I log in to finally forced me to sit down for 2 minutes and add the host + username combinations into my ssh-config. (Procrastination is such a beautiful word!)

Host freq
HostName some.long.hostname.that.i.need.frequently.com
User mysysadminassignedmethis

Configuration blocks like the example above shorten the full command to ssh freq from ssh mysysadminassignedmethis@some.long.hostname.that.i.need.frequently.com. Quite an improvement, I'm sure you'll agree.

However, since I did a proper job, naming things in a logical and consistent manner using patterns such as servicename-stg for the staging environment and servicename-prod for the corresponding live host, there was still quite a lot of typing to do. If you saw my post about tab completion for project folders you can probably guess where this is going.

As I now have all the relevant information in ~/.ssh/config it's very easy to parse out a helpful wordlist to create ssh tab completion. I have it and now you can have it, too.

Download ssh-complete.bash, source it from your ~/.bashrc and simply TAB away.

There are plenty of other useful things you can set in your ssh-config. See its man page for further information.

Shorts

Nov 10th 2014

Differential Syncing

16:57

For a personal project, I looked into the magical world of how to sync work from two or more peers on a single item, without anyone losing their work.

Thankfully, Neil Fraser has published a paper on Diff Strategies, Fuzzy Patching, and indeed Differential Synchronization. Even more thankfully, Google has open sourced a diff-match-patch library (ported to several popular programming languages) that does all the heavy lifting for you.

Most likely my personal project will never be finished to a point where it would be made public, but since I found this stuff interesting, I just thought I'd put this out there for others to enjoy.

Jul 19th 2014

Better tools for procrastination

14:20

I have a problem: the internet. Or rather the vast amount of interesting content being published versus the time and energy I have to consume it. I'll read an article here, bookmark an article there, but mostly I just open stuff in tabs in order to "read them later." And I know I'm not alone.

Currently, I have too many bookmarks to count both locally and in various cloud services, but more importantly around 80 tabs across 9 windows open. More importantly because those tabs and windows each use up a chunk of the finite RAM memory in my computer. As a result of this my computer almost constantly feels sluggish.

Now, I know the right course of action would be to address my behaviour. But who does the right thing?

In lieu of improving my judgment on what's truly worth my time and attention, I instead found a tool to help me with the immediate symptom: The Great Suspender.

The Great Suspender suspends a tab after a set timeout, unless it matches a white list, or on demand. Individual tabs or all tabs in a window can later be restored as needed.

What I really need is a plugin that will simply close unattended tabs after a period of time. Because, even though I really do revisit some of those postponed articles, many are just waiting to be bookmarked and forgotten about forever. Perhaps I'll add it to my ever growing list of hobby projects...

Dec 3rd 2013

Managing scrollTop in your Backbone single-page app

19:04

One of the great caveats of single-page apps is that they rely on taking over many of the browser's default behaviours. One of the more significant ones is how the browser behaves on page-to-page navigation, be it forwards or backwards. By default, the browser will take you to the top of the page when you navigate forwards by following a link. In contrast, you expect to be returned to the position on the page where you followed a link, when you use your browser's back-button.

In case you happen to be using Backbone to power your single-page app, this behaviour can be restored with very little effort and code. Unfortunately, this will only work in browsers supporting the History API, so old-IE (IE 9 and earlier) users are out of luck.

To pull it off, a global navigation event listener is used to store the current scrollTop just-in-time.

// A global a.onclick event handler for all your navigational needs
// see e.g. Backbone Boilerplate for a more complete example
$(document).on("click", "a", function (ev) {
    ev.preventDefault();

    // Replace current state before triggering the next route, 
    // storing the scrollTop in the state object
    history.replaceState(
        _.extend(history.state || {}, { 
            scrollTop: document.body.scrollTop || $(document).scrollTop() 
        }),
        document.title,
        window.location
    );

    Backbone.history.navigate(this.pathname, { trigger: true });
});

Listening to the route event from your Backbone.Router you then restore scrollTop when it exists in history.state, or default to page top. To catch navigation happening via the back- and forward-buttons in the browser, Backbone.history should be set up to listen for popState events by setting { pushState: true } in the options to Backbone.history.start().

// Backbone.Routers trigger the route-event
// after the route-handler is finished
var router = new AppRouter(); // AppRouter extends from Backbone.Router

router.on("route", function () {
    // Inspect history state for a scrollTop property,
    // otherwise default to scrollTop=0
    var scrollTop = history.state && history.state.scrollTop || 0;

    $("html,body").scrollTop(scrollTop);
});

For those who need to see before they believe, take a look at the demo.

NB. The code examples are simplified to the extreme and shouldn't be treated as complete drop in code.

Shorts

Meta

Pages

Search blog

Latest comments