Deno 2.4: deno bundle is back
To upgrade to Deno 2.4, run the following in your terminal:
deno upgradeIf Deno is not yet installed, run one of the following commands to install or learn how to install it here.
# Using Shell (macOS and Linux):
curl -fsSL https://deno.land/install.sh | sh
# Using PowerShell (Windows):
iwr https://deno.land/install.ps1 -useb | iexWhat’s new in Deno 2.4
deno bundle- Importing text and bytes
- Built-in OpenTelemetry is now stable
- Modify the Deno environment with the new
--preloadflag - Easier dependency management with
deno update - Collect script coverage with
deno run --coverage DENO_COMPAT=1- Permission changes
- Conditional
package.jsonexports deno runbare specifiersdeno fmtXML and SVG files- Better
tsconfig.jsonsupport - Simpler Node globals
- Local npm packages
- Node.js API support
- LSP improvements
- Other fun things
- Acknowledgements
deno bundle
Deno 2.4 restores the
deno bundle subcommand for
creating single-file JavaScript bundles from JavaScript or TypeScript. It
supports both server-side and browser platforms, works with npm and JSR
dependencies, and includes automatic tree shaking and minification via esbuild.
# Bundle with minification
$ deno bundle --minify main.ts
# Set platform to browser (defaults to "deno")
$ deno bundle --platform browser --output bundle.js app.jsx
# Also generate an external sourcemap
$ deno bundle --platform browser --output bundle.js --sourcemap=external app.jsxFor long time Deno users, you may remember we used to have deno bundle, which
was subsequently deprecated.
JavaScript bundling is an incredibly complex problem, and we did not believe we
could build deno bundle properly. Now that deno bundle uses
esbuild under the hood, it is here to stay.
We’re working on a runtime API to make bundling available programmatically in the future. On top of that, we plan to add plugins, allowing you to customize how the bundler processes modules during the build process.
For more information visit
deno bundle reference
and the bundling docs page
Importing text and bytes
Have you ever wanted to include a data-file of some sort in your JavaScript module graph? Maybe a markdown file, icons, or a binary blob? Until now you would have had to load these files at runtime, carefully ensuring the assets were shipped alongside your code:
const image = Deno.readFileSync(import.meta.resolve("./image.png"));
const text = await Deno.readTextFile(import.meta.resolve("./log.txt"));In Deno 2.4, you can link these files into the JavaScript graph with the flag
--unstable-raw-imports:
import message from "./hello.txt" with { type: "text" };
import bytes from "./hello.txt" with { type: "bytes" };
import imageBytes from "./image.png" with { type: "bytes" };
console.log("Message:", message);
// Message: Hello, Deno!
console.log("Bytes:", bytes);
// Bytes: Uint8Array(12) [
// 72, 101, 108, 108, 111,
// 44, 32, 68, 101, 110,
// 111, 33
// ]
Deno.serve((_req) => {
return new Response(imageBytes, {
status: 200,
headers: {
"Content-Type": "image/png",
"Content-Length": imageBytes.byteLength.toString(),
},
});
});
// Shows image.png at localhost:8000You can use this with deno bundle, simplifying the process of importing
non-JavaScript files in your application and avoiding manual file I/O or
middleware.
import icon from "./icon.png" with { type: "bytes" };
console.log("Icon", icon);$ deno bundle --unstable-raw-imports -o app.js main.ts
⚠️ deno bundle is experimental and subject to changes
Bundled 2 modules in 7ms
app.js 268B
$ deno app.js
Icon Uint8Array(69) [
137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13,
73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1,
8, 2, 0, 0, 0, 144, 119, 83, 222, 0, 0, 0,
12, 73, 68, 65, 84, 120, 218, 99, 96, 96, 96, 0,
0, 0, 4, 0, 1, 200, 234, 235, 249, 0, 0, 0,
0, 73, 69, 78, 68, 174, 66, 96, 130
]Additionally, this feature works with deno compile, so that you can embed
assets into your final compiled binary.
import dictData from "./dictionary.txt" with { type: "text" };
const DICT = dictData.split(" ");
while (true) {
let input = prompt("> Enter the word to check: ");
input = input.trim();
if (!input) {
continue;
}
if (!DICT.includes(input)) {
console.error(`${input} is not a known word`);
} else {
console.log(`${input} is a known word`);
}
}$ deno compile --unstable-raw-imports spellcheck.js
Compile file:///dev/spellcheck.js to spellcheck
$ ./spellcheck
> Enter the word to check: deno
deno is a known word
> Enter the word to check: asdf
asdf is not a known wordBytes and text imports add to Deno’s existing ability to import JSON and Wasm files natively:
import file from "./version.json" with { type: "json" };
console.log(file.version);
// "1.0.0"
import { add } from "./add.wasm";
console.log(add(1, 2));
// 3While the ability to import various file types have been around (such as in Next.js and other frameworks), these approaches are not spec-friendly and introduce unnecessary complexity via domain-specific languages and ahead-of-time compilers that modify the language.
We’ve wanted to add importing other file types earlier, but also want to be aligned with the spec and avoid introducing breaking changes. Astute observers might note that this feature actually goes ahead of current spec (here’s the proposal for import attributes). However, due to ongoing discussions and proposed upcoming features about this feature, we are confident this implementation is in the right direction.
Built-in OpenTelemetry is now stable
In 2.2, we introduced
built-in OpenTelemetry support,
which auto-instruments the collection of logs, metrics, and traces for your
project. We’re excited to announce that it is now stable in 2.4, which means you
no longer need --unstable-otel flag:
$ OTEL_DENO=1 deno --allow-net server.ts
Listening on http://localhost:8000/Deno’s OpenTelemetry support simplifies observability in your JavaScript projects, as it automatically associates logs with HTTP requests, works in Node with no additional config, and is available to all your projects in our new Deno Deploy:
console.logs and associates them with HTTP requests. Here we click view a trace from a log, then view all logs within that HTTP request.
Note that you will still need to set the environment variable OTEL_DENO=1 to
enable instrumentation, since it uses additional resources and don’t want it on
all the time.
For more information about Deno’s OpenTelemetry support, check out the following resources:
- Zero-config Debugging with Deno and OpenTelemetry
- How to get deep traces in your Node.js backend with OTel and Deno
- Easier debugging with auto-instrumented OTel in Deno Deploy
- Deno OpenTelemetry reference documentation
Modify the Deno environment with the new --preload flag
We’ve landed a new --preload flag that will execute code before your main
script. This is useful if you are building your own platform and need to modify
globals, load data, connect to databases, install dependencies, or provide other
APIs:
delete Deno;
globalThis.window = globalThis;console.log(Deno);$ deno --preload setup.ts main.ts
error: Uncaught (in promise) ReferenceError: Deno is not defined
console.log(Deno);
^
at file:///main.ts:1:13While we’ve traditionally been cautious about allowing user code to modify the
runtime, it’s become clear that there are enough circumstances in which this is
needed. This flag is available to use in
deno run,
deno test and
deno bench subcommands.
Easier dependency management with deno update
We’ve added a new subcommand,
deno update, which
allows you to update your dependencies to the latest versions:
deno update --latest.
This command will update npm and JSR dependencies listed in deno.json or
package.json files to latest semver compatible versions.
# Ignore semver constraints
deno update --latest
# Filter packages that match "@std/*"
deno update "@std/*"
# Include all workspace members
deno update --recursivedeno outdated --update did the same thing, but to save you the headache of
typing additional characters, we added the alias deno update.
For more information about deno update, check out
the Deno docs.
Collect script coverage with deno run --coverage
deno test --coverage
will execute your test suite while collecting coverage information, which is a
breeze to use. However, in some situations like if you need to spawn a
subprocess as part of the test suite,
deno test would not
collect the coverage of the subprocess, making the report spotty.
Deno 2.4 alleviates this problem by introducing the --coverage flag that you
can pass to deno run.
You can also use DENO_COVERAGE_DIR environment variable instead.
function foo(a: number, b: number) {
if (a > 0) {
console.log(a);
} else {
console.log(a);
}
if (b > 0) {
console.log(b);
} else {
console.log(b);
}
}
const [a = 0, b = 0] = Deno.args;
foo(+a, +b);$ deno run --coverage main.ts
0
0
$ deno coverage
| File | Branch % | Line % |
| --------- | -------- | ------ |
| main.ts | 0.0 | 57.1 |
| All files | 0.0 | 57.1 |To learn more about coverage collection and presentation visit Deno docs.
Oh by the way, HTML coverage report now supports dark mode 🤫.
DENO_COMPAT=1
We’ve introduced a new environment variable, DENO_COMPAT=1 , that will tell
Deno to enable the below flags to improve ergonomics when using Deno in
package.json-first projects:
--unstable-detect-cjs--unstable-node-globals--unstable-bare-node-builtins--unstable-sloppy-imports
For instance:
# Before 2.4
deno --unstable-detect-cjs --unstable-node-globals --unstable-bare-node-builtins --unstable-sloppy-imports app.js
# 2.4
DENO_COMPAT=1 deno app.jsIn the future, the scope of this environmental variable might be expanded
further — eg. to not require npm: prefixes when
deno installing
packages.
We are also stabilizing the --unstable-sloppy-imports flag to become
--sloppy-imports, which tells Deno to infer file extensions from imports that
do not include them. While Deno generally encourages requiring file extensions
to avoid inefficiencies such
as probing the filesystem, the
--sloppy-imports flag is a way to run code that uses extensionless imports.
Permission changes
The
--allow-net flag
now supports subdomain wildcards and CIDR ranges:
const res1 = await fetch("http://test.foo.localhost");
const res2 = await fetch("http://test.bar.localhost");$ deno --allow-net=*.foo.localhost subdomain_wildcards.ts
Response {
url: "http://test.localhost",
...
}
┏ ⚠️ Deno requests net access to "test.bar.localhost:80".
┠─ Requested by `fetch()` API.
┠─ To see a stack trace for this prompt, set the DENO_TRACE_PERMISSIONS environmental variable.
┠─ Learn more at: https://docs.deno.com/go/--allow-net
┠─ Run again with --allow-net to bypass this prompt.
┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) >const res1 = await fetch("http://192.168.0.128:8080");
const res2 = await fetch("http://192.168.0.1:8080");$ deno --allow-net=192.168.0.128/25 main.ts
Response {
url: ""http://192.168.0.128:8080"",
...
}
┏ ⚠️ Deno requests net access to "192.168.0.1:8080".
┠─ Requested by `fetch()` API.
┠─ To see a stack trace for this prompt, set the DENO_TRACE_PERMISSIONS environmental variable.
┠─ Learn more at: https://docs.deno.com/go/--allow-net
┠─ Run again with --allow-net to bypass this prompt.
┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) >Deno 2 added
--allow-import flag
that allows you to specify which remote hosts Deno can download and execute code
from.
This release adds a complementary --deny-import flag that allows to explicitly
block certain hosts.
By default Deno allows to import code from several hosts:
deno.land:443jsr.io:443esm.sh:443cdn.jsdelivr.net:443raw.githubusercontent.com:443user.githubusercontent.com:443
import * as cowsay from "https://cdn.jsdelivr.net/npm/cowsay";$ deno main.tsNow, you can disallow importing code from one of the default hosts:
$ deno --deny-import=cdn.jsdelivr.net main.ts
error: Requires import access to "cdn.jsdelivr.net:443", run again with the --allow-import flag
at file:///main.ts:1:25To further supplement --allow-import usages, the
Deno.permissions runtime
API has been fixed to support "import" type:
console.log(Deno.permissions.query({ name: "import" }));
// Promise { PermissionStatus { state: "prompt", onchange: null } }Finally, the Deno.execPath()
API doesn’t require read permissions anymore:
console.log(Deno.execPath());# Deno 2.3
$ deno main.ts
┏ ⚠️ Deno requests read access to <exec_path>.
┠─ Requested by `Deno.execPath()` API.
┠─ To see a stack trace for this prompt, set the DENO_TRACE_PERMISSIONS environmental variable.
┠─ Learn more at: https://docs.deno.com/go/--allow-read
┠─ Run again with --allow-read to bypass this prompt.
┗ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions) >
# ✅ Now
$ deno main.ts
/dev/.deno/bin/denoWe made this update because in common scenarios, requiring read permission ends up less secure than not requiring permissions. For example, if a user wants to spawn a Deno subprocess using the current executable, they would do something like:
new Deno.Command(Deno.execPath(), { args: ["eval", "1+1"] }).outputSync();And to run it:
# Deno 2.3
$ deno --allow-read --allow-run=deno spawn.ts
# ✅ Now
$ deno --allow-run=denoBefore Deno 2.4, it was possible to limit the scope of --allow-read flag, but
it required upfront knowledge of where the Deno executable was or a bit of shell
expansion trickery. Most users understandably opted to give a blanket
--allow-read flag instead.
Not requiring read permissions allows the above program to be run with just
--allow-run=deno flag.
Conditional package.json exports
This version ships with support for conditional exports in npm packages.
Conditional exports is a mechanism that allows npm packages to use different exports depending on the user provided conditions.
The stark example here is
the react-server condition
that libraries from the React ecosystem can use to swap out exports for use with
Server Components.
import react from "npm:[email protected]";
console.log(react.Component);$ deno app.jsx
Component: [Function: Component]
$ deno --conditions=react-server app.jsx
undefinedYou can specify arbitrary conditions and as many of them as you want. If the
flag is not used Deno uses following conditions by default: deno, node,
import, default.
We expect most users to not have to use this flag directly, but is a crucial option for the tooling you might depend on.
deno run bare specifiers
Deno v2.4 now supports using bare specifiers as entry points in
deno run.
Imagine you had a deno.json like this:
{
"imports": {
"lume/": "https://deno.land/x/[email protected]/",
"file-server": "jsr:@std/http/file-server",
"cowsay": "npm:cowsay"
}
}You might have expected to be able to deno run file-server and be done with
it. Unfortunately, before Deno 2.4, this didn’t work:
# Before Deno v2.4
$ deno run -ERW lume/cli.ts
error: Module not found "file:///dev/lume/cli.ts".
$ deno run file-server
error: Module not found "file:///dev/file-server".
$ deno run -ER cowsay "Hello there!"
error: Module not found "file:///dev/cowsay".However, in 2.4:
# ✅ In Deno 2.4
$ deno run -ERW lume/cli.ts
🍾 Site built into ./_site
$ deno run file-server
Listening on ...
$ deno run -ER cowsay "Hello there!"
______________
< Hello there! >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||In most cases you can also omit run subcommand, like so
deno -ER cowsay "Hello there!"
deno fmt XML and SVG files
deno fmt will know
automatically format .xml and .svg files for you:
<svg width="100" height="100">
<circle cx="50" cy="50"
r="40" stroke="green" stroke-width="4"
fill="yellow" />
</svg>$ deno fmt
/dev/circle.svg
Formatted 1 file
$ cat circle.svg
<svg width="100" height="100">
<circle
cx="50"
cy="50"
r="40"
stroke="green"
stroke-width="4"
fill="yellow"
/>
</svg>Additionally, formatting .mustache templates is now supported, but requires
--unstable-component flag or unstable.fmt-component option in deno.json.
Better tsconfig.json support
Deno automatically discovers tsconfig.json files next to deno.json and/or
package.json files.
This release also brings better handling for tsconfig.json files, with added
support for "references", "extends", "files", "include" and "exclude"
options. That means you can expect a much better experience when working with
popular frontend frameworks like
Vue, Svelte,
Solid,
Qwik and more.
Simpler Node globals
Deno v2.0 added the process global
for improved compatibility with existing npm ecosystem. But there are more
global variables that were not available in Deno for user code, but were
available for npm packages:
BufferglobalsetImmediateclearImmediate
Additionally, globals like setTimeout and setInterval (as well as their
clear* counterparts) are different globals depending if the context was user
code or in an npm dependency.
To achieve this bifurcation, we used a fairly complex setup hooking into V8 internal APIs to decide if a global is available at a particular call site or not. While the solution was clever, it comes with a high performance cost — on each access of one of these globals, we were walking the stack and checking if the call site is coming from an npm package. Finally, the mental overhead of understanding which globals are available where is non-trivial.
In this release, we’ve made Buffer, global, setImmediate and
clearImmediate available to user code as well. This helps if you are running
an existing Node.js project that relies on these globals, as you no longer need
to use the --unstable-node-globals flag to expose them, since they are now
available everywhere all the time.
Local npm packages
In
Deno v2.3, we introduced a way to use local npm packages.
We received a lot of positive feedback about this issue, but some of you raised
concerns that the patch option can be easily confused with npm patch.
The option has been renamed to links (to better reflect npm link equivalent
functionality). You will receive a deprecation warning when using patch option
instead of links.
{
+ "links": [
- "patch": [
"../cowsay"
]
}In the future we might support npm patch equivalent functionlity out of the
box. If you depend on this tool,
let us know.
Node.js API support
We’ve improved support for Node.js APIs again. Aside from the numerous additions
and fixes that you can dive into in the list below, the highlight is support for
the glob API, as well as
achieving over 95% compatibility for modules such as node:buffer,
node:events, node:querystring, node:quic and node:wasm.
We plan to keep increasing these compatibility numbers in the next release with
focus on modules such as node:crypto, node:http, node:tls, node:worker
and node:zlib.
Additionally, Deno 2.4 will use @types/node version 22.15.14 by default when
type checking.
Finally, here’s the full list of Node.js API fixes:
- Add
fs.glob,fs.globSync,fs.promises.glob process.loadEnvFilecorrectly returnsundefined- Add
internal/http2/utilmodule - Add
fs.fchmodandfs.fchmodSync - Add
fs.fchownandfs.fchownSync - Add
fs.lchmod,fs.promises.lchmodandfs.lchmodSync - Add AES CTR to supported ciphers list
- Add assert.CallTracker
- Add
events.getMaxListeners - Add key length validation in
DiffieHellman.prototype.computeSecret - Type check
LibuvStreamWrap.writeBuffer - Add validation to
Cipherivmethods - Align input validation of
Buffer.compare node:tlsallowsrejectUnauthorized: false- Check OOB when writing to
Buffer - Make
Buffer.fillcorrect - Correct
kMaxLengthvalue ofnode:buffer net.createInterfacedoesn’t require env permission- Add
crypto.timingSafeEqual - Deprecate
HashandHmacconstructors dgrammulticast group membershipcrypto.DiffieHellmanconstructor behaviors- Don’t use user manipulated Response objects, use correct
rawHeadersstructure - Emit
workerevent when a new worker thread is created - Enable
Bufferpool for strings - Export
assert.CallTrackeras named export - Add
fs.promises.lchownandfs.promises.lutimes - Export
StatementSyncfromnode:sqlite - Fix
Buffer.inspectcompatiblity - Fix
crypto.pbkdf2compat - Fix
Database#execshould return undefined - Fix
EventEmitter.on - Fix
getEventListenersinnode:events - Fix
addAbortListener - Fix assertion error message of assert.ok
- Fix buffer.includes edge cases
- Fix buffer.indexOf for ucs2 encoding
- Fix dns.lookup when promisified with
options.all - Fix error type in
crypto.DiffieHellmanconstructor - Fix
events.getEventListeners - Fix
events.once - Correctly export
loadEnvFilefromnode:process - Fix
fs.watchFiletrigger - Fix function error message in
invalidArgTypeHelper - Fix input validation of
crypto.hkdf - Fix inspect of
CustomEvent - Fix oneshot hash validation
- Fix prototype of
asymmetricKeyDetailsofAsymmetricKeyObject - Fix
ReferenceErrorinnode:stream - Fix validation of input in
events.setMaxListeners - Handle
-pflag inspawn - Handle
nullssl options innode:https - Hold weak reference to SQLite database in instances
- Implement
beforeandafterhooks innode:test - Implement
crypto.CertificateAPI - Implement
dgram.setBroadcast - Implement
dgram.setMulticastLoopback - Implement
dgram.setMulticastTTL - Improve
assert.fail - Improve
assert.ifError - Improve comparison of faked objects in
assert.deepStrictEqual - Improve
getaddrinfocompatibility - Improve input validations of
stream/consumers - Improve
crypto.scryptsupport - Include
assert.okinnode:test - Keep BOM in
Buffer.toString('utf8') - Make
Bufferwork with resizable ABs - Make conditional exports work in
require() - Make
DatabaseSync.readOnlyoptional - Mark pool
ArrayBufferas untransferable - Match WebCrypto tag too small error msg with Node
Module.wrapcleanup fornpm:v8-code-cachenode:buffervalidatesINSPECT_MAX_BYTES- Pass Node.js specific flags via
NODE_OPTIONSenv var inspawn - Prevent stdin double read
- Remove duplicated stream classes
- Return
undefinedinstead ofnullinnode:sqlite - Return values in
node:domain - Stub
crypto.getFipsCryptotofalse - Support 2nd arg of
EventEmitter.prototype.listenerCount - Support
DEP0005deprecation warning - Support HTTP over unix sockets
- Support
KeyObjectincrypto.publicEncrypt/crypto.privateDecrypt - Support mTLS connections
- Throw invalid state from
crypto.getAuthTag - Support TLS server unref
- Update
crypto.decipherIverror properties - Update interaction between event emitters and domains
- Update message for
MaxListenersExceededWarning - Use “localhost” as default tls hostname
- Validate auth tag for GCM mode cipher
- Validate prime bigint candidate
- Validate
randomUUID()options - Fix
ServerResponse.reqnot being set - Throw on
assert.deepStrictEqual({}, Object.create(null)) - Support for
t.skipandt.todoinnode:test - Don’t return a smi from
zlib.crc32
LSP improvements
The Deno LSP received numerous improvements including:
deno.configoption in now correctly handled outside of workspace- Jupyter cells correctly handle
for awaitand respect media type fortsx - Use correct resolution kind when checking for no-export-npm
- Lookup bare workspace specifiers for auto-import
- Lookup mapped npm specifier resolutions for auto-import
- Lookup patched jsr packages for auto-import
- Use canonicalized fallback filesystem root
- Truncate JSON files larger than 10Mb
- Don’t diff 10,000+ line files for formatting
- Discard quick fixes importing /node_modules/ paths
- Do not warn about unscoped package name
- Don’t cache jsxImportSource on lockfile-only changes
- Don’t show no-export diagnostics for type-only npm imports
Other fun things
fetchnow works over Unix and Vsock sockets - create an instance ofDeno.HttpClientwith a properproxyoption:
const client = Deno.createHttpClient({
proxy: {
transport: "unix",
path: "/path/to/unix.sock",
},
// or
proxy: {
transport: "vsock",
cid: 2,
port: 80,
},
});
await fetch("http://localhost/ping", { client });deno servenow supportsonListen()callbacks:
export default {
fetch(req) {
return new Response("Hello world!");
},
onListen(addr) {
console.log(
`😎 Hello world server started on ${addr.hostname}:${addr.port}`,
);
},
} satisfies Deno.ServeDefaultExport;$ deno serve server.ts
😎 Hello world server started on 0.0.0.0:8000- Better management of Jupyter kernels with
deno jupyter:
# Give kernel an explicit name
$ deno jupyter --install --name="deno_kernel"
✅ Deno kernelspec installed successfully at /Jupyter/kernels/deno_kernel.
# Don't overwrite existing kernel by mistake
$ deno jupyter --install --name="deno_kernel"
error: Deno kernel already exists at /Jupyter/kernels/deno_kernel, run again with `--force` to overwrite it
# Give a display name to the kernel
deno jupyter --install --display="Deno 2.4 kernel"
# Now you will see "Deno 2.4 kernel" in the kernel selector UI- Lint plugins can now access comments
export default {
name: "my-lint-plugin",
rules: {
"my-lint-rule": {
create(context) {
return {
Program(node) {
console.log("Top level comments", node.comments);
},
FunctionDeclaration(node) {
const all = ctx.sourceCode.getAllComments();
const before = ctx.sourceCode.getCommentsBefore(node);
const after = ctx.sourceCode.getCommentsAfter(node);
const inside = ctx.sourceCode.getCommentsInside(node);
console.log({ program, all, before, after, inside });
},
};
},
},
},
} satisfies Deno.lint.Plugin;deno benchanddeno coveragetables are now Markdown compatible
You can now directly copy-paste them into Markdown documents with proper rendering
# Before
-----------------------------------
File | Branch % | Line % |
-----------------------------------
parser.ts | 87.1 | 86.4 |
tokenizer.ts | 80.0 | 92.3 |
-----------------------------------
All files | 86.1 | 87.4 |
-----------------------------------
# After
| File | Branch % | Line % |
| ------------ | -------- | ------ |
| parser.ts | 87.1 | 86.4 |
| tokenizer.ts | 80.0 | 92.3 |
| All files | 86.1 | 87.4 |- Listening for Ctrl+Close (
SIGHUP) now works correctly on Windows
// This will now work correctly on Windows
Deno.addSignalListener("SIGHUP", () => {
console.log("Got SIGHUP");
});Acknowledgments
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 2.4: 林炳权, André Lima, Andy Vu, Asher Gomez, Boye Lillejord-Nygård, chirsz, Christian Svensson, Clarence Delmacio Manuel, ctrl+d, Cyan, Daniel Osvaldo R, David Emanuel Buchmann, Edilson Pateguana, Efe, Elias Rhouzlane, familyboat, Hajime-san, ikkz, James Bronder, Janosh Riebesell, JasperVanEsveld, Jeff Hykin, Jonh Alexis, Kenta Moriuchi, Kingsword, Laurence Rowe, Lino Le Van, LongYinan, Marshall Walker, MikaelUrankar, nana4gonta, narumincho, Nicholas Berlette, scarf, Scott Kyle, sgasho, Simon Lecoq, stefnotch, Timothy J. Aveni, ud2, Volker Schlecht, and zino.
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 2.4. You can view the full list of pull requests merged in Deno 2.4 on GitHub.
Thank you for catching up with our 2.4 release, and we hope you love building with Deno!
🚨️ There have been major updates to Deno Deploy! 🚨️
- Improved Playgrounds with livestreaming logs, traces, and templates like Next.js
- Automatic and immediate observability and telemetry
- Simpler management for environment variables
and much more!

