diff --git a/node/npm_specifiers.md b/node/npm_specifiers.md index 8f2d770f..0bbb8223 100644 --- a/node/npm_specifiers.md +++ b/node/npm_specifiers.md @@ -1,82 +1,34 @@ # `npm:` specifiers Since version 1.28, Deno has native support for importing npm packages. This is -done by importing using `npm:` specifiers. - -The way these work is best described with an example that you can run with -`deno run --allow-env`: +done by importing using `npm:` specifiers. For example the following code: ```ts, ignore -import chalk from "npm:chalk@5"; - -console.log(chalk.green("Hello!")); -``` - -These npm specifiers have the following format: +import { emojify } from "npm:node-emoji@2"; -```ts, ignore -npm:[@][/] +console.log(emojify(":t-rex: :heart: NPM")); ``` -Another example with express: - -```js, ignore -// main.js -import express from "npm:express@^4.17"; -const app = express(); - -app.get("/", (req, res) => { - res.send("Hello World"); -}); - -app.listen(3000); -console.log("listening on http://localhost:3000/"); -``` - -Then doing the following will start a simple express server: +Can be run with: ```sh -$ deno run -A main.js -listening on http://localhost:3000/ +$ deno run main.js +🦖 ❤️ NPM ``` When doing this, no `npm install` is necessary and no `node_modules` folder is -created. These packages are also subject to the same permissions as Deno -applications. +created. These packages are also subject to the same +[permissions](../basics/permissions.md) as other code in Deno. -## npm executable scripts +npm specifiers have the following format: -npm packages with `bin` entries can be executed from the command line without an -`npm install` using a specifier in the following format: - -```ts, ignore -npm:[@][/] ``` - -For example: - -```sh -$ deno run --allow-env --allow-read npm:cowsay@1.5.0 Hello there! - ______________ -< Hello there! > - -------------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || - -$ deno run --allow-env --allow-read npm:cowsay@1.5.0/cowthink What to eat? - ______________ -( What to eat? ) - -------------- - o ^__^ - o (oo)\_______ - (__)\ )\/\ - ||----w | - || || +npm:[@][/] ``` +For examples with popular libraries, please refer to our +[how-to guides](./how_to_with_npm.md). + ## TypeScript types Many packages ship with types out of the box, you can import those and use them @@ -96,6 +48,36 @@ package: import express from "npm:express@^4.17"; ``` +### Module resolution + +The official TypeScript compiler `tsc` supports different +[moduleResolution](https://www.typescriptlang.org/tsconfig#moduleResolution) +settings. Deno only supports the modern `node16` resolution. Unfortunately many +NPM packages fail to correctly provide types under node16 module resolution, +which can result in `deno check` reporting type errors, that `tsc` does not +report. + +If a default export from an `npm:` import appears to have a wrong type (with the +right type seemingly being available under the `.default` property), it's most +likely that the package provides wrong types under node16 module resolution for +imports from ESM. You can verify this by checking if the error also occurs with +`tsc --module node16` and `"type": "module"` in `package.json` or by consulting +the [Are the types wrong?](https://arethetypeswrong.github.io/) website +(particularly the "node16 from ESM" row). + +If you want to use a package that doesn't support TypeScript's node16 module +resolution, you can: + +1. Open an issue at the issue tracker of the package about the problem. (And + perhaps contribute a fix :) (Although there unfortunately currently is a lack + of tooling for packages to support both ESM and CJS, since default exports + require different syntaxes, see also + [microsoft/TypeScript#54593](https://github.com/microsoft/TypeScript/issues/54593)) +2. Use a [CDN](./cdns.md), that rebuilds the packages for Deno support, instead + of an `npm:` identifier. +3. Ignore the type errors you get in your code base with `// @ts-expect-error` + or `// @ts-ignore`. + ### Including Node types Node ships with many built-in types like `Buffer` that might be referenced in an @@ -110,6 +92,39 @@ Note that it is fine to not specify a version for this in most cases because Deno will try to keep it in sync with its internal Node code, but you can always override the version used if necessary. +## npm executable scripts + +npm packages with `bin` entries can be executed from the command line without an +`npm install` using a specifier in the following format: + +``` +npm:[@][/] +``` + +For example: + +```sh +$ deno run --allow-read npm:cowsay@1.5.0 Hello there! + ______________ +< Hello there! > + -------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || + +$ deno run --allow-read npm:cowsay@1.5.0/cowthink What to eat? + ______________ +( What to eat? ) + -------------- + o ^__^ + o (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + ## `--node-modules-dir` flag npm specifiers resolve npm packages to a central global npm cache. This works