Deno 1.28: Featuring 1.3 Million New Modules
We’re excited to announce that Deno 1.28 stabilizes npm compatibility, which means you can now import over 1.3 million npm modules in Deno. Building apps will be easier and more secure than ever, now that you can use your favorite persistent data modules such as Prisma, Mongoose, and MySQL, as well as frontend frameworks such as React, Vue, etc.
Using npm is easier and safer with Deno. Deno’s built-in toolchain, first-class std library, and robust IDE support means you can be productive, faster. And Deno’s secure-by-default, opt-in permissions model means spending less time worrying about suspicious packages and more time shipping product.
Deno maintains that modern JavaScript should be built with ES Modules and web
standard APIs. This release does not change that. Importing npm modules is done
through URLs in a standard compliant fashion - we continue to move towards a
browser-compatible future, where you’re using web APIs such as fetch
,
Request
, and Response
. Now, Deno is taking npm a step forward by allowing
you to access your favorite modules in a modern, secure programming environment.
To help you get started using npm modules with Deno, we’ll be publishing resources, how-to guides, and more every day this week. Be sure to follow our Twitter and subscribe to our YouTube to follow along.
In this post:
Installing or Upgrading Deno
If you already have Deno installed, you can upgrade to 1.28 by running:
deno upgrade
If you are installing Deno for the first time:
# MacOS and Linux
curl -fsSL https://deno.land/install.sh | sh
# Windows
irm https://deno.land/install.ps1 | iex
Click here for more installation options.
Using npm
You can use npm packages by importing an npm:
specifier.
In an import statement:
import { chalk } from "npm:chalk@5";
Or map a bare specifier to an npm specifier in an import map:
{
"imports": {
"chalk": "npm:chalk@5"
}
}
You can also run npm scripts or CLIs using Deno:
deno run --allow-env --allow-read npm:create-vite-extra
You can even execute npm packages with subcommands like this:
deno run npm:<package_name> <subcommand>
For example, the equivalent of npx prisma init
in Deno is:
deno run npm:prisma init
Security
While npm has made software easily usable and shareable, the unchecked approach to installing and running dependencies has made Node and npm susceptible to supply chain attacks. Through typosquatting, social engineering, and other exploits, malicious modules can be uploaded and then installed into production Node applications, compromising millions of users and their sensitive data.
Instead of allowing untrusted, third-party code to have access to your entire system, Deno’s secure-by-default approach can inform and restrict you when your dependencies attempt to access the system.
deno run npm:install-malware
⚠️ ┌ Deno requests write access to /usr/bin/.
├ Requested by `install-malware`
├ Run again with --allow-write to bypass this prompt.
└ Allow? [y/n] (y = yes, allow; n = no, deny) >
Learn more about Deno’s opt-in permissions system.
package.json
No Using npm with Deno is simpler:
- No
npm install
step: modules are installed the first time you run your program. - No
package.json
: less boilerplate noise cluttering your code base. - No
node_modules
folder by default (use--node-modules-dir
for backwards compatibility). Modules are cached once in a special global directory.
Be productive immediately with Deno. With a built-in toolchain (including tester, formatter, linter, and more) and native TypeScript support, you can skip installing and configuring dependencies and dive right into the code.
Ongoing Work
Our aim is to make as many npm modules compatible with Deno as possible. Some
modules may not be compatible (yet) due to some edge cases we haven’t come
across, post-install scripts, or assumptions a few packages make about executing
in a folder with a typical Node setup (e.g. assuming a package.json
exists in
the current working directory).
We’ll be working hard over the next few months to address these issues and
improve our compatibility. For example, we’ve currently repurposed some of
Node’s test suites to ensure our Node compatibility layer (e.g. modules like
fs
) works the same as Node’s and we’ll be expanding this coverage. We’re also
actively fixing any edge cases surfaced by our community.
Some subcommands in Deno like deno compile
do not yet work with npm modules.
This work is being tracked in
deno#15960.
To help us increase compatibility with npm, if you run into any problems using npm with Deno, please open an issue. We’re confident that with more usage, we’ll close most of the remaining compatibility gaps.
Auto discovery of the lock file
Deno has had support for lock files since v1.0, however the experience of using
them left much to be desired - it was always a user’s responsibility to provide
the --lock=<filename>
flag to use a lockfile. We recognize that this situation
led to many users not using a lock file at all.
Starting with Deno v1.28, the lock file will be automatically discovered and
used if a configuration file (deno.json(c)
) is discovered. In such case, a
lock file will automatically be created (if one doesn’t exist yet), next to the
configuration file, with the deno.lock
name. The lock file will be
automatically and additively updated if new dependencies become part of the
module graph.
As a consequence, the --lock-write
flag’s behavior has expanded for this
auto-discovery scenario - instead of needing to pass this flag to update the
lock file, it now can be used to force the generation of the lock file from
scratch.
If you wish to disable automatic discovery of the lock file, you can use the
--no-lock
flag.
Additionally, the --lock
flag no longer requires an argument by default
anymore - if it is omitted, then Deno will default to ./deno.lock
.
Deno
APIs
Changes to Stabilizations
The following APIs have been stabilized in this release and no longer require
the --unstable
flag to be used.
Deno.bench()
Deno.gid()
Deno.networkInterfaces()
Deno.systemMemoryInfo()
Deno.uid()
Deno.Command
API
New unstable This release adds a new unified Deno.Command
API to supersede the unstable
Deno.spawn
, Deno.spawnSync
, and Deno.spawnChild
APIs.
Basic async usage:
let c = new Deno.Command("echo", { args: ["foo"] });
let { stdout, stderr } = await c.output();
Basic sync usage:
let c = new Deno.Command("echo", { args: ["foo"] });
let { stdout, stderr } = c.outputSync();
Advanced async usage (with streaming):
const c = new Deno.Command("cat", { stdin: "piped" });
c.spawn();
// open a file and pipe input from `cat` program to the file
const file = await Deno.open("output.txt", { write: true });
await c.stdout.pipeTo(file.writable);
const stdin = c.stdin.getWriter();
await stdin.write(new TextEncoder().encode("foobar"));
await stdin.close();
const s = await c.status;
console.log(s);
V8 10.9
This release upgrades to the latest release of V8 (10.9, previously 10.8). Mostly these are internal improvements but also includes a few public facing API changes:
A full list of changes between 10.8 and 10.9 is here.
Manual rewrite
As Deno has grown, so too has the Manual. We continuously added things here and there; overtime this has led it to become a bit untidy. In this release, we’ve done a full refactoring of the table of contents and prose to be simpler and more organized. We’ve even added an entire section dedicated to using npm.
There’s always room for improvement in documentation - if you see an area that could be improved please submit a PR to denoland/manual.
Launch Week
To demonstrate what you can now build with npm and Deno, we will be releasing tutorials, how-to guides, video walkthroughs on our YouTube, and other helpful resources every day this week.
And if you’re using Deno in a commercial setting and have any technical questions, please sign up for Office Hours, where you can have access to our engineers, who’ll help unblock you for 30 minutes.
Follow our Twitter and subscribe to our YouTube so you don’t miss out on anything!