Code Style Article

The editor integration section for linter-eslint seems to be missing a step for the Atom integration (at least with respect to React). It doesn’t like the tags in your render() code:

Parsing error: Unexpected token

This is what I did to make it work with vim, meteor and lint.

Get all the npm packages, in my case I need to use the same packages for vim, so I installed them globally.

sudo npm install -g --save-dev eslint-config-airbnb eslint-plugin-import eslint-plugin-meteor eslint-plugin-react eslint-plugin-jsx-a11y eslint

Edit the packages.json with the lint shortcut.

{
    ....
    "scripts": {
      "start": "meteor run",
      "lint": "eslint .",
      "pretest": "npm run lint --silent"
    },
    ...
}

Create the .eslintrc with this settings.

{
	"plugins": [
	    "meteor"
	],
	"extends": [
	    "airbnb",
	    "plugin:meteor/recommended"
	],
	"rules": {
	    "meteor/eventmap-params": [
	        2, { "templateInstanceParamName": "instance" }
	    ],
	    "import/no-unresolved": [
	        2, { "ignore": ["^meteor/"] }
	    ],
	    // enable this._variable (used many times to refer the this._id)
	    "no-underscore-dangle": ["error", { "allowAfterThis": true }],
	    // my indentation is four spaces (sorry, its better for me)
	    "indent": ["error", 4],
	    // meteor uses globals and includes a lot
	    "no-unused-vars": 0,
            // enable console
            "no-console": 0,
	},
	"env": {
	    "meteor": true,
	    "node": true,
	    "browser": true
	},
	// ignore some undeclared global variables and methods
	// used by Meteor
	"globals": {
	    "describe": false,
	    "it": false,
	    "before": false,
	    "beforeEach": false,
	    "after": false,
	    "afterEach": false
	}
}

Install the scrooloose/syntastic Vundle in Vim.

" Lint
Plugin 'scrooloose/syntastic'
let g:syntastic_javascript_checkers = ['eslint']
let g:syntastic_check_on_open=1

Now meteor and vim are using the same .eslinrc configuration file. I can lint with Meteor and also get the lint error report from vim.

2 Likes

How do you prevent it from scanning .meteor, node_modules and packages?

I think the guide should include a little more details of how incredibly helpful ESLint can be for React. It provides much more than style and typo checking. I’ve found it very helpful to improving my React programming. For example: warning a component should be a pure render function instead of a class and when function binding can cause inefficient garbage collection.

A few other notes:

  1. In Windows, you should install the NPM plugins globally. Otherwise, you can double your build times.
  2. In Atom, I only had to install ESLint. It automatically installed the dependencies and I don’t think Babel is necessary.
  3. In Atom, you need to set the ESLint global installation flag if the you install the NPM plugins globally.
  4. For react, you need to set up parser options in your eslintrc.json file for ecmaVersion and sourceType.

Is there any evidence or reason to this? Or are you talking specifically about meteor build?

After I installed the ESLint plugins locally, Meteor went from 16 to 40 seconds to restart any time I saved changes. Switching to global lowered my build times back to 16 seconds. This is only on Windows. On Ubuntu, the local install had no effect.
Here’s a thread I posted discussing it.

1 Like

in Code style doc you are writing

Collections should be named as a plural noun, in PascalCase. The name of the collection in the database (the first argument to the collection constructor) should be the same as the name of the JavaScript symbol.

but users collection is in db lowercase, how can I change it ?
Thanks
Best Regards

I just want to second this piece of advice and thank @trajano for it! This is the key to getting the false positive errors on absolute paths to go away.

I’ve seen many posts where people are indicating that absolute paths in import statements weren’t working. They work. They are interpreted by Meteor as paths relative to the project root directory. But without this resolver, ESLint is telling everyone that they are errors, and people are confusing that with Meteor not supporting it. I dug into Meteor’s module code and found that not only are the absolute paths supported, but the very first test verifies that they work. This is explicit support.

To expand on the installation of this, it is an NPM module. So add it to the “npm install” command recommended in the article as follows…

meteor npm install --save-dev eslint-config-airbnb eslint-plugin-import eslint-import-resolver-meteor eslint-plugin-meteor eslint-plugin-react eslint-plugin-jsx-a11y eslint

Of course, if you already have the others just…

meteor npm install --save-dev eslint-import-resolver-meteor

Then add the following to your .eslintrc.json file

  "settings": {
    "import/resolver": "meteor"
  },
1 Like

Can someone send a PR to add this stuff to the guide article?

Your wish is my command (today)! Done.

With the advent of conditional and nested import support in Meteor 1.3.3 and up, ESLint “breaks” if you make use of a conditional or nested import within a module.

To expand on that, if you use code like

if (this.isServer) {
   import { ServerSauce } from './server/serverOnlyCode';
}

ESLint will give a syntax error similar to the following and stop processing the file.

272:7  error  Parsing error: 'import' and 'export' may only appear at the top level

Luckily, the maintainers of babel-eslint, an alternative parser for ESLint, accepted a PR to implement an option that allows this syntax.

To get ESLint to work with nested imports and exports (yes, have not yet seen a use-case for them but conditional exports work too with Ben’s changes), just run

