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?
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 standard.
To make the above import lodash from "lodash"
work, add the following to the
deno.json
configuration file.
{
"imports": {
"lodash": "https://esm.sh/lodash@4.17.21"
}
}
The deno.json
file is auto-discovered and acts (among other things) as an
import map.
Read more about deno.json
here.
This also works with npm specifiers. Instead of the above, we could have also
written something similar in our deno.json
configuration file:
{
"imports": {
"lodash": "npm:lodash@^4.17"
}
}
Example - Using deno_std's fmt module via fmt/
{
"imports": {
"fmt/": "https://deno.land/std@0.202.0/fmt/"
}
}
import { red } from "fmt/colors.ts";
console.log(red("hello world"));
Example - Using project root for absolute imports
To use your project root for absolute imports:
{
"imports": {
"/": "./",
"./": "./"
}
}
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 the deno_std import from 0.177.0 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:
{
"imports": {
"https://deno.land/std@0.177.0/": "https://deno.land/std@0.202.0/"
},
"scopes": {
"https://deno.land/x/example/": {
"https://deno.land/std@0.177.0/": "./patched/"
}
}
}
Import Maps are for Applications
It is important to note that import map configuration files are only applied for Deno applications, 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.
If you are developing a library, you should instead prefer to use the deps.ts
pattern discussed in Managing Dependencies.