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

Import in body of module; reorder to top. eslint(import/first)

Open lipengzhou opened this issue 4 years ago • 14 comments

Checklist

  • [X] I have tried restarting my IDE and the issue persists.
  • [X] I have read the FAQ and my problem is not listed.

Tell us about your environment

  • ESLint version: 7.31.0
  • eslint-plugin-vue version: 7.14.0
  • Node version: 14.15.1
  • Operating System: Windows 10

Please show your full configuration:

module.exports = {
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly'
  },
  env: {
    browser: true,
    es2021: true
  },
  extends: ['plugin:vue/vue3-strongly-recommended', 'standard'],
  parserOptions: {
    ecmaVersion: 12,
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: ['vue', '@typescript-eslint'],
  rules: {}
}

What did you do?

<script lang="ts">
export default {
  name: 'HomeIndex'
}
</script>

<script lang="ts" setup>
import foo from './foo.vue'

</script>

What did you expect to happen?

If use alongside normal

Then I tried to adjust their position, put script setup on top, normal script on the bottom without this error, but at run time will throw an exception:ReferenceError: Cannot access '__default__' before initialization

I think it's a contradictory question。

What actually happened?

error  Import in body of module; reorder to top  import/first

Repository to reproduce this issue

lipengzhou avatar Jul 19 '21 11:07 lipengzhou

As far as I know, it's technically impossible to be compatible with that rule. Please let me know if anyone knows a good way.

ota-meshi avatar Jul 19 '21 12:07 ota-meshi

What about just disabling the rule?

// .eslintrc.js
{
// options
  rules: {
    'import/first': 'off'
  }
}

Mootook avatar Oct 01 '21 19:10 Mootook

Would there be a way to just have it disabled for files that use script setup? Ideally this is enforced where applicable and if script setup can not be in compliance with it I would rather not turn it off completely for my whole entire project.

Is it not possible to enforce the rule in the sense that the imports are always at the top of each individual script tag?

I.E. below is fine

<script>
import foo from 'bar'

// some code
</script>
<script setup>
import otherModule from 'baz'

// some code
</script>

while the below would report the error

<script>
import foo from 'bar'

// some code
</script>
<script setup>
// some code

 // error here since import is not at the top of the script tag
import otherModule from 'baz'
</script>

kalvenschraut avatar Dec 09 '21 17:12 kalvenschraut

I think there is nothing we can do about this in eslint-plugin-vue, as this error is caused by eslint-plugin-import and Vue core.

@ota-meshi @mysticatea Maybe vue-eslint-parser could do something to fix this?

FloEdelmann avatar Feb 02 '22 21:02 FloEdelmann

+1 for this. I ran into the same issue

ahnpnl avatar May 04 '22 07:05 ahnpnl

As noted in #1700 if you run eslint with the --fix flag, the linter will actually rearrange your <script> and <script setup> blocks, potentially changing the meaning of the Vue code.

<script lang="ts">
export default {
  name: 'HomeIndex'
}
</script>

<script lang="ts" setup>
import foo from './foo.vue'

</script>

changes to

<script lang="ts">
</script>

<script lang="ts" setup>
import foo from './foo.vue'
export default {
  name: 'HomeIndex'
}

</script>

The automated linter will move the export to the wrong block.

Any user of eslint-plugin-vue should probably set 'import/first': 'off' until this is fixed. You don't want your linter silently changing the meaning of your Vue code.

morgan-atproperties avatar Jun 10 '22 16:06 morgan-atproperties

Here is a more complete example.

<!--
 Modified version of script setup example
 documented here: https://vuejs.org/api/sfc-script-setup.html#usage-alongside-normal-script
-->

<script>
// normal <script>, executed in module scope (only once)
const runSideEffectOnce = () => {}
runSideEffectOnce()

// declare additional options
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script setup>
// executed in setup() scope (for each instance)
import HelloWorld from './HelloWorld.vue'
HelloWorld.hello()
</script>

becomes

<script>
// normal <script>, executed in module scope (only once)
</script>

<script setup>
// executed in setup() scope (for each instance)
import HelloWorld from './HelloWorld.vue'
const runSideEffectOnce = () => {}
runSideEffectOnce()

// declare additional options
export default {
  inheritAttrs: false,
  customOptions: {}
}
HelloWorld.hello()
</script>

morgan-atproperties avatar Jun 10 '22 16:06 morgan-atproperties

Hello everyone! I have the same troubles. Maybe there are some updates on how to solve this problem without disabling the eslint rule?

basil-gor avatar Jan 04 '23 07:01 basil-gor

Any updates?

nestle49 avatar Feb 28 '23 13:02 nestle49

No, please see the comment thread above. If a fix or workaround can be found (and it's not clear if that's possible at all), it will be commented here. Please only comment new information in this issue and stop asking for updates.

FloEdelmann avatar Feb 28 '23 13:02 FloEdelmann

In Vue 3.3, you can now use defineOptions in <script setup> and avoid this issue altogether, see https://blog.vuejs.org/posts/vue-3-3#defineoptions and https://vuejs.org/api/sfc-script-setup.html#defineoptions.

<script lang="ts" setup>
import foo from './foo.vue'

defineOptions({
  name: 'HomeIndex'
})
</script>

FloEdelmann avatar Jun 21 '23 13:06 FloEdelmann