chrislynch.link

Code

WebAssembly 2.0 seeks to fix the gaps in current WebAssembly

I previously wrote about the excitement around WebAssembly and, having seen many technologies like this come and go in the past, my analysis of why WebAssembly might be a bad idea. In summary, it’s not that it is technologically bad – it’s simply that I don’t see a space for it in a world where computing power has been becoming thinner on the client-side for years and microprocessor prices are skyrocketing.

(And yes, I know that WebAssembly can also run on the edge of the server-side. So can a lot of things, so whilst it’s interesting I don’t see much of a point of it there either except where performance is paramount and computational cost is high).

The other thing I found odd about WebAssembly was the need to wrap it up in Javascript (which most of the time could do the job WebAssembly was being deployed for). So, I was interested to see the W3C updating the WebAssembly 2.0 specification with, amongst other things, an improved interface to Javascript.

In my original article, I predicted that Javascript isn’t going anywhere. Looks like the W3C agreed.

The new Web Assembly 2.0 specification can be found here:

WebAssembly remains a technology to watch, but I suspect mainstream adoption and market penetration will be difficult for it to achieve against stalwart web development platforms PHP and nodeJS.

Why I Think WebAssembly is a Bad Idea

If you haven’t discovered WebAssembly yet, it’s a pretty exciting technology that allows you to code in a range of languages (C++, Rust, and Typescript most notably) then compile your code into a WASM file that can run in all popular web browsers. Because the code is compiled it runs quickly and consistently across all devices. WebAssembly can’t render directly and has to rely on being called by and emitting Javascript to manipulate the DOM, but it still opens up some exciting options and introduces the potential to do things in the browser that we just can’t do right now like 3D games, heavy image manipulation, cryptography, etc.

Sounds pretty cool right? Well, that’s not all – a lot of big names are using WebAssembly including Disney+ and Shopify. There’s a growing list of projects using WebAssembly at https://madewithwebassembly.com/

So, if I’m telling you about a new way of writing code for the web that’s quicker, more portable, and lets you use the language of your choice… why do I think it’s a bad idea?

Well, we’ve been here before. More than once. We’ve been here with Java Applets. We’ve been here with ASP.net. And Flash. And Silverlight. In fact, it’s one of the negative patterns that we just don’t seem to be able to break in computer programming; we take a working client-server model and we try to make the client fatter and thicker and get it to do more heavy lifting. Then, after a while, we realize the error of our ways and we break things apart again.

We did it with the PC. We did it with the smartphone. We did it with wearables.

We just can’t stop trying to load more processing and activity into the client-side, a pattern that always ends up being reversed.

Yes, WebAssembly is good at “heavy lifting”

Here’s a great example of a project made better with WebAssembly. It’s a clever piece of software that helps researchers and scientists preview the quality of DNA sequence data. It needs to do some heavy lifting and moving this functionality out of Javascript and into WebAssembly brought some significant speed benefits to the application.

This doesn’t mean by default that WebAssembly is always faster than Javascript. Actually, if you’re not doing something computationally complex, the chances are good that WebAssembly will actually be slower than Javascript, like in these examples.

Now, I’m not criticizing the developers of this application, they’ve made something pretty impressive, but I’ve got to ask the obvious question… why do you need to number crunch DNA samples in a browser in Javascript in the first place? Personally, I wouldn’t do this on the client-side unless I absolutely had to… and I don’t have to.

But where you do your heavy lifting matters…

Let’s say I have an application that needs to do some audio manipulation. I want to do it in the browser as part of a larger software as a service application, so this is doable in Javascript but computationally intensive. I could get the data pushed up to my server and process it there, but that’s going to increase the load on my server so I’m going to need a bigger server or to set up my server to expand itself elastically as I need it. WebAssembly makes some sense here, because I can make the client do the work.

However, this makes the fundamental assumption that every client device has enough computing power to do what we want it to do. In a world where we have a shortage of microprocessors that is likely to last for another few years, increasing costs, and lower-powered devices (like Chromebooks) becoming more popular, why are we trying to push processing back on to clients again?

