Inertia 2.0 Released, Now Supports Asynchronous Requests

MMS Founder
MMS Bruno Couriol

The Inertia team recently released Inertia 2.0. New features include asynchronous requests, deferred props, prefetching, and polling. Asynchronous requests enable concurrency, lazy loading, and more.

In previous versions, Inertia requests were synchronous. Asynchronous requests now offer full support for asynchronous operations and concurrency. This in turn enables features such as lazy loading data on scroll, infinite scrolling, prefetching, polling, and more. Those features make the single-page application appear more interactive, responsive, and fast.

Link prefetching for instance improves the perceived performance of an application by fetching the data in the background before the user requests it. By default, Inertia will prefetch data for a page when the user hovers over the link after more than 75ms. By default, data is cached for 30 seconds before being evicted. Developers can customize it with the cacheFor property. Using Svelte, this would look as follows:

import { inertia } from '@inertiajs/svelte'

<a href="/users" use:inertia={{ prefetch: true, cacheFor: '1m' }}>Users</a>
<a href="/users" use:inertia={{ prefetch: true, cacheFor: '10s' }}>Users</a>
<a href="/users" use:inertia={{ prefetch: true, cacheFor: 5000 }}>Users</a>

Prefetching can also happen on mousedown, that is when the user has clicked on a link, but has not yet released the mouse button. Lastly, prefetching can also occur when a component is mounted.

Inertia 2.0 enables lazy loading data on scroll with the WhenVisible component, which under the hood uses the Intersection Observer API. The following code showcases a component that shows a fallback message while it is loading (examples written with Svelte 4):

<script>
    import { WhenVisible } from '@inertiajs/svelte'

    export let teams
    export let users
</script>


    <svelte:fragment slot="fallback">
        <div>Loading...</div>
    </svelte:fragment>

    
</WhenVisible>

The full list of configuration options for lazy loading and prefetching is available in the documentation for review. Inertia 2.0 also features polling, deferred props, and infinite scrolling. Developers are encouraged to review the upgrade guide for more details.

Inertia targets back-end developers who want to create single-page React, Vue, and Svelte apps using classic server-side routing and controllers, that is, without the complexity that comes with modern single-page applications. Developers using Inertia do not need client-side routing or building an API.

Inertia returns a full HTML response on the first page load. On subsequent requests, server-side Inertia returns a JSON response with the JavaScript component (represented by its name and props) that implements the view. Client-side Inertia then replaces the currently displayed page with the new page returned by the new component and updates the history state.

Inertia requests use specific HTTP headers to discriminate between full page refresh and partial refresh. If the X-Inertia is unset or false, the header indicates that the request being made by an Inertia client is a standard full-page visit.

Developers can upgrade to Inertia v2.0 by installing the client-side adapter of their choice (e.g., Vue, React, Svelte):

npm install @inertiajs/vue3@^2.0

Then, it is necessary to upgrade the inertiajs/inertia-laravel package to use the 2.x dev branch:

composer require inertiajs/inertia-laravel:^2.0


Inertia
is open-source software distributed under the MIT license. Feedback and contributions are welcome and should follow Inertia’s contribution guidelines.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

Express 5.0 Released, Focuses on Stability and Security

MMS Founder
MMS Bruno Couriol

The Express.js team has released version 5.0.0, 10 years after the first major version release in 2014. The release focuses on stability and security with a view to enabling developers to write more robust Node.js applications.

Express 5 drops support for old versions of Node.js. The release note states:

This release drops support for Node.js versions before v18. This is an important change because supporting old Node.js versions has been holding back many critical performance and maintainability changes. This change also enables more stable and maintainable continuous integration (CI), adopting new language and runtime features, and dropping dependencies that are no longer required.

Following a security audit, the team decided to introduce changes in how path route matching works. To avoid regular expression Denial of Service (ReDoS) attacks, Express 5 no longer supports sub-expressions in regular expressions, for example /:foo(d+).


app.get('/:id(d+)', (req, res) => res.send(`ID: ${req.params.id}`));

