BLOG POSTS
Vue.js with ESLint and Prettier Setup Guide

Vue.js with ESLint and Prettier Setup Guide

Setting up Vue.js with ESLint and Prettier is like having a stern code reviewer and a perfectionist formatter working together to keep your codebase clean and consistent. ESLint catches potential bugs and enforces coding standards, while Prettier handles the formatting automatically, eliminating those endless debates about semicolons and indentation. This guide walks you through the complete setup process, from initial configuration to advanced customization, plus troubleshooting the inevitable conflicts that arise when these tools don’t play nice together.

How ESLint and Prettier Work Together

ESLint is a static analysis tool that identifies problematic patterns in JavaScript code, while Prettier is an opinionated code formatter that enforces consistent style. The challenge is that they sometimes step on each other’s toes – ESLint might complain about formatting that Prettier automatically applies.

The solution involves three key packages:

  • eslint-config-prettier – Disables ESLint rules that conflict with Prettier
  • eslint-plugin-prettier – Runs Prettier as an ESLint rule
  • @vue/eslint-config-prettier – Vue-specific integration

This setup lets you run eslint --fix and get both linting and formatting in one command, which is particularly useful for CI/CD pipelines and pre-commit hooks.

Step-by-Step Setup Guide

Starting with a fresh Vue.js project gives you the cleanest setup. If you’re working with an existing project, you might need to resolve some conflicts along the way.

Creating a New Vue Project with ESLint

Use Vue CLI to scaffold a project with ESLint pre-configured:

npm install -g @vue/cli
vue create my-vue-app

# Select the following options:
# - Manually select features
# - Choose Vue version: 3.x
# - Linter / Formatter: ESLint + Prettier
# - ESLint config: ESLint + Prettier
# - Lint on save: Yes

If you prefer Vite over Vue CLI:

npm create vue@latest my-vue-app
cd my-vue-app
npm install

Manual Installation for Existing Projects

For existing Vue projects, install the necessary packages:

npm install --save-dev eslint prettier
npm install --save-dev eslint-plugin-vue
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
npm install --save-dev @vue/eslint-config-prettier

Create an .eslintrc.js file in your project root:

module.exports = {
  root: true,
  env: {
    node: true,
    'vue/setup-compiler-macros': true
  },
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/prettier'
  ],
  parserOptions: {
    ecmaVersion: 2020
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'vue/multi-word-component-names': 'off'
  }
}

Create a .prettierrc file for Prettier configuration:

{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "none",
  "printWidth": 80,
  "bracketSpacing": true,
  "arrowParens": "avoid"
}

Add a .prettierignore file to exclude certain files:

dist/
node_modules/
*.min.js
*.map
package-lock.json
yarn.lock

Package.json Scripts

Add these useful scripts to your package.json:

{
  "scripts": {
    "lint": "eslint --ext .js,.vue --ignore-path .eslintignore .",
    "lint:fix": "eslint --ext .js,.vue --ignore-path .eslintignore . --fix",
    "format": "prettier --write \"src/**/*.{js,vue,css,scss,html}\"",
    "format:check": "prettier --check \"src/**/*.{js,vue,css,scss,html}\""
  }
}

Configuration Options and Customization

The default setup works well, but you’ll likely want to customize rules based on your team’s preferences. Here are some common configurations:

Stricter Vue.js Rules

For more comprehensive Vue.js linting, use the recommended or strongly-recommended rule sets:

module.exports = {
  extends: [
    'plugin:vue/vue3-strongly-recommended', // or vue3-recommended
    'eslint:recommended',
    '@vue/prettier'
  ],
  rules: {
    'vue/component-name-in-template-casing': ['error', 'PascalCase'],
    'vue/require-default-prop': 'error',
    'vue/require-prop-types': 'error',
    'vue/no-unused-properties': 'warn'
  }
}

TypeScript Support

If you’re using TypeScript, install additional packages:

npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser
npm install --save-dev @vue/eslint-config-typescript

Update your ESLint configuration:

module.exports = {
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/typescript/recommended',
    '@vue/prettier',
    '@vue/prettier/@typescript-eslint'
  ],
  parserOptions: {
    ecmaVersion: 2020
  }
}

IDE Integration and Workflow

Getting your editor to work seamlessly with ESLint and Prettier saves tons of time. Here’s how to set up the most popular editors:

VS Code Setup