We did it when terminals became PCs, then moved everything to the web. We did it with smartphone apps, which we are now replacing with PWAs and single-page Javascript applications. We’re doing it with wearables and will inevitably flip back the other way there too.

Web Assembly for Serverless Computing

There’s a lot of buzz about “serverless computing” at the moment, but for me that doesn’t mean pushing processing back to the client-side. Serverless computing means running code in the cloud without having to invest in a whole server to do it. It’s about time-slicing a much bigger machine into much smaller increments than we currently do by allowing us to grab some resource on an “as we need it” basis from a large pool rather than ring-fence a chunk of resource and then waste it when we’re not using it.

Even an elastic server will waste resources, running at its smallest possible size while idle is still running. Serverless computing allows us to “scale to zero” – zero running costs when we are not running.

Cloudflare is one example of WebAssembly being used right – as a remotely executed, serverless piece of code. In this example, Cloudflare show some image resizing being done “at the edge” using a Cloudflare Worker. It’s quite neat, although in real terms doesn’t offer anything you couldn’t do with a simple server-side PHP script, Javascript file, or any other way.

The AutoCad web app is a far better example (although not as clearly explained as the Cloudflare proof of concept). Here, all the heavy lifting is done remotely so your system requirements are minimal. WebAssembly is a good choice for this as CAD is computationally expensive and has, historically, needed some beefy client-side hardware to run.

As a way of delivering more complex code and allowing it to run fast on a low-powered device, by leveraging external resources, this model makes sense and is scalable for the future. Moving complex processing client-side isn’t a good idea, unless you absolutely have to.

Mostly, it comes down to bandwidth

One of the things that people say that they want to do with WebAssembly is make games that run quickly in the browser. Sounds cool… except we already have this, and it’s called Stadia. Stadia is Google’s streaming games platform, an environment where the game (the heavy lifting) runs remotely and streams the video and audio to your computer. Stadia makes it possible to run even incredibly complex and resource-hungry games, such as Cyberpunk 2077, on relatively lower-powered hardware (like my four-year Chromebook). I don’t care how fast WebAssembly might think it is, but when the game recommends a $400 graphics card as its minimum spec, that game is not running in a browser on a Chrombook. Ever.

The only obstacle to improving the performance of server-side computing of this sort is bandwidth and this is one area of computing where we still see exponential improvement in capacity coupled with falling prices. (And yes, there is such a thing as 6G…)

Should I use Web Assembly?

If I haven’t made it clear enough yet, there’s one good use case for WebAssembly right now and that’s if you’ve got heavy lifting to do. The other oft-touted reason to use WebAssembly is that it lets you write in a wider variety of languages than you currently can for the web. Sadly, this is a lie… and not a very useful one.

Webpages are written in HTML, CSS, and Javascript. With WebAssembly they still are – you’re just calling an external WASM using your Javascript and then handling the output it gives you, manipulating the DOM, etc. So, if you don’t know HTML, CSS, and Javascript and you’re thinking WebAssembly will save you by letting you carry on programming in FORTRAN or whatever… forget it. WebAssembly doesn’t do that.

Also, what is our obsession with trying to program for the web in old languages? There’s a reason that your toolbox at home contains more than one tool. It’s because different tools are good for different things. The same is true of programming languages. If you’re so desperate to write code for the web in FORTRAN though? Have at it – just build a HTTP server in FORTRAN and then write server-side code to your heart’s content. That’s the point of writing server-side code; it doesn’t matter what language you write your code in, I’m only ever going to see the output (which will be in HTML, CSS, and Javascript).

What’s the future for WebAssembly?

I’m old enough to remember when all websites were going to be replaced by Java applets. It didn’t happen. The general web as we know it is not going to be rewritten in WebAssembly any time soon, nor are technologies like Javascript (which is hugely popular right now) going to go down without a fight.

Everyone said node.js would kill PHP. As of January 2022, PHP still runs 77.8% of the web.

