Guidelines for building sustainable, robust & easily maintainable web apps

A few guidelines that I assembled during my career that keep me focused and help me move forward.

  • You must have a quick and comfortable dev env that allows you to stay focused
  • A solid foundation, that you control all of it’s aspects
  • a robust & simple as possible build process both for dev and prod
  • full control over your packages & manually update them when needed
  • utilize as less 3rd party packages as possible, as they might change with every update, and thus you are in less control.
  • don’t necessarily chase the cutting edge – it’s ok to not use the latest alpha release, as it quite often introduces unexpected behaviors.
  • build your own global components like dropdowns, buttons, popups, etc. it is usually a one time effort that pays well in the long run.
  • Strive for organized & standardized code, with self explaining clear structure that will allow easy onboarding for new and returning devs in your team
  • write small & self contained components
  • have a clear folder and file structure
  • use linters for forcing strict coding conventions
  • Customization of components has to be easy, with easy APIs
  • for css use SASS, it allows you to easily structure css, use variables for colors and sizes. mixins & extend for repeated css declarations
  • use importable config files & ENV variables to easily customize your app without digging in the code
  • Always think about performance – it’s too easy to fall into the trap of “I will do it later”. it will be hard to get back to it – plan your performance early
  • use image sprites, and always have the source files in hand. optimize your image assets, save for web & utilize various optimization tools
  • be aware of the browser limitations like maximum number of simultaneous http connections
  • master the browser loading times. what should be loaded in the head, at the bottom of the body, prefetch and lazy loading
  • CSS & Design matters. you should never neglect it. eventually it’s the face of the product, and if it’s broken – the user doesn’t care about the fancy complex stuff you craft in the backbone of your app.
  • Make sure to test it in variety of the browsers you support
  • Make clear style guidelines, and make sure to follow them
  • The designer is not always right. talk about quirks you find. usually after you have a solid css structure, your code dictates the small design cues, like consistent paddings & margins, color palettes and more…
  • Alway keep learning. technologies change every day, be ahead of it. but also know when to make a pause, not every buzzword is the future.

Remove untracked git files

To remove all untracked files & directories, you can use these commands:

  1. first list what is going to be removed, and verify what will be deleted:
    git clean -fdx -n
  2. after you verified what is going to be deleted, remove the -n flag:
    git clean -fdx

the flags we use here are:

  • -f force, in case your git config has the clean.requireForce variable
  • -x to remove both ignored & non ignored files
  • -d remove untracked directories as well
  • -n don’t remove anything, just list what will be deleted

Careers Page Finder – Save some time while job hunting

I’ve been on a job hunt recently, and that involved going through numerous interesting company websites – specifically their carriers/jobs pages :)

Usually the links to those pages appear somewhere in the footer, but sometimes they hide within a menu, or simply within the about text, or any other location that requires more than 3 seconds of your time to find…

So to save those valuable seconds, I’ve came up with an idea for a simple Chrome extension that allows you to go directly to those sneaky urls, and even mark urls that it didn’t match – so it can easily find those in your future searches as well.

I’ve published it to the Chrome Store, and you can download it here.
And it’s completely open source on Github.

Mocking AJAX responses by using a Media type string

When you want to test how your code handles API requests, or any AJAX requests – you will most likely find yourself in a situation where you don’t actually test the code responsible for the request, but just a “hardcoded” response that you provide in the code.

it might look like that:

if (testEnv) {
    doSomethingWithTheResponse({
        foo: 'bar'
    });
} else {
    $.get('/api/get_response_url').success(function(res) {
        doSomethingWithTheResponse(res)});
    }
}

in most cases it will do just fine – but what if there is a complex and crucial functionality within the .success callback?

the answer would be: Mock AJAX response while preserving the actual request code block. like this:

var url = '/api/get_response_url';

if (testEnv) {
    url = 'data:application/json,{"foo":"bar"}';
}

$.get(url).success(function(res) {
    doSomethingWithTheResponse(res);
});

in the above example we are setting the request url to be a media type string, which consists of:

  • top level type: data
  • type: application
  • subtype: json
  • parameters: {“foo”: “bar”}

you can read more about media types and their syntax here.

The request we do now returns what it has in the media type parameter – which is a completely valid, actual AJAX request with our mock response.

JavaScript events debugging with monitorEvents()

A fancy method to debug JS events, and log all or some of them.

simply call the monitorEvents() function in your JS console, and you will see the events flow.

monitorEvents(document.getElementById('monitor-me'), 'click');

monitorEvents

the first argument is the object to monitor, and the second argument is the optional filter. for example – show only click events.

to unbind the listener, you can use unmonitorEvents(document.getElementById(‘monitor-me’))

Maintain cursor position after changing an input value programatically

Sometimes you want to programatically change an input value, like in a case of input validation.
replacing an input value is easy, but has a common drawback – the cursor position will reset.

to overcome it, we can use this simple JS snippet:


function handleInputValueChange(e) {

    var cursorStart = e.target.selectionStart,
        cursorEnd = e.target.selectionEnd;

        // value manipulations...

    e.target.setSelectionRange(cursorStart, cursorEnd);
}

* note that this specific snippet relies on passing an event, onChange for instance.

setState not being updated on time

Say you have two functions in your React app that call setState(), and are dependant one on the other. you might stumble upon a case where the second function excepts to have the new state – but doesn’t.

That happens because setState() doesn’t immediately mutate the state (this.state) but creates a pending state transition. therefore, accessing this.state might return the existing value.

to overcome this, this.setState supports a callback function to be triggered once it’s been updated.

this.setState(newStateObj, () => {});