eslint-plugin-vue
eslint-plugin-vue copied to clipboard
Import in body of module; reorder to top. eslint(import/first)
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
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.
What about just disabling the rule?
// .eslintrc.js
{
// options
rules: {
'import/first': 'off'
}
}
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>
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?
+1 for this. I ran into the same issue
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.
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>
Hello everyone! I have the same troubles. Maybe there are some updates on how to solve this problem without disabling the eslint rule?
Any updates?
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.
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>