【问题标题】:Vite/Vue3 throws Internal server error (experimental syntax / missing parser plugin: decorators) after upgradeVite/Vue3 升级后抛出内部服务器错误(实验语法/缺少解析器插件:装饰器)
【发布时间】:2022-08-18 18:01:40
【问题描述】:

更新 Vite 后,我无法再启动我的项目,因为我收到以下错误消息:

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

在更新之前,一切运行都没有问题,而且日志并没有真正帮助我。 我在 Vue 中使用 SFC,在我的组件中使用 vue-class-component 和 vue-property-decorator。

我已经更新:

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

\"vite\" 和 \"vite build\" 脚本都会出现此问题。 它发现的错误似乎主要发生在组件的部分:

// 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 |        }\"

这些是当前安装的依赖项:

// 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\"
  },

我的打字稿配置:

// 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\"
  ]
}

还有我的 Vite 配置:

// 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 })
  ]
})

  • 你碰巧解决了这个问题吗?我自己也注意到了同样的事情,但是在这里和那里降级了一些依赖项,但错误并没有消失。 (是的,我在两者之间做了核弹node_modulespackage-lock.json
  • @Dids 还没有。我会让你知道我解决它。
  • 你碰巧在 M1 Mac 上吗?因为我已经恢复了每个依赖项,所以 Node.js 和 Vite/TypeScript 配置更改自上次 100% 工作以来,它仍然抛出相同的错误。但现在我开始思考,因为上次我在这方面工作时,我使用的是 Intel Mac,而我现在使用的是 M1 Mac。编辑:没关系,在 CI 上尝试过它仍然失败。我很难过。
  • 这已在 Vue 中得到修复,请参阅下面的更新答案。

标签: javascript typescript vue.js vuejs3 vite


【解决方案1】:

最新更新 - 18.8.2022

该问题现已在 Vue 中得到修复!

您可以找到修复 here 的拉取请求。


注意:以下信息已过时,请参阅顶部的更新,以及下面的进度更新!

找到了解决此特定错误的方法,但请注意,这只是部分解决方案,至少目前如此。 在撰写本文时,您需要使用 Vite 的预发布版本来解决问题。

就我而言,我只需要更新以下依赖项:

"@vitejs/plugin-vue": "3.0.0-beta.1",
"vite": "^3.0.0-beta.7",

您可能会在尝试安装这些包时遇到问题,因为其他包的版本要求不允许安装 Vite 的 3.x 包,在这种情况下,您可以简单地运行以下命令:

rm -fr node_modules package-lock.json
npm install --force

在此之后,您应该能够使用 Vite 构建和运行,而不用它(或 Babel)抱怨装饰器。

坏消息是,在此之后您可能会遇到其他新错误,我认为需要在 Vite 和所有使用它的插件/您的​​特定项目所需的所有插件中修复这些错误。


更新 - 21.7.2022

这个问题似乎来自 Vue 的单文件组件 (SFC) 编译器,现在他们的 GitHub 存储库中有一个未解决的问题: https://github.com/vuejs/core/issues/6318

此外,同一个人似乎已经制定了解决问题的拉取请求,该请求仍然在此处打开: https://github.com/vuejs/core/pull/6320

从上面的问题和拉取请求来看,我们看到的问题似乎是由在export default ... 之前使用装饰器明确引起的,它没有被正确地重写/转译,从而导致了这个问题。

现在我们要么需要等待,要么在本地进行更改,要么分叉我们自己的副本并应用拉取请求的修复,然后使用我们的分叉版本的 SFC 编译器。手指交叉,这应该可以解决它!

编辑:我尝试了修复并可以确认它有效!下面是我现在如何将它应用到我的项目中,以防你(或其他任何人)想尝试它)。

package.json 的更改:

"scripts": {
  "postinstall": "npm run patch-vue-compiler-sfc",
  "patch-vue-compiler-sfc": "patch --ignore-whitespace -p0 --forward < vue-compiler-sfc.patch || true"
}

使用以下内容创建一个名为 vue-compiler-sfc.patch 的新补丁文件:

--- node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js.orig    2022-08-02 12:54:51
+++ node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js 2022-08-02 16:10:06
@@ -3352,7 +3352,12 @@
     }).program.body;
     ast.forEach(node => {
         if (node.type === 'ExportDefaultDeclaration') {
-            s.overwrite(node.start, node.declaration.start, `const ${as} = `);
+            if (node.declaration.type === 'ClassDeclaration') {
+                s.overwrite(node.start, node.declaration.id.start, `class `)
+                s.append(`\nconst ${as} = ${node.declaration.id.name}`)
+            } else {
+                s.overwrite(node.start, node.declaration.start, `const ${as} = `)
+            }
         }
         if (node.type === 'ExportNamedDeclaration') {
             for (const specifier of node.specifiers) {

现在只需运行npm i 并应用补丁程序,您的项目现在应该消除此错误,即使只是一个临时解决方案。

【讨论】:

  • 这只会改变我的错误。现在我得到:Decorators can only be used with class declarations in TypeScript[vite] Internal server error: Cannot overwrite across a split point 我认为这是一个问题:vue-property-decorator 在这一点上,我计划完全切换到组合 API,并希望一切正常
  • 查看更新的答案,现在隧道尽头有光!
  • 再次更新,这次提供了有关在本地修补问题的快速说明,只需最少的工作。
  • @Nebulosar 尝试将--ignore-whitespace 添加到patch 命令的参数中。我已经编辑了上面的答案以反映这一点。如果这还不够,补丁文件只需要在最后一个新行,那么它应该可以工作。
  • 我更新了package.jsonvue-sfc-compiler.patch,现在更详细,但在修补时也更宽容,例如。行尾和空格不再重要。此外,通过在package.json 中使用postinstall,它现在将尝试在每次运行npm install 时应用补丁。
猜你喜欢
  • 2023-01-29
  • 1970-01-01
  • 2019-09-08
  • 2022-08-11
  • 2023-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多