Hi. I’m Dustin. I’m a creative and curious Sr. Frontend Engineer at True Anomaly in Los Angeles, CA. I spe­cial­ize in front-end web de­vel­op­ment with Ja­va­Script, React, and Node.js. You can also find me on GitHub and LinkedIn.

  • Packaging JS Apps with QuickJS

    QuickJS is a tiny JavaScript engine written in C. Its author, Fabrice Bellard, created FFMPEG and QEMU. QuickJS can run outside of traditional browser environments. This includes packaging JavaScript applications for distribution.

    As of writing, QuickJS supports ECMAScript 2023, so you can write modern JavaScript. It is also fast and well-tested.

    One of the engine’s features is compiling JavaScript code into bytecode. Bytecode is a compact set of instructions that an interpreter can execute. It makes execution more efficient, which is perfect where performance is important. Additionally, the engine supports compilation of JavaScript into dependency-free standalone executables. We will use this feature to package JavaScript apps.

    QuickJS’s small footprint is also suitable for embedded systems and resource-constrained environments.

    Recently, Amazon announced its Low Latency Runtime (LLRT), built on QuickJS. According to Amazon, LLRT starts 10x faster and is 2x less expensive than other JS runtimes on AWS Lambda. That’s a pretty impressive use case.

    Installation

    Installing QuickJS in your development environment is straightforward. Here’s how to get started. Note that on Windows, you can use WSL with Linux.

    Before jumping in, make sure you have Make and a C compiler like GCC or Clang.

    The first step is to get a copy of the source code. You can download the source from the QuickJS website or by cloning it from the GitHub repository. We’ll download it from the website and untar the file:

    wget https://bellard.org/quickjs/quickjs-2024-01-13.tar.xz
    tar -xJf quickjs-2024-01-13.tar.xz

    This command creates the directory quickjs-2024-01-13 with all the necessary source files. I’ll refer to this directory as quickjs from now on.

    Compatibility

    QuickJS does not rely on V8, WebKit, or Gecko. It is not compatible with NodeJS or Deno APIs. It does have access to the OS through its own APIs. To make sure your code is compatible with QuickJS, ensure the following:

    • Your code uses ECMAScript 2023 or lower
    • You are not using browser-specific APIs
    • You are not using Node.js or Deno-specific APIs

    QuickJS focuses on the core JavaScript language, so your code should be platform-agnostic.

    Organization

    For this simple Hello World app we’re putting our files into the quickjs directory. In a business context, you should keep your code separate from QuickJS. Otherwise, you can structure your project as you would any other JavaScript project. You can even use modules.

    Building QuickJS

    Once you have the source code, the next step is to compile it. This will convert the code into an executable you can run on your computer. Navigate to the quickjs directory with cd quickjs.

    Finally, compile the source with the make command. QuickJS’s Makefile will detect your OS and choose the appropriate compiler and flags. Run:

    make

    On macOS, Make will use Clang as the default compiler, whereas on Linux, GCC is more common. Compilation will take a few moments. Once completed, several new files will be added to the quickjs directory. qjs is the command-line tool for executing JavaScript files. qjsc is a tool for compiling JavaScript into bytecode.

    Testing QuickJS

    You can run a simple JavaScript file to verify your installation. Create a file named hello.js with the following code:

    console.log("Hello, QuickJS!");

    Save the file into the quickjs directory and then execute it using the qjs binary:

    ./qjs hello.js

    If QuickJS installed, you will see the message “Hello, QuickJS!” Now you have QuickJS set up and ready, it’s time to package an application.

    Packaging JavaScript

    To create a standalone executable, use the qjsc executable in the quickjs directory. You can execute it with these commands:

    qjsc -o hello hello.js
    ./hello

    If it works, you will see “Hello, QuickJS!” on your terminal. This is the file that we will distribute.

    There are many flags that you can pass to qjsc. Try experimenting with each. For example, output bytecode instead of an executable. Or disable regular expressions to decrease binary size.

    Package Size

    The executable for this “Hello, World!” example is 4.6 MB. It may seem large for such a simple program. However, consider the alternatives. Using deno compile I get an executable that is 76 MB. Compiling the hello.js file using Node 21 produces a 98 MB file. So, In perspective 4.6 MB seems pretty good.

    Distribution

    You don’t need anything special to distribute a QuickJS-packaged application. Using the standalone executables, you have a range of distribution options.

    QuickJS is portable. That means that it can run in many environments. When preparing for distribution, consider the target platforms. If you want your application to work on Windows, macOS, and Linux, you must build the app on each system.

    Closing Thoughts

    Whether you’re developing IoT devices or building server-side tools QuickJS is a stellar option. It’s easy to use, fast, and produces relatively tiny executables.

    Try experimenting with it, push its boundaries, and see how it can be used in your projects. What has your experience with QuickJS been? I’d love to hear your stories, successes, and lessons learned.

  • Pure Scrum

    Scrum is a simple approach to software development based on Agile. I have been using some form of Scrum, at least personally, since the mid-2000’s when I learned about Extreme Programming, then Test Driven Development, Agile, Gherkin, Behavior Driven Development, actual Scrum, and the Scaled Agile Framework. It’s safe to say that I have picked up a lot of non-Scrum practices along the way, and while they are not necessarily bad, they aren’t necessarily Scrum. So I thought I’d write a bit about those little differences.

    Daily Scrum

    Scrum calls Standups Daily Scrum. The mixup probably came from Extreme Programming which has a daily standup meeting. The typical Standup is focused on what each individual did yesterday, what they will do today, and whether anything is blocking them from getting their work done. But that isn’t the only approach.

    A better approach might be to look at the Sprint Backlog to see how things are coming along, discussing the items as needed. I like this because it puts the emphasis on the product and the team, not the individual.

    Product Backlog Items

    User Stories in Extreme Programming are called Product Backlog Items in Scrum, and Scrum doesn’t care how you write them as long as they are defined with sufficient detail.

    That means that my beloved As a <role> I can <capability>, so that <receive benefit> format isn’t necessary, and neither are Scenarios as defined in BDD and enhanced with Cucumber’s Given... Then... When... syntax. Both of which I lurve.

    Events

    Ceremonies are just Events in Scrum. By the way, there are no gaps between Sprints which means that all Events take place during a Sprint.

    • Sprints can last up to a month
    • Daily Scrum meetings are 15 minutes tops
    • Sprint Planning can last up to eight hours
    • Sprint Review up to four hours
    • Sprint Retrospectives are up to three hours

    That’s up to about 20 hours of meetings during a three week sprint. I can tell you from experience that, while it seems like a lot, it can really pay off.

    Sprint Review

    The Sprint Review isn’t supposed to be just a demo. It is supposed to be a collaborative working session with everyone on the team, including the stakeholders, to provide feedback on the product. The Product Backlog should be updated as a result of any feedback gathered during the session.

    It is also important that only releasable code is shown during the review. If it isn’t truly done, then it can’t be released, and therefore should not be part of the review.

    Roles

    There are three main roles in a Scrum team: Development Team, Product Owner, and Scrum Master. Scrum doesn’t prohibit the Develepment Team from interacting with the Product Owner, Stakeholders, or Customers (end-users), in fact, it encourages that kind of thing.

    Interestingly, Scrum seems to reduce the responsibilities of the Scrum Master to simply to helping the team understand Scrum and removing any impediments to the process. The Scrum Master does not “drive” the team by handing out tasks or telling people what to do.

    Scrum allows Scrum Masters and Product Owners to be on the Development Team, but it recommends against doing so because of conflicts of interest and high workloads.

    Development Team

    The Development Team consists of everyone who is doing the work of creating the product during a sprint. This includes but is not limited to, programmers, designers, marketing, writers, and researchers.

    Scrum stresses that the Development Team is completely self-organizing—only they can decide how to turn the backlog into functionality. It is also worth noting that the Development Team recognizes no titles or sub teams such as Lead Developer, Architect, or testing team. The whole team pitches in to complete the increment regardless of individual specialization.


    There are probably many other modifications to Scrum that I have picked up over the years, but these are the main ones that came up during training. I don’t think that these modifications are necessarily wrong—honestly I think many of them are awesome, but I have a natural bias toward systems and processes—they just aren’t Scrum, or “pure” Scrum.