You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/runtime/modules.md
+73-66
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ $ bun index.ts
31
31
Hello world!
32
32
```
33
33
34
-
In this case, we are importing from `./hello`, a relative path with no extension. To resolve this import, Bun will check for the following files in order:
34
+
In this case, we are importing from `./hello`, a relative path with no extension. **Extensioned imports are optional but supported.**To resolve this import, Bun will check for the following files in order:
35
35
36
36
-`./hello.ts`
37
37
-`./hello.tsx`
@@ -58,7 +58,7 @@ import { hello } from "./hello";
58
58
import { hello } from"./hello.ts"; // this works
59
59
```
60
60
61
-
There is one exception: if you import `from "*.js{x}"`, Bun will additionally check for a matching `*.ts{x}` file, to be compatible with TypeScript's [ES module support](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#new-file-extensions).
61
+
If you import `from "*.js{x}"`, Bun will additionally check for a matching `*.ts{x}` file, to be compatible with TypeScript's [ES module support](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#new-file-extensions).
62
62
63
63
```ts#index.ts
64
64
import { hello } from"./hello";
@@ -88,7 +88,75 @@ exports.hello = hello;
88
88
89
89
That said, using CommonJS is discouraged in new projects.
90
90
91
-
## Resolution
91
+
## Module systems
92
+
93
+
Bun has native support for CommonJS and ES modules. ES Modules are the recommended module format for new projects, but CommonJS modules are still widely used in the Node.js ecosystem.
94
+
95
+
In Bun's JavaScript runtime, `require` can be used by both ES Modules and CommonJS modules. If the target module is an ES Module, `require` returns the module namespace object (equivalent to `import * as`). If the target module is a CommonJS module, `require` returns the `module.exports` object (as in Node.js).
| ES Module | Module Namespace | Module Namespace |
100
+
| CommonJS | module.exports |`default` is `module.exports`, keys of module.exports are named exports |
101
+
102
+
### Using `require()`
103
+
104
+
You can `require()` any file or package, even `.ts` or `.mjs` files.
105
+
106
+
```ts
107
+
const { foo } =require("./foo"); // extensions are optional
108
+
const { bar } =require("./bar.mjs");
109
+
const { baz } =require("./baz.tsx");
110
+
```
111
+
112
+
{% details summary="What is a CommonJS module?" %}
113
+
114
+
In 2016, ECMAScript added support for [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). ES Modules are the standard for JavaScript modules. However, millions of npm packages still use CommonJS modules.
115
+
116
+
CommonJS modules are modules that use `module.exports` to export values. Typically, `require` is used to import CommonJS modules.
117
+
118
+
```ts
119
+
// my-commonjs.cjs
120
+
const stuff =require("./stuff");
121
+
module.exports= { stuff };
122
+
```
123
+
124
+
The biggest difference between CommonJS and ES Modules is that CommonJS modules are synchronous, while ES Modules are asynchronous. There are other differences too.
125
+
126
+
- ES Modules support top-level `await` and CommonJS modules don't.
127
+
- ES Modules are always in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode), while CommonJS modules are not.
128
+
- Browsers do not have native support for CommonJS modules, but they do have native support for ES Modules via `<script type="module">`.
129
+
- CommonJS modules are not statically analyzable, while ES Modules only allow static imports and exports.
130
+
131
+
{% /details %}
132
+
133
+
### Using `import`
134
+
135
+
You can `import` any file or package, even `.cjs` files.
136
+
137
+
```ts
138
+
const { foo } =require("./foo"); // extensions are optional
139
+
const { bar } =require("./bar.mjs");
140
+
const { baz } =require("./my-typescript.tsx");
141
+
```
142
+
143
+
### Using `import` and `require()` together
144
+
145
+
In Bun, you can use `import` or `require` in the same file—they both work, all the time.
146
+
147
+
```ts
148
+
import { stuff } from"./my-commonjs.cjs";
149
+
importStufffrom"./my-commonjs.cjs";
150
+
const myStuff =require("./my-commonjs.cjs");
151
+
```
152
+
153
+
### Top level await
154
+
155
+
The only exception to this rule is top-level await. You can't `require()` a file that uses top-level await, since the `require()` function is inherently synchronous.
156
+
157
+
Fortunately, very few libraries use top-level await, so this is rarely a problem. But if you're using top-level await in your application code, make sure that file isn't being `require()` from elsewhere in your application. Instead, you should use `import` or [dynamic `import()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import).
158
+
159
+
## Importing packages
92
160
93
161
Bun implements the Node.js module resolution algorithm, so you can import packages from `node_modules` with a bare specifier.
94
162
@@ -107,8 +175,8 @@ Once it finds the `foo` package, Bun reads the `package.json` to determine how t
107
175
"bun": "./index.js",
108
176
"worker": "./index.js",
109
177
"node": "./index.js",
110
-
"require": "./index.js", # if importer is CommonJS
111
-
"import": "./index.mjs", # if importer is ES module
178
+
"require": "./index.js", // if importer is CommonJS
179
+
"import": "./index.mjs", // if importer is ES module
112
180
"default": "./index.js",
113
181
}
114
182
}
@@ -159,67 +227,6 @@ In the spirit of treating TypeScript as a first-class citizen, the Bun runtime w
159
227
160
228
If you aren't a TypeScript user, you can create a [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) in your project root to achieve the same behavior.
161
229
162
-
## CommonJS
163
-
164
-
Bun has native support for CommonJS modules. ES Modules are the recommended module format, but CommonJS modules are still widely used in the Node.js ecosystem. Bun supports both module formats.
165
-
166
-
In Bun's JavaScript runtime, `require` can be used by both ES Modules and CommonJS modules. If the target module is an ES Module, `require` returns the module namespace object (equivalent to `import * as`). If the target module is a CommonJS module, `require` returns the `module.exports` object (as in Node.js).
| ES Module | Module Namespace | Module Namespace |
171
-
| CommonJS | module.exports |`default` is `module.exports`, keys of module.exports are named exports |
172
-
173
-
### What is a CommonJS module?
174
-
175
-
In 2016, ECMAScript added support for [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). ES Modules are the standard for JavaScript modules. However, millions of npm packages still use CommonJS modules.
176
-
177
-
CommonJS modules are modules that use `module.exports` to export values. Typically, `require` is used to import CommonJS modules.
178
-
179
-
```ts
180
-
// my-commonjs.cjs
181
-
const stuff =require("./stuff");
182
-
module.exports= { stuff };
183
-
```
184
-
185
-
The biggest difference between CommonJS and ES Modules is that CommonJS modules are synchronous, while ES Modules are asynchronous. There are other differences too, like ES Modules support top-level `await` and CommonJS modules don't. ES Modules are always in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode), while CommonJS modules are not. Browsers do not have native support for CommonJS modules, but they do have native support for ES Modules (`<script type="module">`). CommonJS modules are not statically analyzable, while ES Modules only allow static imports and exports.
186
-
187
-
### Importing CommonJS from ESM
188
-
189
-
You can `import` or `require` CommonJS modules from ESM modules.
190
-
191
-
```ts
192
-
import { stuff } from"./my-commonjs.cjs";
193
-
importStufffrom"./my-commonjs.cjs";
194
-
const myStuff =require("./my-commonjs.cjs");
195
-
```
196
-
197
-
### Importing ESM from CommonJS
198
-
199
-
```ts
200
-
// this works in Bun but not Node.js
201
-
const { stuff } =require("./my-esm.mjs");
202
-
```
203
-
204
-
### Importing CommonJS from CommonJS
205
-
206
-
```ts
207
-
const { stuff } =require("./my-commonjs.cjs");
208
-
```
209
-
210
-
#### Top-level await
211
-
212
-
If you are using top-level await, you must use `import()` to import ESM modules from CommonJS modules.
213
-
214
-
```ts
215
-
import("./my-esm.js").then(({ stuff }) => {
216
-
// ...
217
-
});
218
-
219
-
// this will throw an error if "my-esm.js" uses top-level await
220
-
const { stuff } =require("./my-esm.js");
221
-
```
222
-
223
230
{% details summary="Low-level details of CommonJS interop in Bun" %}
224
231
225
232
Bun's JavaScript runtime has native support for CommonJS. When Bun's JavaScript transpiler detects usages of `module.exports`, it treats the file as CommonJS. The module loader will then wrap the transpiled module in a function shaped like this:
0 commit comments