Wide-scale WebAssembly adoption is a long-way off and it would not surprise me one bit if Javascript found a way to surpass the speed benefits of WASM before the new technology can really find its feet.

Get correct UK time in PHP on Windows (including daylight savings time)

When running on Windows, PHP’s timezones don’t always play nicely with the Windows implementation of daylight savings time (DST). The code below is an easy workaround to this; simple use date("I") to work out if it is summer or not and combine this with date() and strtotime() to get the spot-on time including your GMT offset.

For the UK the DST offset is 1 hour, so the following works perfectly:

date('Y-m-d H:i:s',strtotime('-' . date("I") . 'hours'))

Run code-server with Apache

code-server is nothing short of amazing. A fully-fledged VSCode environment running in a browser means I can jump from one machine to another, including my beloved Pixelbook, with full access to my development environment and toolset. After months of subscribing to services like Codeanywhere, CodeTasty, replacing this with something under my control (and costing me not a red cent) is pretty cool.

That’s not to say setting it up is easy, especially if you tend to throw all your development skunk-works type activity onto one disposable server as I do. One particular problem is running the system securely over SSL when you already have a web server, like Apache, running on the device.

Keeping Code-Server secure when running remotely

If you’re going to run code-server and make it accessible remotely, you want to do that over SSL. The risks of losing control of your development environment are too great otherwise. The easiest way to do this, in my opinion, is with caddy. Caddy is a web server written in Go that, very handily, grabs an SSL certificate for you when you need it and takes care of your SSL needs. Caddy can create a reverse proxy to code-server, letting you access it over SSL on port 443 easily even though it is really running on some other port internally.

The problem with this is that Caddy needs to be running on port 80 and port 443 to perform its SSL magic and it needs to be able to respond to a reverse-lookup from Let’s Encrypt to get an SSL certificate. This means you can’t be running Apache (or any other web server) on those ports.

Caveat: Yes, you can run code-server remotely this quicker and cheaper, but where’s the fun in that?

If you want to keep things simple, you can of course just spin up an extra image on your cloud host of choice and use one of code-server’s really handy cloud images to install your code-server instance. No fuss, no muss. You don’t have to put all your stuff on one machine and it’s probably advisable not to in a lot of scenarios. However, if you (like me) need, or just want, to run everything off one device then this post will show you do it…


If you don’t already have SSL certificates for your domain, get them

This method won’t work if you’re accessing your server by its IP (or it might, I just haven’t tried).

Use LetsEncrypt to get your domain a certificate if you don’t already have one.

Install Code Server

Install code-server exactly as described by code-server themselves. Trust them, they’re the experts.

Don’t run it yet though, you’re going to make some changes to the config file

Install Caddy

Install Caddy as per the instructions here but (like code-server)… don’t run it yet!

Now, start editing your config files…

code-server config

code server needs to be configured to require no password to access it (Caddy will handle authentication) and use no SSL (Caddy will handle that too)

It doesn’t matter what port code server runs on, as long as it’s a free port, but pay attention to the port as you will need it later.

My code-server config looks like this:

bind-addr: 127.0.0.1:8080
auth: none
cert: false

Caddy config

Caddy needs to be told to

  1. Run on non-standard ports for HTTP and HTTPS.
  2. Use the SSL certificates you already have (see above) rather than try to generate its own
  3. Run a reverse proxy to code server
  4. Require HTTPS authentication to allow access

My Caddy file looks like this:

{
        http_port 9080
        https_port 9443
}

mydomain:9999 {

        basicauth * {
                username passwordhash
        }
        reverse_proxy 127.0.0.1:8080
        tls /path/to/ssl/file /path/to/ssl/key

}

Replace mydomain:9999 with your domain and the port you want to run on.

Replace username and passwordhash with a username and password hash (you can generate a password hash here).

Replace the /path/to/ssl/file and /path/to/ssl/key with paths to the relevant files on your machine. If you generated these with LetsEncrypt and you’re using Apache, like me, you will find these in the configuration file for the domain itself.

Firewall config

