Skip to main content
Deno 2 is finally here 🎉️
Learn more
Deno 1.42

Deno 1.42: Better dependency management with JSR

Our vision with Deno is to simplify programming, and one important aspect of that is managing dependencies. While npm has grown to be the most successful open source registry, consuming and publishing modules there has grown increasingly complex.

Built on npm’s success, JSR offers a modern, TypeScript-first, and cross-platform-compatible registry, fully integrated into Deno.

Deno v1.42 provides more robust dependency management with deno publish and deno add subcommands, which can publish and install modules from JSR and npm. On top of that, this release offers improved Node/npm compatibility, several LSP improvements, faster startup time (along with other performance benefits), and more.

If you already have Deno installed, upgrade to version 1.42 in your terminal with:

deno upgrade

If you don’t yet have Deno installed, you can install it with one of the following commands, or many other ways.

MacOS / Linux Install

curl -fsSL https://deno.land/install.sh | sh

Windows Install

irm https://deno.land/install.ps1 | iex

Here’s an overview of what’s new in Deno 1.42:

JSR, deno publish, and deno add

JSR is a new open source registry for modern JavaScript and TypeScript packages. Read about why we built JSR.. JSR is an absolute pleasure to use. It takes all the headaches away from distributing TypeScript and JavaScript. We’re sure you’ll love it.

In 1.42, first class support for JSR is added to Deno. That means without any additional tooling, you can consume and publish modules to JSR.

There are two new subcommands. First is deno add. This works just like npm add but defaults to JSR packages. For example, if you want to use @std/assert from JSR, you would just run

deno add @std/assert

This will add an import map entry allowing you to easily import in your code

import { assertEquals } from "@std/assert";
assertEquals(1, 2);

Note that deno add also supports adding npm packages with the npm: prefix.

For module authors deno publish does what you expect, it publishes to JSR. Read all about it here.

JSR is also fully baked into Deno’s LSP and VS Code extension. Expect go-to-definition to work properly, even with TypeScript. Intellisense should work perfectly fine for JSR packages.

We’d love to hear your feedback on these new features.

Node.js and npm compatibility

Lots of improvements in this release to make Deno more compatible with Node.js:

  • async_hooks module now supports EventEmitterAsyncResource AsyncLocalStorage.enterWith() APIs #22994 #22740

  • child_process.spawn() correctly handles null in stdio configuration #23048

  • crypto module is steadily getting more complete. In this release we added getRandomValues(), subtle, getCipherInfo(), publicKey(), createPublicKey() APIs, as well as added support for more curves in multiple APIs. The changes should unblock usages of popular packages like ssh2, web-push, octokit and more. #22882 #22891 #23028

  • fs received support for Windows “junctions”, FsWatcher.ref(), FsWatcher.unref() and fs.statfs() APIs #22987 #22294

  • http module now exports validateHeaderName() and validateHeaderValue() APIs and ServerResponse now correctly supports setting HTTP methods #22630 #22616

  • http2 received a basic support for createServer() API #22708

  • module.isBuiltin() is now supported #22817

  • process.arch now supports "riscv64"

  • process.argv0 is now correctly set

  • process.version has been updated to return v20.11.1 which is the latest LTS release of Node.js

  • process.setSourceMapsEnabled is now available, but is a no-op

  • punycode module works correctly #22847

  • string_decoder.StringDecoder() matches Node.js behavior #22933

  • timers.setImmediate matches Node.js API and behavior #22808

  • util.styleText is now supported #22758

  • worker_threads module received a major overhaul. It now correctly supports ES modules and CommonJS. Following APIs are now supported: parentPort, workerData, isMainThread, threadId, receiveMessageOnPort(), ref(), unref(). Workers are now setup synchronously and automatically terminated when they are idle. #22841 #20794 #22950 #22647 #22884 #22815 #22766 #22778

  • v8.serialize() and v8.deserialize() have been implemented #22975 #22975

