Eslint-plugin-import: [import/order] Force sort order of certain packages within "external" group

Created on 20 Feb 2020  路  9Comments  路  Source: benmosher/eslint-plugin-import

We're using the import/order rule to enforce a convention in module imports. Here's how the import/order rule is currently configured in our project.

// in .eslintrc.js

module.exports = {
  rules: {
      'import/order': ['error', {
          groups: ['builtin', 'external', 'internal'],
          'newlines-between': 'always',
          alphabetize: {
              order: 'asc',
              caseInsensitive: true,
          },
      }],
}

This will result in the following import conventions:

// in a module with a React component 

// "external" modules are imported first
import { Button } from 'antd'
import PropTypes from 'prop-types'
import React from 'react'

// "internal" modules are imported second
import { BrandedIcon1 } from 'components/BrandedIcon1'
import { BrandedIcon2 } from 'components/BrandedIcon2'

All is well and good, except that our team's convention is to import React first when a module has React components. Therefore, the example above would become:

import React from 'react' // force React to be imported first in the "external" group
import { Button } from 'antd'
import PropTypes from 'prop-types'

import { BrandedIcon1 } from 'components/BrandedIcon1'
import { BrandedIcon2 } from 'components/BrandedIcon2'

Is it possible to achieve this desired sort order using the import/order rule? I was a bit confused by the documentation of the pathGroups and pathGroupsExcludedImportTypes and I wasn't sure if these options could be used to achieve this result. Thanks in advance for the help and keep up the great work on this plugin!

imporexport ordering

Most helpful comment

this worked for me
"import/order": ["error", { "newlines-between": "always", "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "pathGroups": [ { "pattern": "weplay-singleton/**", "group": "internal", "position": "before" }, { "pattern": "weplay-core/**", "group": "internal", "position": "before" }, { "pattern": "weplay-components/**", "group": "internal", "position": "before" }, { "pattern": "weplay-competitive/**", "group": "internal", "position": "before" }, { "pattern": "weplay-events/**", "group": "internal", "position": "before" }, { "pattern": "weplay-media/**", "group": "internal", "position": "before" }, { "pattern": "weplay-platform/**", "group": "internal", "position": "before" }, ], pathGroupsExcludedImportTypes: [ 'weplay-singleton', 'weplay-core', 'weplay-components', 'weplay-competitive', 'weplay-events', 'weplay-media', 'weplay-platform', ] }],

All 9 comments

At @blockstack we'd love this feature too.

You should be able to add pathGroups, marking React as going "before" the external group?

@ljharb Thanks for the response. As far as I can tell, the pathGroups option doesn't work for builtin or external modules, as mentioned in the documentation.

image

The react module is external, so the following configuration options don't have any affect on the sort order.

module.exports = {
  rules: {
      'import/order': ['error', {
          groups: ['builtin', 'external', 'internal'],
          pathGroups: [
              {
                  pattern: 'react',  // this doesn't seem to work because react is `external`
                  group: 'external',
                  position: 'before',
              },
          ],
          'newlines-between': 'always',
          alphabetize: {
              order: 'asc',
              caseInsensitive: true,
          },
      }],
}

this worked for me
"import/order": ["error", { "newlines-between": "always", "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "pathGroups": [ { "pattern": "weplay-singleton/**", "group": "internal", "position": "before" }, { "pattern": "weplay-core/**", "group": "internal", "position": "before" }, { "pattern": "weplay-components/**", "group": "internal", "position": "before" }, { "pattern": "weplay-competitive/**", "group": "internal", "position": "before" }, { "pattern": "weplay-events/**", "group": "internal", "position": "before" }, { "pattern": "weplay-media/**", "group": "internal", "position": "before" }, { "pattern": "weplay-platform/**", "group": "internal", "position": "before" }, ], pathGroupsExcludedImportTypes: [ 'weplay-singleton', 'weplay-core', 'weplay-components', 'weplay-competitive', 'weplay-events', 'weplay-media', 'weplay-platform', ] }],

Thanks @egemon! Your solution worked for me. I was missing the pathGroupsExcludedImportTypes option.

Here's configuration that forces react to be imported above other external dependencies.

// in .eslintrc.js

module.exports = {
  rules: {
      'import/order': ['error', {
          groups: ['builtin', 'external', 'internal'],
          pathGroups: [
              {
                  pattern: 'react',
                  group: 'external',
                  position: 'before',
              },
          ],
          pathGroupsExcludedImportTypes: [
              'react',
          ],
          'newlines-between': 'always',
          alphabetize: {
              order: 'asc',
              caseInsensitive: true,
          },
      }],
}

I think there's an opportunity to improve the documentation for the pathGroupsExcludedImportTypes option. The documentation made me think the allowed values for pathGroupsExcludedImportTypes were only groups (e.g., builtin, external, etc.) and not patterns (e.g., react, react-router-dom, etc).

image

Glad you figured it out :-) so is this resolved? Happy to reopen if not.

@ljharb it is. I think I should open PR and issue to add smth like that into documentation?

Thanks, that'd be great.

@ljharb Yes, this is resolved. Thanks!

Was this page helpful?
0 / 5 - 0 ratings