Blake Embrey, member of the Express.JS technical committee, provides an example of regular expression (e.g., /^/flights/([^/]+?)-([^/]+?)/?$/i), that, when matched against '/flights/' + '-'.repeat(16_000) + '/x' may take 300ms instead of running below one millisecond. The Express team recommends using a robust input validation library.

Express 5 also requires wildcards in regular expressions to be explicitly named or replaced with (.*)** for clarity and predictability. Thus, paths like /foo* must be updated to /foo(.*).

The syntax for optional parameters in routes also changes. Former Express 4’s :name? becomes {/:name}:


app.get('/user/:id?', (req, res) => res.send(req.params.id || 'No ID'));


app.get('/user{/:id}', (req, res) => res.send(req.params.id || 'No ID'));

Unnamed parameters in regex capture groups can no longer be accessed by index. Parameters must now be named:


app.get('/user(s?)', (req, res) => res.send(req.params[0])); 


app.get('/user:plural?', (req, res) => res.send(req.params.plural));

Express 5 additionally enforces valid HTTP status codes, as a defensive measure against silent failures and arduous sessions of debugging responses.


res.status(978).send('Invalid status');  


res.status(978).send('Invalid status');  

Express.js 5 makes it easier to handle errors in async middleware and routes. Express 5 improves error handling in async. middleware and routes by automatically passing rejected promises to the error-handling middleware, removing the need for try/catch blocks.


app.get('/data', async (req, res, next) => {
  try {
    const result = await fetchData();
    res.send(result);
  } catch (err) {
    next(err);
  }
});


app.get('/data', async (req, res) => {
  const result = await fetchData();
  res.send(result);
});

While the Express team strives to keep the breaking changes minimal, the new release will require interested developers to migrate their Express code to the new version. Developers can review the migration guide available online.

Express.js is a project of the OpenJS Foundation (At-Large category). Developers are invited to read the full release note for additional technical details and examples.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

After Rome Failure, VoidZero is the Newest Attempt to Create Unified JavaScript Toolchain

MMS Founder
MMS Bruno Couriol

Evan You, creator of the Vue.JS web framework and Vite build tool, recently announced the creation of VoidZero Inc., a company dedicated to building a unified development toolchain for the JavaScript ecosystem. You posits that VoidZero may succeed where Rome, a previous project with similar goals, failed as it would inherit the large user base from the popular Vite toolchain. While VoidZero would release open-source software, the company itself is VC-funded.

VoidZero aims at creating an open-source, high-performance, and unified development toolchain for the JavaScript ecosystem that covers parsing, formatting, linting, bundling, minification, testing, and other common tasks that are part of the web development life cycle. While unified, the toolchain would be made of components that cover a specific task of the development cycle and can be used independently.

High performance would result from using the system development language Rust. Rust’s compile-to-native nature removes layers of abstraction and is credited to run at close-to-native speed. Rust’s memory safety features additionally facilitate concurrently running tasks and better utilization of multicore architectures. Additional performance gains come from better design (e.g., parsing once and using the same AST for all tasks in the development cycle).

The release note also mentions seeking to provide the same developer experience across all JavaScript runtimes. JavaScript is now being run in many different environments, including at the edge. New runtimes have appeared in recent years to reflect those new execution contexts (e.g., Deno, Bun, Cloudflare Workers, Amazon’s LLRT).

You justified its vision on Twitter:

The biggest challenge of a unified toolchain is the zero-to-one problem: it needs to gain critical mass for exponential adoption to justify continued development, but it is hard to cross the chasm before it actually fulfills the vision.

VoidZero does not have this problem, because Vite is already the fastest growing toolchain in the JavaScript ecosystem. And even by pure implementation progress, we’ve already built more than Rome did (before it transitioned into Biome) at this point. I think the premise that JS would benefit from a unified toolchain stands without questions – it’s the execution that matters.

