LoDash: isBlank and isPresent mixins

When you need to check a value for presence, don't rely on JavaScript since it considers 0 or "0" false. Also don't rely on LoDash's _.isEmpty:

if ('0') { ... } // false
if (0) { ... } // false
if (!_.isEmpty('0')) { ... } // true (= good)
if (!_.isEmpty(0)) { ... } // false (= not good)

This is because isEmpty it is only meant for objects with a length.

While the name implies that it's meant only for collections, you probably still want something like isBlank or `is…


Using regular expressions in JavaScript

Regular expressions in Javascript are represented by a RegExp object. There also is a regex literal as in many other languages: /regex/. However, they are used slightly differently.

Regex literal

  • Usage: /foo+/
  • Shorthand for creating a regular expression object

RegExp() object

  • Usage: Regexp("foo+") or new RegExp("foo+")
  • No surrounding slashes required (they're the literal markers)
  • Since the argument is a string, backslashes need to be escaped as well: RegExp("\\d+")


  • Regex objects [never eq…

Some hints on upgrading to Unpoly 0.60.0

Unpoly 0.60.0 removed the jQuery dependency to improve performance (see Hennings talk about Javascript without jQuery). I upgraded one of our applications which used a lot of JavaScript with Unpoly compilers and jQuery and want to mention some aspects I had trouble with:

Use up.$compiler as a first step

up.compiler now yields a native DOM element instead of jQuery element. In order to get the old behavior, use up.$compiler. This is u…


Events triggered by jQuery cannot be observed by native event listeners

jQuery has a function $.fn.trigger(). You can use it to dispatch an event on a jQuery object:

let $element = $('.foo')

A caveat is that such an event will be received by jQuery event listeners, but not by native event listeners:

let $element = $('.foo')

$element.on('change', event => console.log('I will be called'))
$element[0].addEventListener('change', event => console.log('I WON'T be called'))


This is currently a WONTFIX for jQuery (see c…

How to: Migrate from CoffeeScript to ES6

It is quite easy to migrate from CoffeeScript to ES6. You can use decaffeinate to convert your CoffeeScript source to modern JavaScript.


  • Install the NPM module globally yarn global add decaffeinate
  • Add the following line to your ~/.bashrc to export the Yarn binaries in your Bash
export PATH="$PATH:$(yarn global bin)"
  • Run decaffeinate to get the converted modern JavaScript file.


  • decaffeinate will add some [suggestions](https://gith…

Webpack: Automatically generating an icon font from .svg files

Over the years we have tried several solution to have vector icons in our applications. There are many ways to achieve this, from SVGs inlined into the HTML, SVGs inlined in CSS, JavaScript-based solutions, to icon fonts.

Out of all these options, the tried and true icon font seems to have the most advantages, since

  • icon fonts are supported everywhere
  • they perform well and require no JavaScript at all
  • their icons align nicely with text
  • their icons automatically inherit color and size of the surrounding text

The big issue used to b…

Webpack: How to split your bundles

To keep JavaScript sources small, it can sometimes make sense to split your webpack bundles. For example, if your website uses some large JavaScript library – say TinyMCE – which is only required on some select pages, it makes sense to only load that library when necessary.

In modern webpack this is easily doable by using the asynchronous import function.

Say we have an unpoly compiler that sets up TinyMCE like this (code is somewhat simplified):

// TinyMCE as part of the main bundle!

import tinymce from 'tinymce/tinymce'

// UI

Cucumber: Inspecting the Chrome download folder to test file downloads with Selenium

We already have some approaches on how to test file downloads withe selenium. Nonetheless here is another approach, which inspects the Chrome download folder. This way you do not need a separate logic on whether a file is served from a controller or a public path. The DownloadHelpers might also be re-used for reading e.g. a PDF file and checking its content.

Note: The step below will override a [spreewald step](https://gith…


Webpack(er): Analyze the size of your JavaScript components

We're always striving towards keeping our website's JavaScript as small as possible.

If you're using webpack(er), you can use the webpack-bundle-analyzer plugin to get a good overview, which of your JavaScript modules take up how much space, and where you can optimize.

To use it, add it via npm or yarn

yarn add webpack-bundle-analyzer

Then add this to your environment.js:

// Uncomment this code to show statistics of bundle sizes. Generated file will automatically o…

SameSite Cookies

The SameSite cookie attribute was first drafted in 2016. It defines under which circumstances a cookie should be sent to the server, putting cookies into three different classes:

SameSite variants


Send the cookie whenever a request is made to the cookie domain. A cookie without the SameSite attribute will currently be handled as if it was sent with SameSite=None.

Note: Googl…

Linked contentAuto-destruct in 24 days

Updated: Detecting when fonts are loaded via JavaScript

Card has been rewritten to include document.fonts.

Webpacker: Side effects of using window.* within the ProvidePlugin

Some older Node modules rely on window.jQuery to be present. One suggested solution is to use this config in the app/config/webpack/environment.js:

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.jQuery': 'jquery'

module.exports = environment

This will work. But a side effect is that the fo…

How to test Autoprefixer and CSSnext in PostCSS

PostCSS is a tool for transforming styles with JS plugins. In Webpacker you can configure the plugins and their settings via the postcss.config.js file.

module.exports = {
  plugins: [
      autoprefixer: {
        flexbox: 'no-2009'
      stage: 3

Note: Stage 3 means you can use all CSS features that are listed as "This idea is becoming part of the web". Do not use …


Speed up your websites: Put JavaScripts at bottom

For websites that don't do JavaScript rendering on the client, it's best practice to put script tags at the bottom of the HTML. This way, the page can start to render before scripts have been loaded and run.

The caveat is that you also have to move all other script tags from your views to the bottom of the page. This can be done with helpers.

How to implement

  1. Add the attached javascript_helper to your app.
  2. Move your `javascript_i…

Webpack: How to avoid multiple versions of jQuery

To avoid multiple versions of a package, you can manually maintain a resolutions section in your package.json. We recommend you to do this for packages like jQuery. Otherwise the jQuery library attached to window might not include the functions of your packages that depend on jQuery.

Note: This is only an issue in case you want to use a package functionality from window e.g. $(...).datepicker() from your dev console or any other javascript within the application.


By default yarn will create a folder node_modules

Linked contentRepeats

The developer console can do more than you think!

You can do so much more than console.log(...)! See the attached link for a great breakdown of what the developer console can give you.

Some of my favorites:

console.log takes many arguments

E.g. console.log("Current string:", string, "Current number:", 12)

E.g. console.log("Check out the current %o, it's great", location)


Migration from the Asset Pipeline to Webpacker

This is a short overview of things that are required to upgrade a project from the Asset Pipeline to Webpacker. Expect this upgrade to take a few days even the diff is quite small afterwards.


1. Find all libraries that are bundled with the asset pipeline. You can check the application.js and the application.css for require and import statements. The source of a library is most often a gem or a vendor directory.
2. Find an working example for each library in the application and write it down.
3. Find out the ver…

Linked contentRepeats

Debugging AJAX requests with better_errors

better_errors is an awesome gem for enhanced error pages in development, featuring a live-REPL for some light debugging.

To debug the exception you got on an AJAX-Request, visit /__better_errors on your app's root path (e.g. http://localhost:3000/__better_errors). It shows the error page for the last exception that occurred, even when it has been triggered by an AJAX request.

This website uses cookies to improve usability and analyze traffic.
Accept or learn more