Skip to content

Commit

Permalink
updating for deno future (#681)
Browse files Browse the repository at this point in the history
  • Loading branch information
thisisjofrank authored Aug 6, 2024
1 parent cbbd02f commit f47988d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 141 deletions.
99 changes: 30 additions & 69 deletions runtime/manual/basics/import_maps.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,65 @@ oldUrl: /runtime/manual/basics/modules/import_maps/
---

In order for Deno to resolve a _bare specifier_ like `"react"` or `"lodash"`, it
needs to be told where to look for it. Does `"lodash"` refer to an npm module or
does it map to an https URL?
needs to be told where to look for it. Does `"lodash"` refer to an module in our
project or does it refer to a third party dependency? Deno needs to know where
to resolve the import specifier `lodash` to.

```ts
import lodash from "lodash";
```

Node and npm use `package.json` and the `node_modules` folder to do this
resolution. Deno, on the other hand, uses the
[import map](https://github.com/WICG/import-maps) standard.

To make the above `import lodash from "lodash"` work, add the following to the
[`deno.json` configuration file](../getting_started/configuration_file.md).
We can point Deno to the `lodash` package on npm, for example, by adding it to
the `"imports"` section in `deno.json`.

```json
{
"imports": {
"lodash": "https://esm.sh/[email protected].21"
"lodash": "npm:lodash@^4.17"
}
}
```

The `"imports"` section in `deno.json` is often referred to as an `import map`
that is based on the
[Import Maps Standard](https://github.com/WICG/import-maps).

You may have seen Node and npm use `package.json` and the `node_modules` folder
to do similar package resolution.

The `deno.json` file is auto-discovered and acts (among other things) as an
import map.
[Read more about `deno.json` here](../getting_started/configuration_file.md).

This also works with npm specifiers. Instead of the above, we could have also
written something similar in our `deno.json` configuration file:

```json
{
"imports": {
"lodash": "npm:lodash@^4.17"
}
}
```

## Example - Using the Deno Standard Library

Running the following:
Using third party modules is explained further in
[ECMAScript Modules](./modules/).

```bash
deno add @std/foo
```
## Custom path mappings

Produces the following:
The import map in `deno.json` can be used for more general path mapping of
specifiers. You can map an exact specifiers to a third party module or a file
directly, or you can map a part of an import specifier to a directory.

```json title="deno.json"
```jsonc title="deno.jsonc"
{
"imports": {
"@std/foo": "jsr:@std/foo@^1.2.3"
// Map to an exact file
"foo": "./some/long/path/foo.ts",
// Map to a directory, usage: "bar/file.ts"
"bar/": "./some/folder/bar/"
}
}
```

The import can then be used in your script:
Usage:

```ts title="bar.ts"
import { bar } from "@std/foo";

bar(1, 2);
```ts
import * as foo from "foo";
import * as bar from "bar/file.ts";
```

## Example - Using project root for absolute imports
Path mapping of import specifies is commonly used in larger code bases for
brevity.

To use your project root for absolute imports:

Expand All @@ -86,37 +81,3 @@ import { MyUtil } from "/util.ts";

This causes import specifiers starting with `/` to be resolved relative to the
import map's URL or file path.

## Overriding imports

The other situation where import maps can be very useful is to override imports
in specific modules.

Let's say you want to override a Deno Standard Library package import from
^1.2.3 to the latest in all of your imported modules, but for the
`https://deno.land/x/example/` module you want to use files in a local `patched`
directory. You can do this by using a scope in the import map that looks
something like this:

```json
{
"imports": {
"@std/foo": "jsr:@std/foo@^1.2.3"
},
"scopes": {
"https://deno.land/x/example/": {
"@std/foo": "./patched/mod.ts"
}
}
}
```

## Import Maps are for Applications

It is important to note that import map configuration files are
[only applied for Deno applications][scope], not in the various libraries that
your application code may import. This lets you, the application author, have
final say about what versions of libraries get included in your project.

[scope]: https://github.com/WICG/import-maps#scope
[Environment Variables]: /runtime/manual/basics/env_variables/
143 changes: 71 additions & 72 deletions runtime/manual/basics/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,86 @@
title: "ECMAScript Modules in Deno"
---

## Concepts

- [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
allows you to include and use modules held elsewhere, on your local file
system or remotely.
- [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
allows you to specify which parts of your module are accessible to users who
import your module.

## Overview

Deno by default standardizes the way modules are imported in both JavaScript and
TypeScript using the ECMAScript 6 `import/export` standard.

It adopts browser-like module resolution, meaning that file names must be
specified in full. You may not omit the file extension and there is no special
handling of `index.js`.

```js
import { add, multiply } from "./arithmetic.ts";
```

Dependencies are also imported directly, there is no package management
overhead. Local modules are imported in exactly the same way as remote modules.
As the examples show below, the same functionality can be produced in the same
way with local or remote modules.

## Local Import

In this example the `add` and `multiply` functions are imported from a local
`arithmetic.ts` module.

**Command:** `deno run local.ts`
TypeScript using the
[ECMAScript module standard](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules).
In line with this standard, **file names must be specified in full**. You should
not omit the file extension and there is no special handling of `index.js`.

```ts
import { add, multiply } from "./arithmetic.ts";

function totalCost(outbound: number, inbound: number, tax: number): number {
return multiply(add(outbound, inbound), tax);
}

console.log(totalCost(19, 31, 1.2)); // 60
console.log(totalCost(45, 27, 1.15)); // 82.8
// Always include the file extension
import { add } from "./calc.ts";
```

## Export
## Importing modules

In the local import example above the `add` and `multiply` functions are
imported from a locally stored arithmetic module. To make this possible the
functions stored in the arithmetic module must be exported.
In this example the `add` function is imported from a local `calc.ts` module.

To do this just add the keyword `export` to the beginning of the function
signature as is shown below.

```ts
```ts title="calc.ts"
export function add(a: number, b: number): number {
return a + b;
}
```

export function multiply(a: number, b: number): number {
return a * b;
}
```ts title="main.ts"
import { add } from "./calc.ts";

console.log(add(1, 2)); // 3
```

All functions, classes, constants and variables which need to be accessible
inside external modules must be exported. Either by prepending them with the
`export` keyword or including them in an export statement at the bottom of the
file.
You can run this example by calling `deno run main.ts` in the directory that
contains `main.ts` and `calc.ts`.

## Using third party modules and libraries with Deno
## Adding third party modules and libraries to deno.json

Using remote modules (downloaded from a registry) in Deno uses the same `import`
syntax as your local code.

The modules that you add to your project are tracked as `imports` in
`deno.json` - we call this the import map.

```json
```json title="deno.json"
{
"tasks": {
"dev": "deno run --watch main.ts"
},
"imports": {
"@scopename/mypackage": "jsr:@scopename/mypackage@^16.1.0"
}
}
```

You can add modules using the `Deno CLI` subcommand `deno add`
You can add modules using the `deno add` subcommand:

```bash
$ deno add @scopename/mypackage
Add @scopename/mypackage - jsr:@scopename/mypackage@^16.1.0
```sh
# Add the latest version of the module to deno.json
$ deno add @luca/cases
Add @luca/cases - jsr:@luca/cases@^1.0.0
```

Deno add will automatically add the latest version of the module you requested
to your project imports. If you're coming from the `node` ecosystem, this is
equivalent to `npm install PACKAGE --save`.
```json title="deno.json"
{
"imports": {
"@luca/cases": "jsr:@luca/cases@^1.0.0"
}
}
```

## Using Imported Packages
The `deno add` command will automatically add the latest version of the module
you requested to your project imports, unless you specify an exact version:

```sh
# Passing an exact version
$ deno add @luca/[email protected]
Add @luca/cases - jsr:@luca/cases@^1.0.0
```

## Using installed modules

Once a package is added to the import map in `deno.json`, you can import the
module by its name, and Deno will automatically resolve the module.
module by its name, and Deno will automatically resolve the module. For example:

```ts title="mod.ts"
import { someFunction } from "@scopename/mypackage";
```ts title="main.ts"
import { camelCase } from "@luca/cases";

someFunction();
camelCase("hello world"); // "helloWorld"
```

## Package Registries
Expand Down Expand Up @@ -227,6 +199,33 @@ not generally recommend this approach for third-party components.
URL imports remain supported, **but we recommend using a package registry for
the best experience.**

### Overriding URL imports

The other situation where import maps can be very useful is to override URL
imports in specific modules.

Let's say you want to override a `https://deno.land/x/[email protected]/mod.ts`
specifier that is used inside files coming from `https://deno.land/x/example/`
to a local patched version. You can do this by using a scope in the import map
that looks something like this:

```json
{
"imports": {
"example/": "https://deno.land/x/example/"
},
"scopes": {
"https://deno.land/x/example/": {
"https://deno.land/x/[email protected]/mod.ts": "./patched/mod.ts"
}
}
}
```

_It is important to note that URL imports have no notion of packages. Only the
import map at the root of your project is used. Import maps used inside URL
dependencies are ignored._

## Proxies

Deno supports proxies for module downloads and the Web standard `fetch` API.
Expand Down

0 comments on commit f47988d

Please sign in to comment.