Some developers on Reddit have raised concerns regarding VoidZero’s venture capital backing. The release note mentions that potential revenue incomes would come on top of the released open-source components in the shape of end-to-end solutions targeting the Enterprise segment, which has specific requirements in terms of scale and security. As adoption in the Enterprise is tied to adoption outside of the Enterprise (where developers are sourced from), VoidZero has an incentive to maintain free access to its core offering, beyond the usual benefits of open-source development. Trevor I. Lasn, in an article in which he elaborates on the pros and cons of VC funding, wonders:

[Premium features or enterprise solutions] aren’t necessarily a bad thing. Sustainable open source is good for everyone. But it does raise questions about long-term accessibility and potential lock-in.

The full release note is available online and includes many more technical details together with answers to a list of frequently asked questions.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

New Signals Proposal Seeks to Formalize Reactive Programming Primitives in JavaScript

MMS Founder
MMS Bruno Couriol

The JavaScript language recently added the Signals proposal (currently in Stage 1) to the list of candidate features striving to improve the language. The Signals proposal seeks to provide common primitives primarily for framework maintainers to implement reactive programming patterns. The proposal reflects input from authors/maintainers of Angular, Bubble, Ember, FAST, MobX, Preact, Qwik, RxJS, Solid, Starbeam, Svelte, Vue, Wiz, and more.

Reactive applications essentially require: an interface to external systems to receive input events and send actions; computing the reaction to the input event; and sending the corresponding actions to the matching external systems (e.g., screen display, remote databases). With functional UI approaches (e.g., Elm), the reaction computation relies on a pure function (called the reactive function) such that (actions_n, state_n+1) = f(state_n, event_n), where:

  • n is the nth event processed by the reactive system,
  • state_n is the state of the reactive system when the nth event is processed.

Many frameworks for implementing user interfaces (Angular2, Vue, React, etc.) rather make use of callback procedures, or event handlers, which, as a result of an event, directly perform the corresponding reaction. Deciding which actions to perform (be it input validation, local state update, error handling, or data fetching) often means accessing and updating some pieces of state that are not always in scope. Frameworks thus include some state management, dependency injection, or communication capabilities to handle delivering state where it is needed and updating it when allowed and required.

An alternative that has gained popularity in recent years is, when convenient and possible, to declare the relationship between input events and pieces of state (e.g., button click -> increment °C), between pieces of state themselves (e.g., °F = °C * 9/5 + 32), and between pieces of state and reactions (e.g., °C changes -> update gauge color on the screen). Those declarations happen once and for all, eliminating a range of bugs where developers update a variable’s dependency and forget to update the variable itself.

Some UI frameworks thus have developers declare these relationships using ad-hoc primitives and syntax ($ in Svelte; ref, reactive, and computed in Vue). Beyond differing syntax, such framework may adopt differing ways of implementing reactivity, and possibly slightly differing semantics. The proposal admittedly targets framework maintainers and the interoperability of their approaches:

Differently from Promises/A+, we’re not trying to solve for a common developer-facing surface API, but rather the precise core semantics of the underlying signal graph. [,] The signal API here is a better fit for frameworks to build on top of, providing interoperability through a common signal graph and auto-tracking mechanism.

The plan for this proposal is to do significant early prototyping, including integration into several frameworks, before advancing beyond Stage 1. We are only interested in standardizing Signals if they are suitable for use in practice in multiple frameworks, and provide real benefits over framework-provided signals.

The proposal provides a simple example of a counter implementation:

const counter = new Signal.State(0);
const isEven = new Signal.Computed(() => (counter.get() & 1) == 0);
const parity = new Signal.Computed(() => isEven.get() ? "even" : "odd");


declare function effect(cb: () => void): (() => void);

effect(() => element.innerText = parity.get());


setInterval(() => counter.set(counter.get() + 1), 1000);

The example showcases the syntax for declaring independent pieces of state (Signal.state), pieces of state tied to their dependencies (Signal.computed), and how a library maintainer can leverage the signal primitives to link the execution of actions to state changes (effect(...)).

The proposal includes an implementation that features automatic dependency tracking, lazy evaluation, and memoization. Automatic dependency tracking provides better developer ergonomics (vs. manually providing dependencies —cf. React’s useMemo). Lazy evaluation and memoization prevent unnecessary and untimely computations, improving the performance profile of the API.