It’s unlikely that the ports you picked for Caddy are going to be open on your firewall. (If they are, they probably belong to something already or your firewall config is leaky). You need to ensure that the SSL port Caddy is running on is able to accept inbound connections. You may choose to lock this down to known IP addresses if you have fixed IP addresses that you are going to be remotely accessing the system from.

You’re good to go

Start the code-server service and, once it is running, start Caddy.

code-server &
caddy start

You should be able to connect remotely to your development environment at https://[your-domain]:[caddy-ssl-port]

You will be prompted for the password you configured in the Caddy file (above) – get it right and you should see your remotely accessible code-server in your browser.

Find Biggest Files and Directories on Linux

Here’s a handy command for tracking down which part of your file system has the largest files in Linux.

du -a / | sort -n -r | head -n 5

Linux can be a tricky beast sometimes and it only takes one rogue process, one giant log file, or one run away user upload to eat your disc and bring the server to a grinding halt.

To check how you’re doing for disc space, you can check

df -h

Monitor MySQL Processes at the Command Line

Here are two ways you can get a rolling view on MySQL processes from the Linux command line.

mysqladmin

mysqladmin -u root -p -i 1 processlist

Replace root in the above example with your MySQL username and, after giving your password when prompted, you will see the processlist being output over and over again on screen.

You can pipe the output of this process into a file or any other command line utility.

watch & mysql

It’s also possible to use the command watch to run the processlist command over and over again, but you will need to enter your password into the command line itself to do this, which is insecure.

watch 'mysql -u root --password=rootpassword -e "show processlist"'

This will use the watch command to run the processlist command over and over again. This gives a slightly nicer output to screen in my opinion, but does include a warning about the risks of putting your password into the commandline!

Search Anything with JQuery

Here’s a quick set of functions to search a table, search a list, search paragraphs of text, or search just about anything on a page with JQuery.

The key to making this work effectively is adding the datasearch property to the items being searched and ensuring that your JQuery selector is unique to the set of items you want to search.

function runQuickSearch(searchBox, searchTarget){
    var search = jQuery(searchBox).val().toLowerCase();
    var found = false;
    jQuery(searchTarget).each(function() {
      found = false;
      searchValue = jQuery(this).data('search').toLowerCase();
      if (searchValue.indexOf(search) >= 0 || search.len == 0 ) {
        found = true;
      }
      if (found) { jQuery(this).show(); } else { jQuery(this).hide(); }
    });
  }
                              
  function quickSearch(searchBox, searchTarget){
    jQuery(searchBox).click(function() {
      runQuickSearch(searchBox, searchTarget);
    });

    jQuery(searchBox).keyup(function() {
      runQuickSearch(searchBox, searchTarget);
    });
  }
                              

How to link a search box with the items to be searched

The code below will link the text box #search with the rows of a table with the id #customers. To ensure that the headers don’t get removed, ensure your data rows are inside a <tbody> tag.

jQuery(document).ready(function(){
   quickSearch('#search','#customers tbody tr');
});

Responsive Lazy Loading

Lazy loading, a web development that holds off on loading images until they are needed, is a great way to speed up your website. When the user doesn’t have to wait for all of your images to load, they get a quicker response time and an improved experience.

There are lots of lazy loading libraries out there, but I couldn’t find one that went the extra mile and also downsized images so that they were no bigger than they needed to be.

Libraries like Bootstrap are great at making sure images fit into the space required of them with classes like img-fluid. But, a 1024×1024 image is still a 1024×1024 image even if it is being squeezed down to 300×300 by the browser. The net effect of this is that the user is downloading a much bigger file than they need, wasting bandwidth and time.

The solution? Responsive sized Lazy Loading.

Glazy: A Responsive Lazy Loading Function

function glazyload(){
  $('img.glazy').each(function(){
    img = '';
    if($(this).data('img')){
      img = $(this).data('img').toString().trim();
    }
    if(img == ''){
      img = 'placeholder.jpg';
    }

    width = $(this).parent().width();
    minwidth = $(this).data('imgminwidth');

    if(width == 0){ width = $(this).parent().parent().width(); }
    if(width < minwidth){ width = minwidth; }
    if(width == 0){ width = 600; }

    $(this).attr('src','image.php?imagefile=' + img + '&resizetoWidth=' + width);
  });
}

