- This package contains custom rules to enforce the order of declarations within
<script setup>
in Vue 3.
The declarations in <script setup>
are sorted in the following fixed order:
"type",
"defineProps",
"defineEmits",
"defineSlots",
"defineModel",
"defineOptions",
"class",
"plainVars",
"reactiveVars",
"composables",
"computed",
"watchers",
"lifecycle",
"unknowns",
"functions",
"defineExpose"
A single blank line (which corresponds to two consecutive newline characters) is inserted between different groups.
This means that if you have a group of define declarations followed by another group (such as "plainVars"),
there will be one blank line between these groups in the final sorted output.
Example: Consider the following two groups:
Group 1 (defineProps):
const aa = defineProps<{ msg: string }>();
Group 2 (plain variable declarations):
const hello = "Hello World!";
const count = 0
The final sorted output will be:
const aa = defineProps<{ msg: string }>();
const hello = "Hello World!";
const count = 0
Notice the blank line between the two groups, which helps visually separate different types of declarations.
By default, the rule enforces the predefined order of declarations within <script setup>
.
However, you can customize the declaration order by specifying the sectionOrder
option in eslint.config.js
.
By default, the rule follows this order:
"type",
"defineProps",
"defineEmits",
"defineSlots",
"defineModel",
"defineOptions",
"class",
"plainVars",
"reactiveVars",
"composables",
"computed",
"watchers",
"lifecycle",
"unknowns",
"functions",
"defineExpose"
If you want to specify a custom order, you can do so in eslint.config.js by providing a sectionOrder array.
Example: Prioritizing defineProps and plainVars
// eslint.config.js
export default [
{
files: ["**/*.vue"],
languageOptions: {
parser: vueEslintParser,
parserOptions: {
parser: typescriptEslintParser,
ecmaVersion: 2022,
sourceType: "module",
},
},
plugins: {
"vue3-script-setup": {
rules: {
"declaration-order": eslintVueSetupOrderRule,
},
},
},
rules: {
"vue3-script-setup/declaration-order": [
"error",
{
sectionOrder: ["defineProps", "plainVars"], // this!!
},
],
},
},
];
In this case:
- defineProps will always be placed before plainVars.
- Other declarations will follow their default order.
If an invalid section is provided in sectionOrder, an ESLint error will be thrown.
For example, this incorrect configuration:
"vue3-script-setup/declaration-order": [
"error",
{
sectionOrder: ["defineProps", "invalidSection"],
},
],
will result in the following error:
Error: Invalid "sectionOrder" option: "invalidSection" is not a recognized section. Valid sections: defineProps, defineEmits, defineOthers, plainVars, reactiveVars, composables, computed, watchers, lifecycle, functions, unknowns.
This ensures that only valid sections are allowed, preventing misconfiguration.
With this customization, you can fine-tune the declaration order to suit your projectβs coding style while still enforcing consistency. π
By default, the rule enforces the predefined order of declarations within <script setup>
.
However, you can customize the declaration order by specifying the lifecycleOrder
option in eslint.config.js
.
By default, the rule follows this order:
onBeforeMount: 0,
onMounted: 1,
onBeforeUpdate: 2,
onUpdated: 3,
onBeforeUnmount: 4,
onUnmounted: 5,
onErrorCaptured: 6,
onRenderTracked: 7,
onRenderTriggered: 8,
onActivated: 9,
onDeactivated: 10,
onServerPrefetch: 11,
If you want to specify a custom order, you can do so in eslint.config.js by providing a lifecycleOrder object.
Example: Prioritizing defineProps and plainVars
// eslint.config.js
export default [
{
files: ["**/*.vue"],
languageOptions: {
parser: vueEslintParser,
parserOptions: {
parser: typescriptEslintParser,
ecmaVersion: 2022,
sourceType: "module",
},
},
plugins: {
"vue3-script-setup": {
rules: {
"declaration-order": eslintVueSetupOrderRule,
},
},
},
rules: {
"vue3-script-setup/declaration-order": [
"error",
{
lifecycleOrder: { // this!!
onMounted: 0,
onBeforeMount: 1,
}
},
],
},
},
];
In this case:
- onMounted will always be placed before onBeforeMount.
pnpm install eslint-vue-setup-rules
OR
yarn add eslint-vue-setup-rules
OR
pnpm install https://github.com/KumJungMin/eslint-vue-setup-order
Then, add the ESLint plugin to your eslint.config.js
(for ESLint v9 using the flat config pattern):
// eslint.config.js
import vueSetupRules from "eslint-vue-setup-rules";
export default [
{
// Add the plugin object here:
plugins: { "vue3-script-setup": vueSetupRules },
rules: { "vue3-script-setup/declaration-order": "error" },
},
{
files: ["**/*.vue"],
languageOptions: {
parser: vueEslintParser,
parserOptions: {
parser: typescriptEslintParser,
ecmaVersion: 2022,
sourceType: "module",
},
},
},
// ... other settings
];
Alternatively, you can add the rule file directly to your project:
- Add the file
rules/declaration-order.js
to your project directory:
your-project/
βββ src/
β βββ eslint-rules/
β βββ declaration-order.js
βββ eslint.config.js
βββ ...
- Then, update your
eslint.config.js
to include the custom rule:
import eslintVueSetupOrderRule from "./src/eslint-rules/declaration-order.js";
export default [
{
files: ["**/*.vue"],
languageOptions: {
parser: vueEslintParser,
parserOptions: {
parser: typescriptEslintParser,
ecmaVersion: 2022,
sourceType: "module",
},
},
plugins: {
"vue3-script-setup": {
rules: {
"declaration-order": eslintVueSetupOrderRule, // this!
},
},
},
rules: {
"vue3-script-setup/declaration-order": "error",
},
},
// ... other settings
];
When you run the command:
npx eslint .
If the declaration order is incorrect, the rule will automatically fix it. For example:
Before:
<script setup lang="ts">
import { onBeforeMount, ref } from "vue";
const count = ref(0);
const msg = ref("");
const aa = defineProps<{ msg: string }>();
const emits = defineEmits();
const hello = "Hello World!";
const changeMsg = () => {};
function handleClick() {
emits("click");
}
onBeforeMount(() => {
console.log("onBeforeMount");
});
</script>
<template>
</template>
After (fixed):
<script setup lang="ts">
import { onBeforeMount, ref } from "vue";
const aa = defineProps<{ msg: string }>();
const emits = defineEmits();
const hello = "Hello World!";
const count = ref(0);
const msg = ref("");
onBeforeMount(() => {
console.log("onBeforeMount");
});
const changeMsg = () => {};
function handleClick() {
emits("click");
}
</script>