Interesting discussions occurred on Reddit with one developer reflecting:

There is maybe a https://xkcd.com/927/ situation going on here, sure. But it’s pretty significant that I think all of the big frameworks are involved in creating the standard. So, this is going from a whole bunch of ways of solving the problem that signals solve and having just one instead (with frameworks building on that one for their specific needs).
[…] Being in browsers means it’ll be potentially more performant and memory efficient, even if only slightly (slight improvements can make a significant difference at this scale).

There are basically two fundamental takes on what should and shouldn’t be included in ECMAScript. [One camp] thinks that only the essentials should be added/included and devs should reinvent their own wheel (or use some JS library). The other camp thinks something more along the lines of JS providing APIs for common problems and welcoming standards like this, and Object.groupBy() over lodash… fewer dependencies, less code to ship, less frustration with “well, how does this library solve the problem vs the one I’m familiar with?”

Interested readers are invited to read the full proposal online. The GitHub repository contains plenty of explanations and code samples that serve to clarify the goal, syntax, and semantics of the proposal.

Reactive programming facilitates the development of event-driven, reactive applications by providing abstractions to express time-varying values and automatically managing dependencies between such values. A number of approaches have been proposed across various languages such as Haskell, Scheme, JavaScript, Java, .NET, and more. Reactive programming is particularly relevant for JavaScript — one of the native browser languages used for web applications.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

The Deno Team Releases JSR, a New JavaScript Package Registry

MMS Founder
MMS Bruno Couriol

The Deno team recently beta released JSR, a new JavaScript registry that strives to better fit the current needs of modern development and unify a fragmented JavaScript ecosystem. In particular, JSR embraces ESM (JavaScript native modules), natively accepts TypeScript packages, and supports major JavaScript runtimes (e.g., Node, Deno, Bun, browsers, miscellaneous serverless environments).

The npm package manager, originally released in 2010, was originally designed around Node.js, the CommonJS module system, and vanilla JavaScript. Fast forward 15 years, JavaScript now has a native module system (ESM), TypeScript has become the main choice for typed JavaScript, and a test bed for new JavaScript language features. Importantly, JavaScript is no longer limited to the browser and Node.js. Cloud providers often run their own optimized JavaScript runtime. Deno and Bun are also growing as alternatives to Node.js, revisiting key assumptions and focusing on developer experience.

JSR, the newly released JavaScript registry is free and open-source, supersedes CommonJS modules with ESM, natively accepts TypeScript packages, and as a goal seeks to improve on the developer experience, performance, reliability, and security of npm.

JSR’s documentation also describes cross-runtime packages as a design goal:

The goal of JSR is to work everywhere JavaScript works, and to provide a runtime-agnostic registry for JavaScript and TypeScript code. Today, JSR works with Deno and other npm environments that populate a node_modules. This means that Node.js, Bun, Cloudflare Workers, and other projects that manage dependencies with a package.json can interoperate with JSR as well.

JSR strives nonetheless to reuse the npm ecosystem by allowing JSR packages to depend on npm packages:

JSR is designed to interoperate with npm-based projects and packages. You can use JSR packages in any runtime environment that uses a node_modules folder. JSR modules can import dependencies from npm.

JSR also uses a package scoring system to nudge package publishers toward best practices in code distribution. For instance, a ranking score rewards packages that include comprehensive JSDoc documentation on each exported symbol (used to automatically generate package documentation). The ranking score includes other factors such as the presence of optimal type declarations for fast type-checking and the compatibility with multiple runtimes.

Developers are encouraged to review the release note for miscellaneous examples of publishing flows. For instance, a package creator publishing a TypeScript package with JSR and Deno needs to populate at least three files: a jsr.json metadata file, the TypeScript source files for the package, and a README.md file providing an overview of the package. The jsr.json file would go as follows:

{
  "name": "@kwhinnery/yassify",
  "version": "1.0.0",
  "exports": "./mod.ts"
}

The exports field specifies the package modules that are exposed to the package consumers.

