javascript – Vite/Vue3 throws Internal server error (experimental syntax / missing parser plugin: decorators) after upgrade

After updating Vite I can’t start my project anymore because I get the following error message:

[vite] Internal server error: This experimental syntax requires enabling one of the following parser plugin(s): "decorators-legacy","decorators"

Before the update everything was running without problems and also the log doesn’t really help me. I use SFC in Vue and vue-class-component and vue-property-decorator for my components.

I have updated:

vite: 2.6.14 -> 2.9.12
@vitejs/plugin-vue: 1.8.0 -> 2.3.3
@vue/compiler-sfc: 3.2.22 -> removed, because it is now a part of plugin-vue

The problem occurs with both the “vite” and “vite build” scripts. The errors it finds seem to occur mainly in the part of the components:

// Log

12:55:04 [vite] Internal server error: This experimental syntax requires enabling one of the following parser plugin(s): "decorators-legacy", "decorators". (7:2)
  Plugin: vite:vue
  File: A:/repositories/private/scribe/src/components/app/ui/tooltip/Tooltip.vue
  6  |      <div
  7  |        class="tooltip"
  8  |        :class="{
     |      ^
  9  |          'tooltip--show': show,
  10 |          'tooltip--left': isLeft,
12:55:06 [vite] Internal server error: This experimental syntax requires enabling one of the following parser plugin(s): "decorators-legacy", "decorators". (21:2)
  Plugin: vite:vue
  File: A:/repositories/private/scribe/src/components/app/ui/dropdown/Dropdown.vue
  9  |        :class="{
  10 |          'dropdown-list--expanded': open,
  11 |          'dropdown-list--wide': wide,
     |                                     ^
  12 |          'dropdown-list--expanded-top': open && top,
  13 |        }"

These are the dependencies currently installed:

// package.json

...

  "dependencies": {
    "@apollo/client": "3.6.9",
    "@fortawesome/fontawesome-svg-core": "6.1.1",
    "@fortawesome/free-brands-svg-icons": "6.1.1",
    "@fortawesome/free-regular-svg-icons": "6.1.1",
    "@fortawesome/free-solid-svg-icons": "6.1.1",
    "@fortawesome/vue-fontawesome": "3.0.0-5",
    "@samuelmeuli/font-manager": "1.4.0",
    "@tiptap/extension-font-family": "2.0.0-beta.24",
    "@tiptap/extension-image": "2.0.0-beta.30",
    "@tiptap/extension-link": "2.0.0-beta.42",
    "@tiptap/extension-text-align": "2.0.0-beta.31",
    "@tiptap/extension-text-style": "2.0.0-beta.26",
    "@tiptap/extension-underline": "2.0.0-beta.25",
    "@tiptap/starter-kit": "2.0.0-beta.189",
    "@tiptap/vue-3": "2.0.0-beta.95",
    "@types/he": "1.1.2",
    "@vue/apollo-composable": "4.0.0-alpha.18",
    "@vuelidate/core": "2.0.0-alpha.41",
    "@vuelidate/validators": "2.0.0-alpha.29",
    "click-outside-vue3": "4.0.1",
    "core-js": "3.23.2",
    "crypto-js": "4.1.1",
    "date-fns": "2.28.0",
    "dompurify": "2.3.8",
    "downloadjs": "1.4.7",
    "graphql": "16.5.0",
    "graphql-tag": "2.12.6",
    "he": "1.2.0",
    "html2canvas": "1.4.1",
    "jsonpack": "1.1.5",
    "localforage": "1.10.0",
    "lodash": "4.17.21",
    "mitt": "3.0.0",
    "object-hash": "3.0.0",
    "prismjs": "1.28.0",
    "register-service-worker": "1.7.2",
    "splitpanes": "3.1.1",
    "typogr": "0.6.8",
    "vite-plugin-markdown": "2.0.2",
    "vue": "3.2.37",
    "vue-class-component": "8.0.0-rc.1",
    "vue-color-kit": "1.0.5",
    "vue-gtag": "2.0.1",
    "vue-i18n": "9.1.10",
    "vue-prism-editor": "2.0.0-alpha.2",
    "vue-property-decorator": "10.0.0-rc.3",
    "vue-router": "4.0.16",
    "vue-scrollto": "2.20.0",
    "vue-waypoint": "4.2.1",
    "vuedraggable": "4.1.0",
    "vuex": "4.0.2"
  },
  "devDependencies": {
    "@intlify/vite-plugin-vue-i18n": "3.4.0",
    "@intlify/vue-i18n-loader": "4.2.0",
    "@types/crypto-js": "4.1.1",
    "@types/dompurify": "2.3.3",
    "@types/downloadjs": "1.4.3",
    "@types/jsonpack": "1.1.1",
    "@types/lodash": "4.14.182",
    "@types/object-hash": "2.2.1",
    "@types/prismjs": "1.26.0",
    "@types/splitpanes": "2.2.1",
    "@typescript-eslint/eslint-plugin": "5.29.0",
    "@typescript-eslint/parser": "5.29.0",
    "@vitejs/plugin-vue": "2.3.3",
    "@vue/eslint-config-prettier": "7.0.0",
    "@vue/eslint-config-typescript": "11.0.0",
    "eslint": "8.18.0",
    "eslint-plugin-import": "2.26.0",
    "eslint-plugin-prettier": "4.0.0",
    "eslint-plugin-vue": "9.1.1",
    "lint-staged": "13.0.2",
    "prettier": "2.7.1",
    "sass": "1.53.0",
    "sass-loader": "13.0.0",
    "typescript": "4.7.4",
    "vite": "2.9.12",
    "vite-plugin-commonjs": "0.5.2",
    "vite-plugin-i18n-resources": "1.0.3",
    "vite-plugin-package-version": "1.0.2",
    "vue-tsc": "0.38.1"
  },

My Typescript configuration:

// tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "useDefineForClassFields": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ],
    "types": [
      "@intlify/vite-plugin-vue-i18n/client"
    ],
    "typeRoots": [
      "./src/types",
      "./node_modules/@types"
    ],
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

And my Vite configuration:

// vite.config.json

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import loadVersion from "vite-plugin-package-version";
import i18nResources from "vite-plugin-i18n-resources";
import markdown, { Mode } from "vite-plugin-markdown";
import { resolve } from "path";

const path = require("path")

function graphQlFile() {
  return {
    name: 'graphql-file',
    transform(src, id) {
      if (id.endsWith(".graphql") || id.endsWith(".gql")) {
        const str = JSON.stringify(src)
        return {
          code: "import gql from 'graphql-tag';const doc="+str+"; export default gql`${doc}`",
          map: null
        }
      }
    }
  }
}

export const ssrTransformCustomDirective = () => {
  return {
    props: [],
    needRuntime: true
  }
}

export default defineConfig({
  server: {
    port: 8080
  },
    resolve: {
    alias: [
      {
        find: "@",
        replacement: path.resolve(__dirname, "src")
      }
    ]
  },
  plugins: [
    vue({
      template: {
        ssr: true,
        compilerOptions: {
          directiveTransforms: {
            "click-outside": ssrTransformCustomDirective,
            "safe-html": ssrTransformCustomDirective
          }
        }
      }
    }),
    i18nResources({
      path: resolve(__dirname, "./src"),
    }),
    loadVersion(),
    graphQlFile(),
    markdown({ mode: Mode.HTML })
  ]
})

Leave a Comment