On this page
- Create and run a TypeScript program
- Built-in web APIs and the Deno namespace
- Runtime security
- Importing JavaScript modules
- Remote modules and the Deno standard library
- Configure your project with deno.json
- Node.js APIs and npm packages
- Configure your IDE
- Web application frameworks
- Deploying to production
- Next Steps
First Steps
Welcome to Deno! If you're just getting started, here's a primer on some key features and functionality of the runtime. If you haven't already, make sure to install the Deno runtime.
Create and run a TypeScript program Jump to heading
While you are welcome to use JavaScript, Deno has built-in support for
TypeScript as well. In your terminal, create
a new file called hello.ts
, and include the following code.
interface Person {
firstName: string;
lastName: string;
}
function sayHello(p: Person): string {
return `Hello, ${p.firstName}!`;
}
const ada: Person = {
firstName: "Ada",
lastName: "Lovelace",
};
console.log(sayHello(ada));
This program declares an
interface
for a Person, and defines a function that prints a message to the console using
this data type. You can execute the code in this example using the deno run
command.
deno run hello.ts
You can learn more about using TypeScript in Deno here.
Built-in web APIs and the Deno namespace Jump to heading
Deno aims to provide a browser-like programming environment,
implementing web standard APIs that exist in
front-end JavaScript. For example, the
fetch
API is
available in the global scope, just as in the browser. To see this in action,
replace the contents of hello.ts
with the following code.
const site = await fetch("https://www.deno.com");
console.log(await site.text());
Because this example is fetching data from across the internet, you will need to
allow network permissions. You can give network permissions with the
--allow-net
flag or by using -A
to allow all permissions. We'll look at
permissions and security in more depth later on. Run the example with:
deno run -A hello.ts
For APIs that don't exist as a web standard (like accessing variables from the
system environment, or manipulating the file system), those APIs are exposed in
the Deno namespace. Replace the contents of
hello.ts
with the following code, which will start
an HTTP server on
localhost:8000.
Deno.serve((_request: Request) => {
return new Response("Hello, world!");
});
Save your changes and run the script.
deno run -A hello.ts
Learn more about the web-standard APIs built in to Deno and the Deno namespace APIs.
Runtime security Jump to heading
A major feature of Deno is runtime security by default, meaning that you must explicitly allow your code to access potentially sensitive APIs like file system access, network connectivity, and access to environment variables.
So far, we've been running all of our scripts with the -A
flag, which grants
all runtime feature access to our scripts. This is the most permissive mode to
run a Deno program, but usually you'll want to grant your code only the
permissions it needs to run.
To see this in action, let's replace the contents of hello.ts
with the fetch
example from earlier.
const site = await fetch("https://www.deno.com");
console.log(await site.text());
Run this program without the -A
flag - what happens then?
deno run hello.ts
Without any permission flags passed in, you'll see security prompts that look something like this:
$ deno run index.ts
✅ Granted net access to "www.deno.com".
┌ ⚠️ Deno requests net access to "deno.com".
├ Requested by `fetch()` API.
├ Run again with --allow-net to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) >
In the prompt, you might have noticed that it mentions the CLI flag you'd need
to run your code with permission to access the network - the --allow-net
flag.
If you run the script again using this flag, you won't be prompted to
interactively grant network access to your script:
deno run --allow-net hello.ts
For simplicity, we will sometimes show examples that use deno run -A ...
, but
whenever possible (and in your production or CI environments), we encourage you
to take advantage of Deno's full suite of
configurable runtime security options.
Importing JavaScript modules Jump to heading
Most of the time, you will want to break up your program into multiple files. Again favoring web standards and a browser-like programming model, Deno supports this through ECMAScript modules. Consider the earlier TypeScript example we showed you:
interface Person {
firstName: string;
lastName: string;
}
function sayHello(p: Person): string {
return `Hello, ${p.firstName}!`;
}
const ada: Person = {
firstName: "Ada",
lastName: "Lovelace",
};
console.log(sayHello(ada));
You might want to break this program up such that the Person
interface and the
sayHello
function are in a separate module. To do this, create a new file in
the same directory called person.ts
and include the following code:
export default interface Person {
firstName: string;
lastName: string;
}
export function sayHello(p: Person): string {
return `Hello, ${p.firstName}!`;
}
This module creates a
named export
for the sayHello
function, and a
default export
for the Person
interface.
Back in hello.ts
, you can consume this module using the import
keyword.
import Person, { sayHello } from "./person.ts";
const ada: Person = {
lastName: "Lovelace",
firstName: "Ada",
};
console.log(sayHello(ada));
Note that file extensions are required when importing modules - import logic in Deno works as it does in the browser, where you would include the full file name of your imports.
You can learn more about the module system in Deno here.
Remote modules and the Deno standard library Jump to heading
Deno supports loading and executing code from URLs, much as you would using a
<script>
tag in the browser. In Deno 1.x, the
standard library and most
third-party modules are distributed on HTTPS URLs.
To see this in action, let's create a test for the person.ts
module we created
above. Deno provides a built-in test runner, which
uses an assertion module distributed via HTTPS URL.
import { assertEquals } from "https://deno.land/std@0.224.0/assert/mod.ts";
import Person, { sayHello } from "./person.ts";
Deno.test("sayHello function", () => {
const grace: Person = {
lastName: "Hopper",
firstName: "Grace",
};
assertEquals("Hello, Grace!", sayHello(grace));
});
Run this test with:
deno test person_test.ts
The output should look something like this:
$ deno test person_test.ts
Check file:///Users/kevin/dev/denoland/scratchpad/person_test.ts
running 1 test from ./person_test.ts
sayHello function ... ok (4ms)
ok | 1 passed | 0 failed (66ms)
There's much more to explore with the standard library and third-party modules - be sure to check them out!
Configure your project with deno.json Jump to heading
Deno projects don't require a configuration file by default, but sometimes it's
convenient to store settings, admin scripts, and dependency configuration in a
well-known location. In Deno, that file is
deno.json
or deno.jsonc
. This
file acts a bit like a package.json
file in Node.js.
One of the things you can use deno.json
for is configuring an
import map, which will let you set up aliases for
frequently used modules.
To demonstrate, let's pin the version of the standard library we want to
use in our project to version 0.224.0
.
Create a deno.jsonc
file with the following contents.
{
"imports": {
// The dollar sign in front of "std" isn't special - it's an optional
// convention to show that $std is an alias set up in an import map
"$std/": "https://deno.land/std@0.224.0/"
}
}
Now, open up your test file from before, and change it to use this import alias.
import { assertEquals } from "$std/assert/mod.ts";
import Person, { sayHello } from "./person.ts";
Deno.test("sayHello function", () => {
const grace: Person = {
lastName: "Hopper",
firstName: "Grace",
};
assertEquals("Hello, Grace!", sayHello(grace));
});
Running the test with deno test person_test.ts
should work just as before, but
you might notice that Deno downloads a few extra files and generates a
deno.lock
file, specifying a set of files depended on by your code. Both
deno.jsonc
and deno.lock
can be checked in to source control.
Learn more about configuring your project here.
Node.js APIs and npm packages Jump to heading
Deno provides a compatibility layer that enables your code to use
Node.js built-in modules and third-party modules from npm.
Using Node and npm modules in your code looks a lot like using standard Deno
modules, except you'll use either a node:
or npm:
specifier when importing
Node built-ins or npm modules, respectively.
To see how it works, create a file called server.js
and include the
following - a simple HTTP server using the popular
Express framework.
import express from "npm:express@4";
const app = express();
app.get("/", (request, response) => {
response.send("Hello from Express!");
});
app.listen(3000);
With node:
and npm:
specifiers, you can bring the best of the Node.js
ecosystem with you to Deno.
Learn more about Node and npm support.
Configure your IDE Jump to heading
Deno development is supported in a number of
major IDEs. A popular option is
Visual Studio Code, with an
official extension maintained by the Deno
team.
Install the extension
and enable it in your VS Code workspace by choosing the
Deno: Initialize Workspace Configuration
option in the
command palette.
Not a VS Code user? Find an integration for your favorite editor here.
Web application frameworks Jump to heading
A common use case for Deno is building data-driven web applications. Doing that usually requires use of a higher-level web framework, for which many options exist in the Deno ecosystem. Here are a few of the most popular choices.
Deno-native frameworks Jump to heading
- Deno Fresh - Fresh is a web framework designed for Deno. Pages are server-rendered by default, with the option to include interactive islands that run JavaScript on the client. If you're new to Deno and looking for a place to start, we recommend trying Fresh first!
- Hono - Hono is a light-weight web framework in the tradition of Express. Great for API servers and simple web applications.
Deno-compatible frameworks Jump to heading
- SvelteKit - SvelteKit is another more runtime-agnostic web framework that can be used with Deno. We recommend starting with this template.
- Nuxt (Vue) - Nuxt is a hybrid SSR and client-side framework that works with Deno. We recommend starting with this template.
- Astro - Astro is a modern web framework that was originally designed for Node.js, but runs great on Deno as well. We recommend starting with this template.
Many more frameworks support Deno than are listed here, but we'd recommend these as a great starting point.
Deploying to production Jump to heading
When you're ready to move into production, your easiest option will be Deno Deploy. Deno Deploy makes it easy to create fast, globally distributed serverless applications with Deno.
You can also host Deno in almost any cloud environment.
Next Steps Jump to heading
We've only just scratched the surface of what's possible with Deno. Here are a few resources to check out next.
- Set up your dev environment - Learn about options for configuring your local dev environment
- Tutorials and Examples - Sample code and use cases for Deno
- Deno by Example - Code snippets to learn Deno by example