The package would then be published in a Deno environment with deno publish and in a Node.js environment with npx jsr publish.

The Deno standard library was recently made available on JSR. Developers can review the package documentation guidelines provided online in order to optimize their package ranking score. The Deno team additionally published an in-depth blog post on how they built JSR.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

CO2.js Helps Developers Track Their Application’s Carbon Footprint

MMS Founder
MMS Bruno Couriol

The Green Web Foundation published a new release of CO2.js, a JavaScript library that enables developers to access the Green Web API and estimate the carbon emissions associated with their apps, websites, and software. CO2.js supports developers who want to create a carbon budget for their site or include carbon footprint estimation in monitoring tools.

By some measures, internet use accounts for 3.7% of global greenhouse gas emissions, which makes it comparable to emissions associated with the entire world air traffic.

The Green Web Foundation explains:

Our mission at The Green Web Foundation is for a fossil-free internet by the year 2030. We know that getting there will take a collective effort on the part of technologists around the globe. That’s why we’re always looking for ways to leverage open source and open data. Our aim is to equip those in tech jobs with compelling, state-of-the-art, practical, and well-documented tools and “patterns” for change. Tools and patterns that can be used right now in workflows and products.

CO2.js is just one of the tools we’ve created to help with this.

CO2.js takes an input of data, in bytes, and returns an estimate of the carbon emissions produced to move that data over the internet. It can be run in the browser, on Node.js servers and some serverless and edge compute runtimes.

Developers can incorporate the carbon emission estimate in their workflow and set a carbon budget in the same way that they already set code coverage targets or performance budgets. If a website or an application goes over budget, an alert could be raised or the deployment could be blocked.

To estimate carbon emissions related to bytes of data, developers can choose between the OneByte model and the Sustainable Web Design model — a richer model that factors in the device type, network type, and CPU utilization:

import  { co2 }  from  "@tgwf/co2";

const swd =  new  co2();
const declaredSwd =  new  co2({  model:  "swd"  });

CO2.js also has a perVisit() function to calculate the carbon emissions of a website, Additionally, developers can check whether a domain is hosted on a green host by querying the Green Web Foundation API:

const  { hosting } = require("@tgwf/co2");

hosting.check(["somedomain.net", "otherdomain.com"]).then((result) => {
  ...
});

CO2.js is open-sourced under the Apache license. Contributors and sponsors are welcome. The Green Web Foundation is a not-for-profit organization that maintains the world’s largest open dataset of websites that run on green energy. They also offer open-source tools to manage the environmental impact of digital services.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

Running PostgreSQL in the Browser with WebAssembly

MMS Founder
MMS Bruno Couriol

With the recently released PGlite, a Wasm build of Postgres that is packaged into a TypeScript client library, developers can run Postgres queries in the browser with no extra dependencies. PGlite is used for reactive, real-time, local-first apps.

Developers could already run SQLite in the browser with WebAssembly. However, running PostgreSQL in the browser previously required spanning a virtual machine and there was no way to persist data. With PGlite, developers can run PostgreSQL queries in a JavaScript environment and persist data to storage in the file system (Node/Bun) or indexedDB (browser).

PGlite was created to support use cases associated with reactive, real-time, local-first applications. ElectricSQL, which self-describes as a local-first software platform for modern apps with instant reactivity, real-time multi-user collaboration, and conflict-free offline support, uses PGlite to sync on demand with a server. They explain:

Local-first is a new development paradigm where your app code talks directly to an embedded local database and data syncs in the background via active-active database replication. […] ElectricSQL gives you instant local-first for your Postgres. Think of it like “Hasura for local-first”.

PGlite includes parameterized SQL queries, an interactive transaction API, pl/pgsql support, web worker execution, and more. PGlite is 2.6MB gzipped. PGlite can be used in memory in the browser as follows:

const db = new PGlite()
await db.query("select 'Hello world' as message;")

Developers can also persist the database to indexedDB:

const db = new PGlite("idb://my-pgdata");

One Reddit developer emphasized testing as an additional use case for PGlite.

