Skip to content

Commit 3dce9ec

Browse files
committed
cli: --dev flag for module resolution and env
1 parent e951825 commit 3dce9ec

File tree

16 files changed

+101
-5
lines changed

16 files changed

+101
-5
lines changed

doc/api/cli.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ added: v12.0.0
127127
128128
Specify the file name of the CPU profile generated by `--cpu-prof`.
129129

130+
### `--dev`
131+
<!-- YAML
132+
added: REPLACEME
133+
-->
134+
135+
> Stability: 1 - Experimental
136+
137+
Enables the `"development"` [conditional export][] in package resolution,
138+
while also setting `process.env.NODE_ENV` to `"development"`.
139+
130140
### `--disable-proto=mode`
131141
<!--YAML
132142
added: v13.12.0
@@ -1150,6 +1160,7 @@ node --require "./a.js" --require "./b.js"
11501160

11511161
Node.js options that are allowed are:
11521162
<!-- node-options-node start -->
1163+
* `--dev`
11531164
* `--disable-proto`
11541165
* `--enable-fips`
11551166
* `--enable-source-maps`
@@ -1495,3 +1506,4 @@ $ node --max-old-space-size=1536 index.js
14951506
[jitless]: https://v8.dev/blog/jitless
14961507
[libuv threadpool documentation]: http://docs.libuv.org/en/latest/threadpool.html
14971508
[remote code execution]: https://www.owasp.org/index.php/Code_Injection
1509+
[conditional export]: esm.html##esm_conditional_exports

doc/api/esm.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ Node.js supports the following conditions:
358358
* `"node"` - matched for any Node.js environment. Can be a CommonJS or ES
359359
module file. _This condition should always come after `"import"` or
360360
`"require"`._
361+
* `"development"` - enabled by the `--dev` flag in Node.js, this allows code
362+
paths to be loaded that provide additional debugging information.
361363
* `"default"` - the generic fallback that will always match. Can be a CommonJS
362364
or ES module file. _This condition should always come last._
363365

@@ -383,6 +385,10 @@ Conditional exports can also be extended to exports subpaths, for example:
383385
"exports": {
384386
".": "./main.js",
385387
"./feature": {
388+
"development": {
389+
"browser": "./feature-browser-dev.js",
390+
"default": "./feature-dev.js"
391+
},
386392
"browser": "./feature-browser.js",
387393
"default": "./feature.js"
388394
}
@@ -392,7 +398,8 @@ Conditional exports can also be extended to exports subpaths, for example:
392398

393399
Defines a package where `require('pkg/feature')` and `import 'pkg/feature'`
394400
could provide different implementations between the browser and Node.js,
395-
given third-party tool support for a `"browser"` condition.
401+
given third-party tool support for a `"browser"` condition, as well as
402+
loading different code between development and production environments.
396403

397404
#### Nested conditions
398405

@@ -1471,8 +1478,8 @@ future updates.
14711478
In the following algorithms, all subroutine errors are propagated as errors
14721479
of these top-level routines unless stated otherwise.
14731480

1474-
_defaultEnv_ is the conditional environment name priority array,
1475-
`["node", "import"]`.
1481+
_defaultEnv_ is the conditional environment array, `["node", "import"]`,
1482+
including the `"development"` condition if the `--dev` flag is set.
14761483

14771484
The resolver can throw the following errors:
14781485
* _Invalid Module Specifier_: Module specifier is an invalid URL, package name

doc/node.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ The default is
100100
File name of the V8 CPU profile generated with
101101
.Fl -cpu-prof
102102
.
103+
.It Fl -dev
104+
Sets the development exports resolution and NODE_ENV environment variable.
105+
.
103106
.It Fl -disable-proto Ns = Ns Ar mode
104107
Disable the `Object.prototype.__proto__` property. If
105108
.Ar mode

lib/internal/bootstrap/pre_execution.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ function initializeReport() {
174174
}
175175

176176
function setupDebugEnv() {
177+
if (getOptionValue('--dev')) {
178+
process.env.NODE_ENV = 'development';
179+
}
177180
require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG);
178181
if (getOptionValue('--expose-internals')) {
179182
require('internal/bootstrap/loaders').NativeModule.exposeInternals();

lib/internal/modules/cjs/loader.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const {
7171
loadNativeModule
7272
} = require('internal/modules/cjs/helpers');
7373
const { getOptionValue } = require('internal/options');
74+
const development = getOptionValue('--dev');
7475
const enableSourceMaps = getOptionValue('--enable-source-maps');
7576
const preserveSymlinks = getOptionValue('--preserve-symlinks');
7677
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
@@ -575,6 +576,16 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
575576
}
576577
for (const p of keys) {
577578
switch (p) {
579+
case 'development':
580+
if (development) {
581+
try {
582+
return resolveExportsTarget(baseUrl, target[p], subpath,
583+
mappingKey);
584+
} catch (e) {
585+
if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') throw e;
586+
}
587+
}
588+
break;
578589
case 'node':
579590
case 'require':
580591
try {

lib/internal/modules/esm/resolve.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const { sep } = require('path');
3333

3434
const preserveSymlinks = getOptionValue('--preserve-symlinks');
3535
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
36+
const development = getOptionValue('--dev');
3637
const typeFlag = getOptionValue('--input-type');
3738
const { URL, pathToFileURL, fileURLToPath } = require('internal/url');
3839
const {
@@ -46,7 +47,11 @@ const {
4647
ERR_UNSUPPORTED_ESM_URL_SCHEME,
4748
} = require('internal/errors').codes;
4849

49-
const DEFAULT_CONDITIONS = ObjectFreeze(['node', 'import']);
50+
const DEFAULT_CONDITIONS = ObjectFreeze([
51+
'node',
52+
'import',
53+
...development ? ['development'] : []
54+
]);
5055
const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS);
5156

5257
function getConditionsSet(conditions) {

src/node_options.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ DebugOptionsParser::DebugOptionsParser() {
271271
}
272272

273273
EnvironmentOptionsParser::EnvironmentOptionsParser() {
274+
AddOption("--dev",
275+
"experimental development mode",
276+
&EnvironmentOptions::development,
277+
kAllowedInEnvironment);
274278
AddOption("--enable-source-maps",
275279
"experimental Source Map V3 support",
276280
&EnvironmentOptions::enable_source_maps,

src/node_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class DebugOptions : public Options {
100100
class EnvironmentOptions : public Options {
101101
public:
102102
bool abort_on_uncaught_exception = false;
103+
bool development = false;
103104
bool enable_source_maps = false;
104105
bool experimental_json_modules = false;
105106
bool experimental_modules = false;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import '../common/index.mjs';
2+
import { path } from '../common/fixtures.mjs';
3+
import { strictEqual } from 'assert';
4+
import { spawnSync } from 'child_process';
5+
6+
{
7+
const output = spawnSync(process.execPath, [path('/pkgexports-dev.mjs')]);
8+
console.log(output.stderr.toString());
9+
strictEqual(output.stdout.toString().trim(), 'production');
10+
}
11+
12+
{
13+
const output = spawnSync(process.execPath,
14+
['--dev', path('/pkgexports-dev.mjs')]);
15+
strictEqual(output.stdout.toString().trim(), 'development');
16+
}

test/fixtures/es-module-loaders/loader-with-custom-condition.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import {ok, deepStrictEqual} from 'assert';
22

3+
const dev = process.env.NODE_ENV === 'development';
4+
35
export async function resolve(specifier, context, defaultResolve) {
46
ok(Array.isArray(context.conditions), 'loader receives conditions array');
5-
deepStrictEqual([...context.conditions].sort(), ['import', 'node']);
7+
deepStrictEqual([...context.conditions].sort(),
8+
['import', 'node', ...dev ? ['development'] : []]);
69
return defaultResolve(specifier, {
710
...context,
811
conditions: ['custom-condition', ...context.conditions],

0 commit comments

Comments
 (0)