Spaces:
Paused
Paused
| # Nano ID | |
| <img src="https://ai.github.io/nanoid/logo.svg" align="right" | |
| alt="Nano ID logo by Anton Lovchikov" width="180" height="94"> | |
| A tiny, secure, URL-friendly, unique string ID generator for JavaScript. | |
| > “An amazing level of senseless perfectionism, | |
| > which is simply impossible not to respect.” | |
| * **Small.** 108 bytes (minified and gzipped). No dependencies. | |
| [Size Limit] controls the size. | |
| * **Fast.** It is 60% faster than UUID. | |
| * **Safe.** It uses cryptographically strong random APIs. | |
| Can be used in clusters. | |
| * **Compact.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`). | |
| So ID size was reduced from 36 to 21 symbols. | |
| * **Portable.** Nano ID was ported | |
| to [14 programming languages](#other-programming-languages). | |
| ```js | |
| import { nanoid } from 'nanoid' | |
| model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" | |
| ``` | |
| Supports modern browsers, IE [with Babel], Node.js and React Native. | |
| [online tool]: https://gitpod.io/#https://github.com/ai/nanoid/ | |
| [with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/ | |
| [Size Limit]: https://github.com/ai/size-limit | |
| <a href="https://evilmartians.com/?utm_source=nanoid"> | |
| <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" | |
| alt="Sponsored by Evil Martians" width="236" height="54"> | |
| </a> | |
| ## Table of Contents | |
| * [Comparison with UUID](#comparison-with-uuid) | |
| * [Benchmark](#benchmark) | |
| * [Tools](#tools) | |
| * [Security](#security) | |
| * [Usage](#usage) | |
| * [JS](#js) | |
| * [IE](#ie) | |
| * [React](#react) | |
| * [Create React App](#create-react-app) | |
| * [React Native](#react-native) | |
| * [Rollup](#rollup) | |
| * [Expo](#expo) | |
| * [PouchDB and CouchDB](#pouchdb-and-couchdb) | |
| * [Mongoose](#mongoose) | |
| * [ES Modules](#es-modules) | |
| * [Web Workers](#web-workers) | |
| * [CLI](#cli) | |
| * [Other Programming Languages](#other-programming-languages) | |
| * [API](#api) | |
| * [Async](#async) | |
| * [Non-Secure](#non-secure) | |
| * [Custom Alphabet or Size](#custom-alphabet-or-size) | |
| * [Custom Random Bytes Generator](#custom-random-bytes-generator) | |
| ## Comparison with UUID | |
| Nano ID is quite comparable to UUID v4 (random-based). | |
| It has a similar number of random bits in the ID | |
| (126 in Nano ID and 122 in UUID), so it has a similar collision probability: | |
| > For there to be a one in a billion chance of duplication, | |
| > 103 trillion version 4 IDs must be generated. | |
| There are three main differences between Nano ID and UUID v4: | |
| 1. Nano ID uses a bigger alphabet, so a similar number of random bits | |
| are packed in just 21 symbols instead of 36. | |
| 2. Nano ID code is **4.5 times less** than `uuid/v4` package: | |
| 108 bytes instead of 483. | |
| 3. Because of memory allocation tricks, Nano ID is **60%** faster than UUID. | |
| ## Benchmark | |
| ```rust | |
| $ node ./test/benchmark.js | |
| nanoid 2,280,683 ops/sec | |
| customAlphabet 1,851,117 ops/sec | |
| uuid v4 1,348,425 ops/sec | |
| uid.sync 313,306 ops/sec | |
| secure-random-string 294,161 ops/sec | |
| cuid 158,988 ops/sec | |
| shortid 37,222 ops/sec | |
| Async: | |
| async nanoid 95,500 ops/sec | |
| async customAlphabet 93,800 ops/sec | |
| async secure-random-string 90,316 ops/sec | |
| uid 85,583 ops/sec | |
| Non-secure: | |
| non-secure nanoid 2,641,654 ops/sec | |
| rndm 2,447,086 ops/sec | |
| ``` | |
| Test configuration: Dell XPS 2-in-1 7390, Fedora 32, Node.js 15.1. | |
| ## Tools | |
| * [ID size calculator] shows collision probability when adjusting | |
| the ID alphabet or size. | |
| * [`nanoid-dictionary`] with popular alphabets to use with `customAlphabet`. | |
| * [`nanoid-good`] to be sure that your ID doesn’t contain any obscene words. | |
| [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary | |
| [ID size calculator]: https://zelark.github.io/nano-id-cc/ | |
| [`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good | |
| ## Security | |
| *See a good article about random generators theory: | |
| [Secure random values (in Node.js)]* | |
| * **Unpredictability.** Instead of using the unsafe `Math.random()`, Nano ID | |
| uses the `crypto` module in Node.js and the Web Crypto API in browsers. | |
| These modules use unpredictable hardware random generator. | |
| * **Uniformity.** `random % alphabet` is a popular mistake to make when coding | |
| an ID generator. The distribution will not be even; there will be a lower | |
| chance for some symbols to appear compared to others. So, it will reduce | |
| the number of tries when brute-forcing. Nano ID uses a [better algorithm] | |
| and is tested for uniformity. | |
| <img src="img/distribution.png" alt="Nano ID uniformity" | |
| width="340" height="135"> | |
| * **Vulnerabilities:** to report a security vulnerability, please use | |
| the [Tidelift security contact](https://tidelift.com/security). | |
| Tidelift will coordinate the fix and disclosure. | |
| [Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba | |
| [better algorithm]: https://github.com/ai/nanoid/blob/master/index.js | |
| ## Usage | |
| ### JS | |
| The main module uses URL-friendly symbols (`A-Za-z0-9_-`) and returns an ID | |
| with 21 characters (to have a collision probability similar to UUID v4). | |
| ```js | |
| import { nanoid } from 'nanoid' | |
| model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" | |
| ``` | |
| If you want to reduce the ID size (and increase collisions probability), | |
| you can pass the size as an argument. | |
| ```js | |
| nanoid(10) //=> "IRFa-VaY2b" | |
| ``` | |
| Don’t forget to check the safety of your ID size | |
| in our [ID collision probability] calculator. | |
| You can also use a [custom alphabet](#custom-alphabet-or-size) | |
| or a [random generator](#custom-random-bytes-generator). | |
| [ID collision probability]: https://zelark.github.io/nano-id-cc/ | |
| ### IE | |
| If you support IE, you need to [transpile `node_modules`] by Babel | |
| and add `crypto` alias: | |
| ```js | |
| // polyfills.js | |
| if (!window.crypto) { | |
| window.crypto = window.msCrypto | |
| } | |
| ``` | |
| ```js | |
| import './polyfills.js' | |
| import { nanoid } from 'nanoid' | |
| ``` | |
| [transpile `node_modules`]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/ | |
| ### React | |
| **Do not** call `nanoid` in the `key` prop. In React, `key` should be consistent | |
| among renders. | |
| This is the bad example: | |
| ```jsx | |
| <Item key={nanoid()} /> /* DON’T DO IT */ | |
| ``` | |
| This is the good example (`id` will be generated only once): | |
| ```jsx | |
| const Element = () => { | |
| const [id] = React.useState(nanoid) | |
| return <Item key={id} /> | |
| } | |
| ``` | |
| If you want to use Nano ID in the `id` prop, you must set some string prefix | |
| (it is invalid for the HTML ID to start with a number). | |
| ```jsx | |
| <input id={'id' + this.id} type="text"/> | |
| ``` | |
| ### Create React App | |
| Create React App has [a problem](https://github.com/ai/nanoid/issues/205) | |
| with ES modules packages. | |
| ``` | |
| TypeError: (0 , _nanoid.nanoid) is not a function | |
| ``` | |
| [Pull request](https://github.com/facebook/create-react-app/pull/8768) was sent, | |
| but it was still not released. | |
| Use Nano ID 2 `npm i nanoid@^2.0.0` until Create React App 4.0 release. | |
| ### React Native | |
| React Native does not have built-in random generator. | |
| 1. Check [`react-native-get-random-values`] docs and install it. | |
| 2. Import it before Nano ID. | |
| ```js | |
| import 'react-native-get-random-values' | |
| import { nanoid } from 'nanoid' | |
| ``` | |
| For Expo framework see the next section. | |
| [`react-native-get-random-values`]: https://github.com/LinusU/react-native-get-random-values | |
| ### Rollup | |
| For Rollup you will need [`@rollup/plugin-replace`] to replace | |
| `process.env.NODE_ENV`: | |
| ```js | |
| plugins: [ | |
| replace({ | |
| 'process.env.NODE_ENV': JSON.stringify(process.env.NODE) | |
| }) | |
| ] | |
| ``` | |
| [`@rollup/plugin-replace`]: https://github.com/rollup/plugins/tree/master/packages/replace | |
| ### Expo | |
| If you use Expo in React Native, you need a different workaround. | |
| 1. Install [`expo-random`](https://www.npmjs.com/package/expo-random). | |
| 2. Use `nanoid/async` instead of `nanoid`. | |
| 3. Import `index.native.js` file directly. | |
| ```js | |
| import { nanoid } from 'nanoid/async/index.native' | |
| async function createUser () { | |
| user.id = await nanoid() | |
| } | |
| ``` | |
| [`expo-random`]: https://www.npmjs.com/package/expo-random | |
| ### PouchDB and CouchDB | |
| In PouchDB and CouchDB, IDs can’t start with an underscore `_`. | |
| A prefix is required to prevent this issue, as Nano ID might use a `_` | |
| at the start of the ID by default. | |
| Override the default ID with the following option: | |
| ```js | |
| db.put({ | |
| _id: 'id' + nanoid(), | |
| … | |
| }) | |
| ``` | |
| ### Mongoose | |
| ```js | |
| const mySchema = new Schema({ | |
| _id: { | |
| type: String, | |
| default: () => nanoid() | |
| } | |
| }) | |
| ``` | |
| ### ES Modules | |
| Nano ID provides ES modules. You do not need to do anything to use Nano ID | |
| as ESM in webpack, Rollup, Parcel, or Node.js. | |
| ```js | |
| import { nanoid } from 'nanoid' | |
| ``` | |
| For quick hacks, you can load Nano ID from CDN. Special minified | |
| `nanoid.js` module is available on jsDelivr. | |
| Though, it is not recommended to be used in production | |
| because of the lower loading performance. | |
| ```js | |
| import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js' | |
| ``` | |
| ### Web Workers | |
| Web Workers do not have access to a secure random generator. | |
| Security is important in IDs when IDs should be unpredictable. | |
| For instance, in "access by URL" link generation. | |
| If you do not need unpredictable IDs, but you need to use Web Workers, | |
| you can use the non‑secure ID generator. | |
| ```js | |
| import { nanoid } from 'nanoid/non-secure' | |
| nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ" | |
| ``` | |
| Note: non-secure IDs are more prone to collision attacks. | |
| ### CLI | |
| You can get unique ID in terminal by calling `npx nanoid`. You need only | |
| Node.js in the system. You do not need Nano ID to be installed anywhere. | |
| ```sh | |
| $ npx nanoid | |
| npx: installed 1 in 0.63s | |
| LZfXLFzPPR4NNrgjlWDxn | |
| ``` | |
| If you want to change alphabet or ID size, you should use [`nanoid-cli`]. | |
| [`nanoid-cli`]: https://github.com/twhitbeck/nanoid-cli | |
| ### Other Programming Languages | |
| Nano ID was ported to many languages. You can use these ports to have | |
| the same ID generator on the client and server side. | |
| * [C#](https://github.com/codeyu/nanoid-net) | |
| * [C++](https://github.com/mcmikecreations/nanoid_cpp) | |
| * [Clojure and ClojureScript](https://github.com/zelark/nano-id) | |
| * [Crystal](https://github.com/mamantoha/nanoid.cr) | |
| * [Dart](https://github.com/pd4d10/nanoid-dart) | |
| * [Deno](https://github.com/ianfabs/nanoid) | |
| * [Go](https://github.com/matoous/go-nanoid) | |
| * [Elixir](https://github.com/railsmechanic/nanoid) | |
| * [Haskell](https://github.com/4e6/nanoid-hs) | |
| * [Janet](https://sr.ht/~statianzo/janet-nanoid/) | |
| * [Java](https://github.com/aventrix/jnanoid) | |
| * [Nim](https://github.com/icyphox/nanoid.nim) | |
| * [PHP](https://github.com/hidehalo/nanoid-php) | |
| * [Python](https://github.com/puyuan/py-nanoid) | |
| with [dictionaries](https://pypi.org/project/nanoid-dictionary) | |
| * [Ruby](https://github.com/radeno/nanoid.rb) | |
| * [Rust](https://github.com/nikolay-govorov/nanoid) | |
| * [Swift](https://github.com/antiflasher/NanoID) | |
| Also, [CLI] is available to generate IDs from a command line. | |
| [CLI]: #cli | |
| ## API | |
| ### Async | |
| To generate hardware random bytes, CPU collects electromagnetic noise. | |
| In the synchronous API during the noise collection, the CPU is busy and | |
| cannot do anything useful in parallel. | |
| Using the asynchronous API of Nano ID, another code can run during | |
| the entropy collection. | |
| ```js | |
| import { nanoid } from 'nanoid/async' | |
| async function createUser () { | |
| user.id = await nanoid() | |
| } | |
| ``` | |
| Unfortunately, you will lose Web Crypto API advantages in a browser | |
| if you use the asynchronous API. So, currently, in the browser, you are limited | |
| with either security or asynchronous behavior. | |
| ### Non-Secure | |
| By default, Nano ID uses hardware random bytes generation for security | |
| and low collision probability. If you are not so concerned with security | |
| and more concerned with performance, you can use the faster non-secure generator. | |
| ```js | |
| import { nanoid } from 'nanoid/non-secure' | |
| const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ" | |
| ``` | |
| Note: your IDs will be more predictable and prone to collision attacks. | |
| ### Custom Alphabet or Size | |
| `customAlphabet` allows you to create `nanoid` with your own alphabet | |
| and ID size. | |
| ```js | |
| import { customAlphabet } from 'nanoid' | |
| const nanoid = customAlphabet('1234567890abcdef', 10) | |
| model.id = nanoid() //=> "4f90d13a42" | |
| ``` | |
| Check the safety of your custom alphabet and ID size in our | |
| [ID collision probability] calculator. For more alphabets, check out the options | |
| in [`nanoid-dictionary`]. | |
| Alphabet must contain 256 symbols or less. | |
| Otherwise, the security of the internal generator algorithm is not guaranteed. | |
| Customizable asynchronous and non-secure APIs are also available: | |
| ```js | |
| import { customAlphabet } from 'nanoid/async' | |
| const nanoid = customAlphabet('1234567890abcdef', 10) | |
| async function createUser () { | |
| user.id = await nanoid() | |
| } | |
| ``` | |
| ```js | |
| import { customAlphabet } from 'nanoid/non-secure' | |
| const nanoid = customAlphabet('1234567890abcdef', 10) | |
| user.id = nanoid() | |
| ``` | |
| [ID collision probability]: https://alex7kom.github.io/nano-nanoid-cc/ | |
| [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary | |
| ### Custom Random Bytes Generator | |
| `customRandom` allows you to create a `nanoid` and replace alphabet | |
| and the default random bytes generator. | |
| In this example, a seed-based generator is used: | |
| ```js | |
| import { customRandom } from 'nanoid' | |
| const rng = seedrandom(seed) | |
| const nanoid = customRandom('abcdef', 10, size => { | |
| return (new Uint8Array(size)).map(() => 256 * rng()) | |
| }) | |
| nanoid() //=> "fbaefaadeb" | |
| ``` | |
| `random` callback must accept the array size and return an array | |
| with random numbers. | |
| If you want to use the same URL-friendly symbols with `customRandom`, | |
| you can get the default alphabet using the `urlAlphabet`. | |
| ```js | |
| const { customRandom, urlAlphabet } = require('nanoid') | |
| const nanoid = customRandom(urlAlphabet, 10, random) | |
| ``` | |
| Asynchronous and non-secure APIs are not available for `customRandom`. | |