$meteor npm install --save-dev babel-eslint

to get the latest version of babel-eslint (>= 6.1.0) and add the following into your ESLint configuration in package.json or .eslintrc.json:

  "parser": "babel-eslint",
  "parserOptions": {
    "allowImportExportEverywhere": true
  },

I’ll create a guide PR to show this there too.

3 Likes

You can use

const ServerSauce = require('./server/serverOnlyCode').ServerSauce

Without having to update eslint.

As for a use case for conditional loads, I use it as part of my gulpfile.js to prevent the actual gulp file from being loaded in Meteor

if (typeof Meteor === typeof undefined) {
  // eslint-disable-next-line vars-on-top, no-var
  var r = require
  r('./.gulp/gulpfile')
}

Of course, require can still be used, but the point of the new support is to get rid of the split personality aspect of using two different module systems in one file. Since Ben implemented it as an NPM module, reify, a means is now available to the whole NPM community to stop using require throughout their file, not just at the top level.

My comment on the use-case was concerning conditional exports, not imports. I believe they were included mostly to maintain import <> export symmetry. I haven’t yet dug into experimenting with conditional exports other than to verify that something with a conditional export does in fact build.

2 Likes

+1 for JSDoc recommendation.

You could even enforce it with ESLint like so,

in eslintConfig

...
"valid-jsdoc": "error",
  "require-jsdoc": [
    "error",
    {
      "require": {
        "FunctionDeclaration": true,
        "MethodDefinition": true,
        "ClassDeclaration": true
      }
    }
  ],
...

I don’t think though enforcing JSDoc would make for a nice experience for those who are just starting out with Meteor. ‘Gentle suggestions’ for beginners and ‘Highly recommended’ for large projects with multiple devs.

1 Like

Haha, this makes me think of some evilly-grinning lead dev :grin:

1 Like

@tmeasday

I started using the style recommendations in this guide several weeks ago and while investigating a high cpu usage issue with Webstorm (2016.2) today, I saw a new version of eslint was available (3.x, while I was on 2.x).

I couldn’t figure out why running npm update wouldn’t update to eslint 3.x, so I ran npm uninstall on all the eslint-related packages I had, and simply attempted to reinstall them fresh.

After doing this I was warned about dependency issues eslint-airbnb-config has with eslint:

npm WARN eslint-config-airbnb@9.0.1 requires a peer of eslint-plugin-jsx-a11y@^1.2.0 but none was installed.
npm WARN eslint-plugin-jsx-a11y@2.0.1 requires a peer of eslint@^2.10.2 || 3.x but none was installed.

I found that eslint-airbnb-config is not yet compatible with the new 3.x version of eslint, released earlier this month.

Until Airbnb updates their config for 3.x support, I think you have to specify the latest compatible version of eslint during your install, along with a version specification for eslint-plugin-jsx-a11y, whose latest version 2.0.1 otherwise requires at least eslint 2.10.x.

This appears to do the trick for me:

meteor npm install --save-dev babel-eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-meteor eslint-plugin-react eslint-plugin-jsx-a11y@1.2.0 eslint-import-resolver-meteor eslint@2.9.0

2 Likes

ESLint 3.x is a breaking change and specifically broke compatibility with Node < 4.0. Therefore, it should not be used with Meteor < 1.4.

The reason running npm update wouldn’t perform the update to ESLint 3.x is because ESLint 3.x’s package.json file correctly specifies that it requires Node >= 4.x. NPM saw that you weren’t running that Node and, very correctly, chose not to do the update.

I think there are multiple plugins that aren’t yet compatible with ESLint 3.x. Best to hold off.

If you choose to push the edge, you’ll have to either run Meteor 1.4 beta or stop using Meteor to run npm. I advise against that latter choice which mixes build systems. I have encountered a lot of problems with different versions of NPM / Node operating on the same node_modules directory. As a matter of policy, I wipe out and rebuild node_modules every time I change NPM / Node versions. That gets rid of a lot of flakiness.

1 Like

It seems that the eslint configuration is broken yet again. Running it on a fresh project turns up these issues:

error ‘meteor’ should be listed in the project’s dependencies. Run ‘npm i -S meteor’ to add it import/no-extraneous-dependencies
error Missing file extension for “meteor/check” import/extensions
error Do not import modules using an absolute path import/no-absolute-path

Does anyone have a working package.json file that can just report real lint errors on a fresh application?

YMMV of course, but here are the dev dependencies I’m using in a new (1.4.2.3) project:

"devDependencies": {
    "babel-eslint": "^6.1.2",
    "eslint": "^3.5.0",
    "eslint-config-airbnb": "^11.1.0",
    "eslint-import-resolver-meteor": "^0.3.3",
    "eslint-plugin-import": "^1.15.0",
    "eslint-plugin-jsx-a11y": "^2.2.2",
    "eslint-plugin-meteor": "^4.0.0",
    "eslint-plugin-react": "^6.2.2",
    "nightmare-meteor": "^2.4.21",
    "shell-source": "^1.1.0",
    "shelljs": "^0.7.4"
  }