Install these extensions:

  • ESLint by Microsoft
  • Prettier – Code formatter by Prettier
  • Vetur or Volar for Vue.js support

Create a .vscode/settings.json file:

{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "vue"
  ],
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

Pre-commit Hooks with Husky

Enforce code quality before commits hit your repository:

npm install --save-dev husky lint-staged

# Initialize husky
npx husky install
npm pkg set scripts.prepare="husky install"

# Add pre-commit hook
npx husky add .husky/pre-commit "npx lint-staged"

Add this to your package.json:

{
  "lint-staged": {
    "*.{js,vue}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{css,scss,html,json,md}": [
      "prettier --write"
    ]
  }
}

Common Issues and Troubleshooting

Here are the most frequent problems you’ll encounter and their solutions:

Conflicting Rules

If ESLint and Prettier are fighting over formatting, you’ll see errors like:

Expected 1 space after 'if' keyword eslint(keyword-spacing)
Delete ';' prettier/prettier

The fix is ensuring @vue/prettier comes last in your extends array:

extends: [
  'plugin:vue/vue3-essential',
  'eslint:recommended',
  '@vue/prettier'  // Must be last
]

Import/Export Issues

If you see “Parsing error: Unexpected token import”, your parser isn’t configured for ES6 modules:

parserOptions: {
  ecmaVersion: 2020,
  sourceType: 'module'
}

Vue 3 Composition API

For Vue 3 with <script setup>, add this to your ESLint config:

env: {
  'vue/setup-compiler-macros': true
}

Performance Issues

Large codebases might experience slow linting. Create an .eslintignore file:

node_modules/
dist/
*.min.js
coverage/
.nuxt/

Comparison with Alternative Setups

Setup Pros Cons Best For
ESLint + Prettier Comprehensive, configurable, great IDE support Complex configuration, potential conflicts Team projects, strict standards
ESLint only Simple setup, fewer dependencies Limited formatting capabilities Solo projects, minimal setup
Prettier only Zero config formatting No code quality checks Pure formatting needs
Standard.js No configuration needed Opinionated, less flexible Quick prototypes, standard adherence

Real-World Use Cases and Examples

Here’s a practical example of how this setup improves code quality in a Vue.js component:

Before ESLint/Prettier

<template>
<div class="user-card">
<h2>{{user.name}}</h2>
<p v-if="user.email">{{ user.email }}</p>
<button @click="deleteUser">Delete</button>
</div>
</template>

<script>
export default{
name:'UserCard',
props:{
user:Object
},
methods:{
deleteUser(){
console.log('Deleting user...')
this.$emit('delete',this.user.id)
}
}
}
</script>

After ESLint/Prettier

<template>
  <div class="user-card">
    <h2>{{ user.name }}</h2>
    <p v-if="user.email">{{ user.email }}</p>
    <button @click="deleteUser">Delete</button>
  </div>
</template>

<script>
export default {
  name: 'UserCard',
  props: {
    user: {
      type: Object,
      required: true
    }
  },
  emits: ['delete'],
  methods: {
    deleteUser() {
      this.$emit('delete', this.user.id)
    }
  }
}
</script>

The automated fixes include proper indentation, spacing, prop validation, and explicit emits declaration – all crucial for maintainable Vue.js applications.

Best Practices and Advanced Configuration

Once you have the basic setup running, consider these advanced practices:

Environment-Specific Rules

Different rules for development and production:

rules: {
  'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
  'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
  'vue/no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'warn'
}

Custom Rule Configuration

Tailor rules to your team’s needs:

rules: {
  'vue/max-attributes-per-line': ['error', {
    'singleline': 3,
    'multiline': 1
  }],
  'vue/html-self-closing': ['error', {
    'html': {
      'void': 'always',
      'normal': 'never',
      'component': 'always'
    }
  }]
}

CI/CD Integration

Add linting to your CI pipeline:

# GitHub Actions example
name: Code Quality
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '16'
      - run: npm ci
      - run: npm run lint
      - run: npm run format:check

This setup creates a robust development environment where code quality is maintained automatically. The initial configuration might seem complex, but it pays dividends in reduced bugs, consistent formatting, and smoother code reviews. For comprehensive documentation, check the official Vue ESLint plugin docs and Prettier’s configuration guide.

Remember that tools should serve your team, not the other way around. Start with the recommended configuration and adjust rules based on your actual development experience and team preferences.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked