Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Improve mode/NODE_ENV defaults and interaction #972

Merged
merged 1 commit into from Jul 13, 2018
Merged

Improve mode/NODE_ENV defaults and interaction #972

merged 1 commit into from Jul 13, 2018

Conversation

edmorley
Copy link
Member

@edmorley edmorley commented Jun 29, 2018

Previously the only way to override mode was by passing --mode on the command line. However this is not possible with all tools, since some (such as karma) reject unrecognised arguments.

Now:

  • mode is derived from NODE_ENV if --mode wasn't passed, and !production NODE_ENV falls back to mode development.
  • if --mode is passed, it takes priority over NODE_ENV.
  • if neither mode nor NODE_ENV is defined, then NODE_ENVis set toproduction, however mode` is left undefined, which causes webpack to output a helpful warning about relying on defaults.
  • the template test runner configs set a default NODE_ENV of test.
  • @neutrinojs/stylelint now also correctly sets failOnError.

Fixes #900.
Fixes #971.
Closes #955.

@edmorley edmorley added this to the v9 milestone Jun 29, 2018
@edmorley edmorley self-assigned this Jun 29, 2018
@edmorley edmorley changed the title Improve mode and NODE_ENV defaults and interaction Improve mode/NODE_ENV defaults and interaction Jun 29, 2018
@edmorley
Copy link
Member Author

edmorley commented Jun 29, 2018

Once we agree on the behaviour/UX I'll fix/add some tests :-)

.eslintrc.js Outdated
@@ -1,3 +1,5 @@
const neutrino = require('./packages/neutrino');

process.env.NODE_ENV = process.env.NODE_ENV || 'lint';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible values instead of "lint" might be "test" or "production". Though given we use "test" for karma.config.js etc, it seems wrong to just call this "production".

ESLint config conditionals that choose to rely on NODE_ENV (eg enabling/disabling the no-console rule) should be using NODE_ENV !== 'development' rather than NODE_ENV === 'production' for compatibility with NODE_ENV='test' anyway -- so using NODE_ENV='lint' doesn't seem like it would cause any more problems.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eliperelman thoughts about this part?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with this, although my initial gut reaction wishes this existed in eslint() instead of being dotfile boilerplate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah me too -- though I guess that would mean we would have to change the whole way the middlewares are instantiated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah which is too much right now. The thing that prevents us from doing this is not being able to reliably infer when the NODE_ENV was set by Neutrino vs. the environment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this sounds crazy, but...

What if the Neutrino instance had options stating whether or not mode and NODE_ENV were specified, and the middleware could control the values?

// packages/neutrino/index.js
const neutrino = new Neutrino({
  mode: yargs.argv.mode,
  NODE_ENV: process.env.NODE_ENV
})

// packages/web/index.js
if (!neutrino.options.NODE_ENV) {
  process.env.NODE_ENV = 'production';
}

// packages/karma/index.js
neutrino.register('karma', (neutrino, override) => config => {
  if (!neutrino.options.NODE_ENV) {
    process.env.NODE_ENV = 'test';
  }
});

Obviously the above isn't correct, but conceptual. Thoughts?

Copy link
Member Author

@edmorley edmorley Jul 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That definitely gets us closer, however if I follow correctly, it would mean that the web preset (and any others) see the NODE_ENV as 'production' and not 'test', thereby meaning the parts of the config they contribute to the karma config, are using the wrong NODE_ENV.

Therefore it seems that the only way to solve this is make the meat of the presets be a step that occurs after they register themselves.

ie:

// registers the presets and what output commands they include,
// but doesn't actually generate any config or adjust NODE_ENV
neutrino.use(some_lint_preset);
neutrino.use(some_build_preset);
neutrino.use(some_test_preset);

// The output function then sets NODE_ENV if undefined (in this case to `"test"`)
// and then actually generates the config, where all presets get to see `NODE_ENV=test`
neutrino.karma();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(but that's a major change and would mean backwards incompatibility with all existing presets)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think keeping middleware compat is more important here.

// Development mode is most appropriate for a !production NODE_ENV (such as `NODE_ENV=test`).
mode = (process.env.NODE_ENV === 'production') ? 'production' : 'development';
} else {
throw new Error('Either --mode must be specified via the CLI, or else NODE_ENV be defined.');
Copy link
Member Author

@edmorley edmorley Jun 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatives to throwing are:

  • default to NODE_ENV='production' and mode='production'
  • default to NODE_ENV='production' and don't set mode at all. This would mean for workflows that include a webpack compile (ie not yarn lint), webpack would output the "no mode was specified, using production" warning message, which might help solve the "prevent people from accidentally omitting mode/NODE_ENV` concern.

Both of the alternatives would mean we could drop the process.env.NODE_ENV = ... boilerplate from the template .eslintrc.js files -- though we would still need it for karma.config.js.

I'm on the fence as to which of these three options is best.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eliperelman and this?

@@ -6,6 +6,8 @@ module.exports = (neutrino, { pluginId = 'stylelint', ...opts } = {}) => {
configBasedir: neutrino.options.root,
files: '**/*.+(css|scss|sass|less)',
context: neutrino.options.source,
// Fail for all of 'production', 'lint' and 'test'.
failOnError: process.env.NODE_ENV !== 'development',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes #971.

@@ -84,7 +84,8 @@ module.exports = (neutrino, opts = {}) => {
include: !opts.include ? [neutrino.options.source, neutrino.options.tests] : undefined,
eslint: {
cache: true,
failOnError: neutrino.config.get('mode') === 'production',
// Fail for all of 'production', 'lint' and 'test'.
failOnError: process.env.NODE_ENV !== 'development',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've flipped this, so it is set to true for yarn test too.


if (!process.env.NODE_ENV) {
if (mode) {
process.env.NODE_ENV = mode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we force NODE_ENV to always be the same value as --mode, but that's not what we want right? What about NODE_ENV=development webpack --mode production?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was intentional (there's a note in the PR description), for the reasons under scenario G here:
#955 (comment)

...though open to counter-arguments :-)

@edmorley
Copy link
Member Author

edmorley commented Jul 3, 2018

@eliperelman, any more thoughts on the UX choices? I'm keen to get them finalised, so I can updated the tests in this PR, then press on with the overall docs update in another PR.

(Context: I really want to get Treeherder builds faster soon (ie next week or two), which means a Neutrino 9 alpha by then, or else stopping using Neutrino and just switching to plain webpack)

@eliperelman
Copy link
Member

I still a little uneasy about #972 (comment) but I can't articulate my issue with it. I'd say let's roll with it, test it out, and revise if necessary.

eliperelman
eliperelman previously approved these changes Jul 3, 2018
@edmorley edmorley dismissed eliperelman’s stale review July 4, 2018 15:38

(Cancelling review until tests are updated)

Previously the only way to override `mode` was by passing `--mode` on
the command line. However this is not possible with all tools, since
some (such as karma) reject unrecognised arguments.

Now:
* `mode` is derived from `NODE_ENV` if `--mode` wasn't passed, and
  !production `NODE_ENV` falls back to mode `development`.
* if `--mode` is passed, it takes priority over `NODE_ENV`.
* if neither `mode` nor `NODE_ENV is defined, then `NODE_ENV` is set
  to `production`, however `mode` is left undefined, which causes
  webpack to output a helpful warning about relying on defaults.
* the template test runner configs set a default `NODE_ENV` of `test`.
* `@neutrinojs/stylelint` now also correctly sets `failOnError`.

Fixes #900.
Fixes #971.
Closes #955.
@edmorley
Copy link
Member Author

I've updated the PR - changes are:

  • if neither NODE_ENV nor mode is defined, now instead of throwing, NODE_ENV is set to production and mode left as undefined. This avoids having to set a default NODE_ENV in .eslintrc.js, and leaving mode as undefined means that when webpack is used, the webpack "mode wasn't set, falling back to defaults" message is shown, which should help educate users.
  • the tests have been updated / additional coverage added.

Copy link
Member

@eliperelman eliperelman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. I'm willing to roll with it and see how it does.

@edmorley
Copy link
Member Author

👍

@edmorley edmorley merged commit 2dce8d2 into neutrinojs:master Jul 13, 2018
@edmorley edmorley deleted the mode-NODE_ENV-defaults branch July 13, 2018 19:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging this pull request may close these issues.

None yet

2 participants