$(document).ready(function(){
  // setTimeout(function(){glazyload();},2000);
  glazyload();
});

How does it work?

Images should initially be set up with a blank src parameter (or pointed to a very small placeholder image) and the class “glazy”. The path to the original version of the image should be data in the data-img parameter. An optional data-imgminwidth can be supplied to provide a minimum width for the image should glazy have a problem working out how big the image should be.

<img src="uploads/placeholder.gif" data-src='uploads/mypic.jpg" data-imgminwidth="300" class="glazy">

When the webpage has been loaded, the glazy() functional will be called automatically. This function will:

  1. Find every image with the class “glazy”
  2. Work out how large this image should be based the width of its parent.
  3. If the parent is an <a> tag, or something else without a width, the width of the grandparent element will be used.
  4. If no width is found, the width will be set to the minimum width specified for the image or, failing that, a fallback hardcoded into the function
  5. Replace the src parameter of the img tag in question with a pointer to an image resizing script, passing the source image and a target width

I use my own homebrewed image.php file to do resizing, you should be able to do just as well with something like TimThumb on PHP or whatever the equivalent is for your platform.

Bootstrap 4 CSS Breakpoints

Ever wondered exactly what the breakpoints are the Bootstrap 4 media queries? Well, wonder no more!

Bootstrap 4 breakpoints
*/
 
/* 
Extra small devices (portrait phones, less than 576px) 
No media query since this is the default in Bootstrap because it is "mobile first"
*/
 
 
/* Small devices (landscape phones, 576px and up) */
@media (min-width: 576px) {  
 
}
 
/* Medium devices (tablets, 768px and up) The navbar toggle appears at this breakpoint */
@media (min-width: 768px) {  
 
}
 
/* Large devices (desktops, 992px and up) */
@media (min-width: 992px) { 
 
}
 
/* Extra large devices (large desktops, 1200px and up) */
@media (min-width: 1200px) {  
    
}

Obviously you can create your own media queries using these as a template. Swap min-width for max-width if you want to create rules that apply “up to” a certain screen width.

Perform a Colour Swap using JQuery

Want to perform a quick, temporary, colour change on a website? Maybe you want to see what you blog theme would look like with a different colourway but don’t want to edit line after line of CSS?

Here’s a cheeky little block of JQuery that can do just that by seeking out every element that has a particular colour, or background colour, set and replacing that colour with something else.

When you get the colour of an element in JQuery it comes back in rgb format, but you can set it using rgb, hex, or just a good old fashioned colour name. Don’t forget to tweak the color if you’re changing the background colour.

Script to change all colours using JQuery

<script>
jQuery(document).ready(function(){
	console.log("Changing colours");
	jQuery("*").each(function(){
		if(jQuery(this).css('color') == 'rgb(255, 221, 34)'){
			jQuery(this).css('color','#1C4C8D');
		}
		if(jQuery(this).css('background-color') == 'rgb(255, 221, 34)'){
			jQuery(this).css('background-color','#1C4C8D');
			jQuery(this).css('color','white');
		}
		if(jQuery(this).css('background') == 'rgb(255, 221, 34)'){
			jQuery(this).css('background','#1C4C8D');
			jQuery(this).css('color','white');
		}
		if(jQuery(this).css('border-color') == 'rgb(255, 221, 34)'){
			jQuery(this).css('border-color','#1C4C8D');
		}
	});
});
</script>

How does this script to change all colours work?

The script is pretty simple – first it gets every element on the page using the JQuery global selector “*”. Then, it simply loops through all of these looking for the offending colour and changing it.

This is not a fast option and certainly not the best way to do this – if you want to make the colour change permanent then you should update your CSS. However, for trying out global colour changes on a site where the colour codes are in multiple places in the CSS, it’s a quick and easy way to see how your site would look with a different colour.