Code testing is a big one for me. I’m currently using in-memory SQLite for tests and I’m often running into differences between SQLite and Postgres (default values, JSON handling, etc). This could allow me to use the real thing without running a full Docker instance.

Another developer said:

No one using Postgres in the cloud is going to use this as an alternative, but there are at least two use cases where this could be very useful:

  • You want your app to be local first (snappy, great offline support, etc) but sync data to a server. This is the ElectricSQL use case.

  • You want a serious data store in-browser. SQLite via Wasm already fits this use case, but it’s nice to have options.

PGlite is open-source software under the Apache 2.0 license. It is being developed at ElectricSQL in collaboration with Neon. PGlite is still in the early stages and plans to support pgvector in future releases.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

How Airbnb Caters to Users with Low Vision with Accessible Text Resizing

MMS Founder
MMS Bruno Couriol

The Airbnb Tech Blog recently detailed how Airbnb enhances accessibility for users with vision difficulties. Through careful implementation of text resizing guidelines, Airbnb maintains web content, functionality, and a good user experience even as the text font size is doubled.

The Web Content Accessibility Guidelines are a set of standards and recommendations to make web content more accessible for individuals with disabilities. Mild visual disabilities are a fairly common occurrence. The CDC estimates the prevalence of the issue to be 3 out of 5 in America. Furthermore, as many Reddit users mention, not only users with a visual disability may reach out to text resizing capabilities of their browsers (or website, when available):

Anyone with a visual disability is likely to have a “large font size” option set in their browser. [lightmatter501]
And yes, people scale the font size with keyboard or mouse buttons. Because of accessibility mostly. [throwtheamiibosaway]
For some pages, I view the browser at 110% or 125% zoom since my monitor is 3440×1440 and sometimes the font is too small to read. I guess that still counts as accessibility. [Reddit user]
I just do it if I want to lean back in my chair for a while, or if I’m showing someone something, or if I’m sharing my screen on Zoom. [superluminary]
I change the minimum font size because of only one particular website I like to visit. But I am young and still have good eyes. [lontrachen]

The WCAG 1.4.4 Resize Text (Level AA) guideline requires that except for captions and images of text, text can be resized without assistive technology up to 200 percent without loss of content or functionality. Airbnb’s blog post details how they use font scaling as a complement to zoom scaling. Font scaling ties to the ability to increase or decrease text font size without necessarily affecting non-text elements of the page. Using browser zooming capabilities on the other hand scales all web content proportionally, which may lead to a suboptimal experience for some users.

The core idea consists of using em and rem CSS units instead of px units. px units are fixed and do not vary with the user-preferred font size. rem units on the other hand are relative to the font size of the root element. The root element defaults to 16px in many browsers, so 1rem is often equal to 16px. Setting font sizes with rem units is a good idea because it is designed to adapt to the user’s browser preferences. em is also a relative unit of measurement that unlike rem is relative to the font size of the parent element or the font-size of the nearest parent with a defined font size.

The blog article explains:

The choice between em and rem units often comes down to the level of control and predictability required for font scaling. While em units can be used, they can lead to cascading font size changes that may be difficult to manage, especially in complex layouts. In contrast, rem units provide a more consistent and predictable approach to font scaling, as they are always relative to the root element’s font size. […]

In the case of Airbnb, the team decided to prioritize the use of rem units specifically for font scaling, rather than scaling all elements proportionally.

The blog article additionally goes into detail about spreading the corresponding design choices across the entire codebase (which uses two different CSS-in-JS systems), ensuring designers and developers adopt the new approach, and solving cross-platform issues (e.g., Safari on mobile). Airbnb deemed the experience successful:

Choosing font scaling as the product accessibility strategy brought about a range of significant benefits that notably enhanced our platform’s overall user experience. Making that change using automation to convert to rem units made this transition easier. When looking at our overall issues count after these changes were site-wide, more than 80% of our existing Resize Text issues were resolved. Moreover, we are seeing fewer new issues since then.

Developers are invited to refer to the full article and review the detailed technical explanations and demos that are provided.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.

