eslint-plugin-import icon indicating copy to clipboard operation
eslint-plugin-import copied to clipboard

BUG: import/order - CSS/Sass/SCSS/etc should be grouped, and never alphabetized

Open TheJaredWilcurt opened this issue 3 years ago • 8 comments

In bundlers (like Webpack), you can import in style files. This is useful so that relative image/fonts get bundled correctly. You may be importing from node_modules, or locally, and the order you import files effects the Cascade in CSS. So they should always be grouped together, and never alphabetized.

  • **/*.css
  • **/*.scss
  • **/*.sass
  • **/*.styl
  • **/*.less

There should be a "styles" group added to the list of official groups, and it should always ignore internal sorting rules, such as alphabetize, to prevent specificity bugs in the imported styles.

TheJaredWilcurt avatar Mar 03 '22 20:03 TheJaredWilcurt

By design, this rule should neither group nor alphabetize unassigned imports:

https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md

Unassigned imports are ignored, as the order they are imported in may be important.

If that's not the behaviour you're currently seeing, I'd suggest providing a code sample or reproduction.

aaronadamsCA avatar Mar 04 '22 13:03 aaronadamsCA

// main.js
import axios from 'axios';
import Vue from 'vue';

import router from '@/router/index.js';
import store from '@/store/index.js';

import { environment } from '@/helpers/apiUtilities.js';
import helpers from '@/helpers/helpers.js';

import App from '@/App.vue';

// Import Sass/CSS libraries here that use relative links to fonts/images
import 'font-awesome/scss/font-awesome.scss';
import 'roboto-fontface/css/roboto/roboto-fontface.css';

// Import in rest of styles
import '@/sass/style.sass';

// ...

My attempts to work with order. I'm very open to suggestions

    'import/order': [
      'error',
      {
        'alphabetize': {
          'caseInsensitive': false,
          'order': 'asc'
        },
        'groups': [
          'builtin',
          'external',
          'internal',
          'parent',
          'sibling',
          'index',
          'object',
          'type'
        ],
        'newlines-between': 'always',
        'pathGroups': [
          {
            'pattern': '@/helpers/**',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '@/mixins/**',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '**/*.vue',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '@@/**',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '**/*.css',
            'group': 'type',
            'position': 'after'
          },
          {
            'pattern': '**/*.scss',
            'group': 'type',
            'position': 'after'
          }
        ],
        'pathGroupsExcludedImportTypes': [
          '**/*.css',
          '**/*.scss'
        ],
        'warnOnUnassignedImports': true
      }
    ],

TheJaredWilcurt avatar Mar 04 '22 17:03 TheJaredWilcurt

Also tried with:

    'import/order': [
      'error',
      {
        'alphabetize': {
          'caseInsensitive': false,
          'order': 'asc'
        },
        'groups': [
          'builtin',
          'external',
          'internal',
          'parent',
          'sibling',
          'index',
          'object',
          'type'
        ],
        'newlines-between': 'always',
        'pathGroups': [
          {
            'pattern': '@/helpers/**',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '@/mixins/**',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '**/*.vue',
            'group': 'object',
            'position': 'before'
          },
          {
            'pattern': '@@/**',
            'group': 'object',
            'position': 'before'
          }
        ]
      }
    ],

TheJaredWilcurt avatar Mar 09 '22 23:03 TheJaredWilcurt

Current workaround is to create a styles.js file. Move the imports there in the order they should be and disable the import/order rule in that file. Then do

// main.js
import axios from 'axios';
import Vue from 'vue';

import router from '@/router/index.js';
import store from '@/store/index.js';

import { environment } from '@/helpers/apiUtilities.js';
import helpers from '@/helpers/helpers.js';

import App from '@/App.vue';

// eslint-disable-next-line no-unused-vars, import/order
import styles from '@/styles.js';

// ...

TheJaredWilcurt avatar Mar 10 '22 18:03 TheJaredWilcurt

Since it's a side-effecting import, i'd do import from '@/styles'; and then you don't need to disable either rule on the importing side.

ljharb avatar Mar 10 '22 19:03 ljharb

I'd rather just not have to do the workaround at all.

TheJaredWilcurt avatar Mar 11 '22 16:03 TheJaredWilcurt

Sure, I can understand that - but style imports are themselves a non-standard hack/workaround, so I'm not sure workarounds are really avoidable when using them.

ljharb avatar Mar 11 '22 16:03 ljharb

same issue +1

lake2 avatar Apr 16 '22 09:04 lake2

I think importing (S)CSS into JavaScript files is becoming increasingly common in the React world, esp via .module.scss files, so it might be worth reconsidering this.

jackkinsella avatar Feb 09 '23 23:02 jackkinsella