As well as several improvements related to npm compatibility:

  • User code can now correctly import CommonJS files from the node_modules/ directory

  • Internal conditional exports (exports starting with #, eg. #crypto) are now supported

  • CSS files are correctly resolved from npm packages during type checking

Additionally, improvements were made to the performance of setting up the node_modules/ directory - you can see up to 1.7x speed up in Deno v1.42.

deno task

Cross-platform shebang support has landed in deno task for any shebang that starts with #!/usr/bin/env -S.

Given a script.ts file and deno.json:

#!/usr/bin/env -S deno run
console.log("Hello there!");
{
  "tasks": {
    "hi": "./script.ts"
  }
}

Running this task now works, even on a Windows machine:

> pwd
C:\Users\david\dev\my_project
> deno task hi
Hello there!

Exit status variable

The shell now supports using $? to get the exit code of the last run command:

{
  "tasks": {
    // outputs 10
    "output": "deno eval 'Deno.exit(10)' || echo $?"
  }
}

Improved redirect support

Input redirects and more file descriptor redirects are now implemented:

{
  "tasks": {
    // redirect file.txt to the stdin of gzip
    "input-redirect": "gzip < file.txt",
    // redirect stdout to stderr
    "stdout-err": "deno run main.ts >&2",
    // redirect stderr to stdout
    "stderr-out": "deno run main.ts 2>&1"
  }
}

Task descriptions

If you are using a JSONC file, you can now add descriptions to your tasks using comments:

{
  "tasks": {
    // Start development server
    "dev": "deno run --watch main.ts",

    /**
     * Run tests with coverage and output HTML report
     */
    "coverage": "deno test --coverage **/*_test.ts && deno coverage --html"
  }
}
$ deno task
- dev
  // Start development server
  deno run --watch main.ts

- coverage
  // Run tests with coverage and output HTML report
  deno test --coverage **/*_test.ts && deno coverage --html

deno lint --fix

The infrastructure has been implemented to fix lint rules automatically on the command line and via quick fixes in the editor.

For example, given the following code:

window.onload = () => console.log("Hi there!");

deno lint now outputs the following:

> deno lint
error[no-window]: window is deprecated and scheduled for removal in Deno 2.0
 --> main.ts:1:1
  |
1 | window.onload = () => console.log("Hi there!");
  | ^^^^^^
  = hint: Instead, use `globalThis`

  docs: https://lint.deno.land/rules/no-window


Found 1 problem (1 fixable via --fix)
Checked 1 file

Notice the text (1 fixable via --fix). Let’s try that:

> deno lint --fix
Checked 1 file
> cat main.ts
globalThis.onload = () => console.log("Hi there!");
> deno lint
Checked 1 file

At the moment, this only works for three lint rules, but the list will grow over time.

--watch-exclude=...

Sometimes when using the --watch flag, you’d rather not have certain files trigger a restart. This is now possible with the --watch-exclude flag:

# exclude file1.ts and file2.ts from being watched
deno run --watch --watch-exclude=file1.ts,file2.ts main.ts

You can also exclude patterns, but remember to surround it in quotes to prevent your shell from expanding them before sending the arguments to Deno:

# exclude any .js file from being watched
deno run --watch --watch-exclude='*.js' main.ts

jsr tag and verbatim-module-syntax lint rule

deno.json files containing name, version, and exports fields are now automatically opted into the jsr lint rule tag.

This tag contains the following rules:

  • no-slow-types
  • verbatim-module-syntax (fixable via --fix)

The no-slow-types lint rule is JSR specific and you can read about it on jsr.io. The verbatim-module-syntax lint rule enforces import and export declarations define their identifiers as being type only when they’re used in only type positions. This is important to ensure code published on jsr.io works in more scenarios. You can read about verbatim module syntax in the TypeScript 5.0 release notes.

Type checking partway through application execution no longer occurs

Previously, if you ran deno run with the --check flag, Deno could potentially type check partway through execution when encountering a statically unanalyzable dynamic import or starting a worker.

This feature had a large maintenance burden, raised some challenges with JSR, and produced the undesirable behavior of potentially failing a running application partway through execution. For this reason, type checking no longer occurs after the initial type check (to emphasize: deno run --check main.ts still type checks BEFORE executing any modules).

It’s recommended to instead use the deno check sub command to type check these modules if desired.

Upcoming deno install changes

deno install allows you to easily install and distribute executable code.

$ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
✅ Successfully installed file_server.
$ file_server
Listening on http://127.0.0.1:4507

We have received feedback that while this command is useful, a lot of users expected it to “install” dependencies locally to the project — just like previously introduced deno add does.

To better align with the expectations, deno install will be changed in Deno 2 to installing scripts locally to the project. That is, deno install will be an alias to deno add.

The current behavior will still be supported with the -g / --global flag to tell Deno that you want to install the script globally.

$ deno install --global --allow-net --allow-read https://deno.land/std/http/file_server.ts
✅ Successfully installed file_server.

Deno will now warn you and suggest to use -g / --global flag if you omit it.

Language server improvements

Since v1.37, our LSP has supported completions for npm: specifiers. In v1.42, we’ve not only added support for jsr: specifiers, but also completions for both package names and versions.

import "jsr:@std/a";
//     "jsr:@std/archive";
//     "jsr:@std/assert"; ✔️
//     "jsr:@std/async";
//     "jsr:@std/data-structures";
//     "jsr:@std/datetime";
//     ...
import "jsr:@std/assert@";
//     "jsr:@std/[email protected]"; ✔️
//     "jsr:@std/[email protected]";
//     "jsr:@std/[email protected]";
//     "jsr:@std/[email protected]";
//     "jsr:@std/[email protected]";
//     ...

Other improvements and fixes

  • Include registry url in JSR import hover text.
  • Don’t warn about local file “redirects” from .js to .d.ts files.
  • Don’t apply symbol renames to vendored remote modules.
  • Apply trailing slash expansion for package specifier import map keys.

Performance

This release saw a bunch of performance improvements across the board, with most notable being:

Faster startup time: 10% improvement in startup time on Linux. Bootstrap initialization is now warmed up during snapshot time and reduced memory allocations.

More efficient setTimeout and setInterval: Timers have undergone a significant rewrite. Creating a million timers takes about 1.4s compared to 5.9s in Deno 1.41, also cutting memory usage by up to 70%. We still have a few optimizations to make, that we will be working on in the coming months.

V8 12.3 and TypeScript 5.4.3

Deno 1.42 ships with V8 12.3 and TypeScript 5.4.3. The notable changes include support for Set methods and support for Iterator Helpers.

Following are now available:

DENO_FUTURE=1 environment variable

Deno v1.42 adds a new environment variable, DENO_FUTURE=1, which enables changes that will take place in, the long anticipated, many times delayed, Deno 2.

Currently DENO_FUTURE=1 enables the following changes:

  • remove window global
  • remove following Deno APIs: Deno.Buffer, Deno.close, Deno.copy, Deno.File, Deno.FsFile.prototype.rid, Deno.fstat, Deno.fstatSync, Deno.ftruncate, Deno.ftruncateSync, Deno.flock, Deno.flockSync, Deno.funlock, Deno.funlockSync, Deno.iter, Deno.iterSync, Deno.metrics, Deno.readAll, Deno.readAllSync, Deno.read, Deno.readSync, Deno.resources, Deno.seek, Deno.seekSync, Deno.shutdown, Deno.writeAll, Deno.writeAllSync, Deno.write, Deno.writeSync

In following releases we will add more changes that will happen in Deno 2, including changes to handling of node_modules/ directory. Specficially enabling BYONM under DENO_FUTURE.

If you want to future-proof your code for the upcoming major Deno 2 release, you can set the DENO_FUTURE=1 environment variable in your shell or CI environment.

Thank you to our contributors!

We couldn’t build Deno without the help of our community! Whether by answering questions in our community Discord server or reporting bugs, we are incredibly grateful for your support. In particular, we’d like to thank the following people for their contributions to Deno 1.42: Dimitris Apostolou, Don Jayamanne, Eric Long, Kenta Moriuchi, Nano Miratus, Sol Boucher, Viktor Marinho, cui fliter, guangwu, mash-graz, mimikun, tuhana, ud2, and Łukasz Czerniawski.

Would you like to join the ranks of Deno contributors? Check out our contribution docs here, and we’ll see you on the list next time.

Believe it or not, the changes listed above still don’t tell you everything that got better in 1.42. You can view the full list of pull requests merged in Deno 1.42 on GitHub here.

Thank you for catching up with our 1.42 release, and we hope you love building with Deno!

🍋 Fresh 2.0 is right around the corner.

Our next major Fresh release will be simpler with a more composable, Express-like API. Read more here.