Microsoft and IBM Release MS-DOS 4.0’s Source Code under the MIT License

MMS Founder
MMS Bruno Couriol

Microsoft and IBM have open-sourced on git the 1988 operating system MS-DOS 4.0 under the MIT License. In addition to the source code for MS-DOS 4, the public git repository contains unreleased beta Multitasking DOS binaries, the ibmbio.com source, and the scanned PDFs of the Multitasking MS-DOS 4.0 (MT-DOS) documentation.

MS-DOS 4.0 was notable for its support of FAT16 hard disk partitions greater than 32 MB and the addition of the MS-DOS Shell. MS-DOS 4.0 however was originally supposed to include multi-tasking capabilities. As its product specification mentions:

MS-DOS 4.0 is a multitasking operating system, developed from and downwardly compatible with MS-DOS 3.0. It supports true multitasking as well as multiple current screen image facility which gives the user the illusion of and benefits from many independent computers. Further, MS-DOS 4.0 allows most existing MS-DOS 2.0 applications to run without changing the MS-DOS 4.0 multitasking environment.

To ease the transition from 8086/8088 line of processors to the (then) new 286 processor without disrupting the installed base, Multitasking MS-DOS targeted two-way compatibility:

Microsoft resolves this situation by providing both upward and downward compatibility. The new environment is designed to allow old programs to run unchanged (upwardly compatible) and to allow most programs written for the new environment to run under the old environment (downwardly compatible).

This design choice brought crucial challenges. As the open-sourced documentation reveals:

The PC architecture supports up to 640K of memory. This is not nearly enough; just the DOS, a network package, a windows package, and Lotus Symphony will consume the entire memory. A software solution must be found to this hardware problem.

Ultimately, the multitasking version of MS-DOS was only licensed by a few European OEMs. IBM declined the product, concentrating instead on improvements to MS-DOS 3.x and their new joint development with Microsoft to produce OS/2.

In North America, what came to be released as MS-DOS 4.0 did not include multitasking and was quickly followed by an MS-DOS 4.01 release to fix issues many had reported.
As a matter of fact, the now open-sourced MS-DOS 4.0 notably featured significantly higher memory usage (92 KB of RAM) than previous and posterior versions, at a time in computing history when RAM was scarce. One developer who compared miscellaneous MS-DOS versions commented:

Personally, I would not recommend any version of DOS lower than PC-DOS 3.30 / MS-DOS 3.31 unless you can live with the severe limitations with regard to disk support. I also wouldn’t recommend any version of 4.x, as it is notoriously buggy.

Steven Vaughan-Nichols reinforced that point:

MS-DOS 4.0 was an awful operating system. […] How awful? Popular programs of the day – such as WordPerfect 5.1, Lotus 1-2-3, and Doom – always broke on it. You’d be in the middle of a task, and, bang, your program would freeze completely. Long before we got to know and hate Windows’ Blue Screen of Death, MS-DOS 4.0 horrified PC users.

That was mainly because MS-DOS 4.0 used an enormous 92KB of RAM.

According to Microsoft, the interested reader may run MS-DOS 4.0 directly on an original IBM PC XT, a newer Pentium, and within the open source PCem and 86box emulators.

In 2014, Microsoft open-sourced the MS-DOS source code for versions 1.25 and 2.0 via the Computer History Museum. Microsoft additionally previously open-sourced Word (for Windows 1.1a), GW-BASIC (initially released in 1983), and the Windows File Manager (first released for Windows 3.0 in the early 1990s). The Windows File Manager continues to be actively maintained, with the last cumulative release occurring in March 2024.

MS-DOS (Microsoft Disk Operating System) is an adaptation of QDOS (Quick and Dirty Operating System) by its developer Tim Paterson destined to be the operating system for the IBM Personal Computer. MS-DOS 1.0 shipped on IBM PC in July 1981 and was till 1990 the most used operating system on Compatible PCs.

About the Author

Subscribe for MMS Newsletter

By signing up, you will receive updates about our latest information.

  • This field is for validation purposes and should be left unchanged.