| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 78ee065 commit 7fd3261
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,7 +60,7 @@ or when referenced by `import` statements within ES module code: | |||
| 60 | 60 | * Strings passed in as an argument to `--eval` or `--print`, or piped to | |
| 61 | 61 | `node` via `STDIN`, with the flag `--input-type=commonjs`. | |
| 62 | 62 | ||
| 63 | - ## <code>package.json</code> <code>"type"</code> field | ||
| 63 | + ### <code>package.json</code> <code>"type"</code> field | ||
| 64 | 64 | ||
| 65 | 65 | Files ending with `.js` or `.mjs`, or lacking any extension, | |
| 66 | 66 | will be loaded as ES modules when the nearest parent `package.json` file | |
@@ -97,7 +97,13 @@ if the nearest parent `package.json` contains `"type": "module"`. | |||
| 97 | 97 | import './startup.js'; // Loaded as ES module because of package.json | |
| 98 | 98 | ``` | |
| 99 | 99 | ||
| 100 | - ## Package Scope and File Extensions | ||
| 100 | + Package authors should include the `"type"` field, even in packages where all | ||
| 101 | + sources are CommonJS. Being explicit about the `type` of the package will | ||
| 102 | + future-proof the package in case the default type of Node.js ever changes, and | ||
| 103 | + it will also make things easier for build tools and loaders to determine how the | ||
| 104 | + files in the package should be interpreted. | ||
| 105 | + | ||
| 106 | + ### Package Scope and File Extensions | ||
| 101 | 107 | ||
| 102 | 108 | A folder containing a `package.json` file, and all subfolders below that | |
| 103 | 109 | folder down until the next folder containing another `package.json`, is | |
@@ -156,7 +162,7 @@ package scope: | |||
| 156 | 162 | extension (since both `.js` and `.cjs` files are treated as CommonJS within a | |
| 157 | 163 | `"commonjs"` package scope). | |
| 158 | 164 | ||
| 159 | - ## <code>--input-type</code> flag | ||
| 165 | + ### <code>--input-type</code> flag | ||
| 160 | 166 | ||
| 161 | 167 | Strings passed in as an argument to `--eval` or `--print` (or `-e` or `-p`), or | |
| 162 | 168 | piped to `node` via `STDIN`, will be treated as ES modules when the | |
@@ -174,7 +180,9 @@ For completeness there is also `--input-type=commonjs`, for explicitly running | |||
| 174 | 180 | string input as CommonJS. This is the default behavior if `--input-type` is | |
| 175 | 181 | unspecified. | |
| 176 | 182 | ||
| 177 | - ## Package Entry Points | ||
| 183 | + ## Packages | ||
| 184 | + | ||
| 185 | + ### Package Entry Points | ||
| 178 | 186 | ||
| 179 | 187 | The `package.json` `"main"` field defines the entry point for a package, | |
| 180 | 188 | whether the package is included into CommonJS via `require` or into an ES | |
@@ -209,15 +217,50 @@ be interpreted as CommonJS. | |||
| 209 | 217 | ||
| 210 | 218 | The `"main"` field can point to exactly one file, regardless of whether the | |
| 211 | 219 | package is referenced via `require` (in a CommonJS context) or `import` (in an | |
| 212 | - ES module context). Package authors who want to publish a package to be used in | ||
| 213 | - both contexts can do so by setting `"main"` to point to the CommonJS entry point | ||
| 214 | - and informing the package’s users of the path to the ES module entry point. Such | ||
| 215 | - a package would be accessible like `require('pkg')` and `import | ||
| 216 | - 'pkg/module.mjs'`. Alternatively the package `"main"` could point to the ES | ||
| 217 | - module entry point and legacy users could be informed of the CommonJS entry | ||
| 218 | - point path, e.g. `require('pkg/commonjs')`. | ||
| 219 | - | ||
| 220 | - ## Package Exports | ||
| 220 | + ES module context). | ||
| 221 | + | ||
| 222 | + #### Compatibility with CommonJS-Only Versions of Node.js | ||
| 223 | + | ||
| 224 | + Prior to the introduction of support for ES modules in Node.js, it was a common | ||
| 225 | + pattern for package authors to include both CommonJS and ES module JavaScript | ||
| 226 | + sources in their package, with `package.json` `"main"` specifying the CommonJS | ||
| 227 | + entry point and `package.json` `"module"` specifying the ES module entry point. | ||
| 228 | + This enabled Node.js to run the CommonJS entry point while build tools such as | ||
| 229 | + bundlers used the ES module entry point, since Node.js ignored (and still | ||
| 230 | + ignores) `"module"`. | ||
| 231 | + | ||
| 232 | + Node.js can now run ES module entry points, but it remains impossible for a | ||
| 233 | + package to define separate CommonJS and ES module entry points. This is for good | ||
| 234 | + reason: the `pkg` variable created from `import pkg from 'pkg'` is not the same | ||
| 235 | + singleton as the `pkg` variable created from `const pkg = require('pkg')`, so if | ||
| 236 | + both are referenced within the same app (including dependencies), unexpected | ||
| 237 | + behavior might occur. | ||
| 238 | + | ||
| 239 | + There are two general approaches to addressing this limitation while still | ||
| 240 | + publishing a package that contains both CommonJS and ES module sources: | ||
| 241 | + | ||
| 242 | + 1. Document a new ES module entry point that’s not the package `"main"`, e.g. | ||
| 243 | + `import pkg from 'pkg/module.mjs'` (or `import 'pkg/esm'`, if using [package | ||
| 244 | + exports][]). The package `"main"` would still point to a CommonJS file, and | ||
| 245 | + thus the package would remain compatible with older versions of Node.js that | ||
| 246 | + lack support for ES modules. | ||
| 247 | + | ||
| 248 | + 1. Switch the package `"main"` entry point to an ES module file as part of a | ||
| 249 | + breaking change version bump. This version and above would only be usable on | ||
| 250 | + ES module-supporting versions of Node.js. If the package still contains a | ||
| 251 | + CommonJS version, it would be accessible via a path within the package, e.g. | ||
| 252 | + `require('pkg/commonjs')`; this is essentially the inverse of the previous | ||
| 253 | + approach. Package consumers who are using CommonJS-only versions of Node.js | ||
| 254 | + would need to update their code from `require('pkg')` to e.g. | ||
| 255 | + `require('pkg/commonjs')`. | ||
| 256 | + | ||
| 257 | + Of course, a package could also include only CommonJS or only ES module sources. | ||
| 258 | + An existing package could make a semver major bump to an ES module-only version, | ||
| 259 | + that would only be supported in ES module-supporting versions of Node.js (and | ||
| 260 | + other runtimes). New packages could be published containing only ES module | ||
| 261 | + sources, and would be compatible only with ES module-supporting runtimes. | ||
| 262 | + | ||
| 263 | + ### Package Exports | ||
| 221 | 264 | ||
| 222 | 265 | By default, all subpaths from a package can be imported (`import 'pkg/x.js'`). | |
| 223 | 266 | Custom subpath aliasing and encapsulation can be provided through the | |
@@ -930,5 +973,6 @@ success! | |||
| 930 | 973 | [`import`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import | |
| 931 | 974 | [`module.createRequire()`]: modules.html#modules_module_createrequire_filename | |
| 932 | 975 | [dynamic instantiate hook]: #esm_dynamic_instantiate_hook | |
| 976 | + [package exports]: #esm_package_exports | ||
| 933 | 977 | [special scheme]: https://url.spec.whatwg.org/#special-scheme | |
| 934 | 978 | [the official standard format]: https://tc39.github.io/ecma262/#sec-modules | |
| Back | FazBrowse Home | New Git URL |
0 commit comments