为啥 vue 在第一次编译时无法识别 TS 语法,但在第二次编译时可以正常工作?
Posted
技术标签:
【中文标题】为啥 vue 在第一次编译时无法识别 TS 语法,但在第二次编译时可以正常工作?【英文标题】:Why does vue fail to recognize TS syntax on the first compilation, but works okay on the second one?为什么 vue 在第一次编译时无法识别 TS 语法,但在第二次编译时可以正常工作? 【发布时间】:2020-06-11 20:51:03 【问题描述】:我遇到了一个奇怪的错误,即 vue cli 在第一次执行时无法识别 TypeScript 语法,但在第二次执行时工作正常。
如果删除node_modules/.cache
再执行命令:
yarn build
您在第一次调用时收到此错误:
ERROR Failed to compile with 1 errors 3:54:55 PM
error in ./src/components/ATSText/TextDate.vue
Module Error (from ./node_modules/eslint-loader/index.js):
error: Parsing error: Unexpected token : at src\components\ATSText\TextDate.vue:69:11:
67 | computed:
68 | dateFormatted:
> 69 | get(): string
| ^
70 | return this.formatDate(this.value);
71 | ,
72 | set(val: string)
1 error found.
@ ./src/utils/schemaConverter.ts 13:47-92
@ ./node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/ts-loader??ref--14-3!./node_modules/vuetify-loader/lib/loader.js??ref--20-0!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/Schema.vue?vue&type=script&lang=ts&
@ ./src/views/Schema.vue?vue&type=script&lang=ts&
@ ./src/views/Schema.vue
@ ./src/router/index.ts
@ ./src/main.ts
@ multi ./src/main.ts
ERROR Build failed with errors.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
如果再次执行相同的命令,编译会正常:
DONE Build complete. The dist directory is ready to be deployed.
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
Done in 28.14s.
如果删除缓存并重复该过程,则循环重复。
作为参考,这些是相关的源文件:
TextDate.vue:
<template>
<v-menu
ref="menu"
v-model="menu"
offset-y
transition="scale-transition"
max-
min-
:close-on-content-click="false"
>
<template v-slot:activator=" on ">
<v-text-field
v-model="dateFormatted"
v-mask="'##/##/####'"
v-on="on"
dense
outlined
hide-details
prepend-inner-icon="event"
:label="label"
:tabindex="tabindex"
:value="value"
@blur="onblur"
@input="oninput"
/>
</template>
<v-date-picker
v-model="date"
no-title
@input="menu = false"
/>
</v-menu>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend(
props:
label: String,
hideDetails:
type: [String, Boolean],
default: false
,
noResize:
type: Boolean,
default: true
,
value: String,
hint: String,
tabindex: [String, Number]
,
data()
return
menu: undefined,
date: undefined
,
watch:
date(val)
if (val)
this.dateFormatted = this.formatDate(val);
,
value(val)
this.date = val
,
computed:
dateFormatted:
get(): string
return this.formatDate(this.value);
,
set(val: string)
this.$emit('input', this.parseDate(val));
,
,
methods:
oninput(val)
this.date = this.parseDate(val);
this.$emit('input', this.date);
,
onblur()
if (!this.date)
this.date = this.parseDateForce(this.dateFormatted)
,
formatDate (date)
if (!date) return null
const [year, month, day] = date.split('-')
return `$day/$month/$year`
,
parseDate (date)
if (!date || (date.length < 10))
return null;
const [day, month, year] = date.split('/')
const result = `$year-$month.padStart(2, '0')-$day.padStart(2, '0')`;
const nDate = new Date(result);
if (!(nDate.getTime() === nDate.getTime()))
return null;
return result;
,
parseDateForce (date)
if (!date || (date.length < 8))
return null;
const [day, month, year] = date.split('/')
let result
if (year >= 70)
result = `$year.padStart(4, '1900')-$month.padStart(2, '0')-$day.padStart(2, '0')`;
else
result = `$year.padStart(4, '2000')-$month.padStart(2, '0')-$day.padStart(2, '0')`;
const nDate = new Date(result);
if (!(nDate.getTime() === nDate.getTime()))
return null;
return result;
,
,
)
</script>
package.json
"name": "framework-ats",
"version": "0.1.0",
"private": true,
"scripts":
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"electron:build": "vue-cli-service electron:build",
"electron:serve": "vue-cli-service electron:serve",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps"
,
"main": "background.ts",
"dependencies":
"@rauschma/stringio": "^1.4.0",
"@types/lodash": "^4.14.149",
"ajv-i18n": "^3.5.0",
"core-js": "^3.4.4",
"lodash": "^4.17.15",
"node-firebird": "^0.8.9",
"typed-rest-client": "^1.7.1",
"typescript-ioc": "^1.2.6",
"v-money": "^0.8.1",
"vue": "^2.6.10",
"vue-class-component": "^7.2.2",
"vue-form-json-schema": "^2.5.0",
"vue-property-decorator": "^8.3.0",
"vue-router": "^3.1.5",
"vue-the-mask": "^0.11.1",
"vuetify": "^2.1.0"
,
"devDependencies":
"@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-eslint": "^4.1.0",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-plugin-typescript": "^4.2.2",
"@vue/cli-service": "^4.1.0",
"@vue/eslint-config-typescript": "^4.0.0",
"babel-eslint": "^10.0.3",
"electron": "^6.0.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"material-design-icons-iconfont": "^5.0.1",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"typescript": "~3.7.5",
"vue-cli-plugin-electron-builder": "^1.4.4",
"vue-cli-plugin-vuetify": "^2.0.4",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.3.0"
tsconfig.json:
"compilerOptions":
"target": "es6",
"module": "commonjs",
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"typeRoots": [
"./node_modules/@types",
"./node_modules/vuetify/types"
],
"types": [
"webpack-env",
"vuetify"
],
"paths":
"@/*": [
"src/*"
]
,
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
,
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
vue.config.ts:
module.exports =
"devServer":
"disableHostCheck": true
,
"transpileDependencies": [
"vuetify"
]
【问题讨论】:
【参考方案1】:在eslintrc
中使用@typescript-eslint/parser
到parserOptions.parser
可以解决问题。
https://github.com/vuejs/vue-cli/issues/5227#issuecomment-788639361
【讨论】:
【参考方案2】:更正实际上很简单,但很难找到: https://github.com/vuejs/vue-cli/issues/5227
为了解决问题,需要修改.eslintrc.js
,将"parser": "babel-eslint"
添加到parserOptions
中:
module.exports =
"env":
"browser": true,
"es6": true,
"node": true
,
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/essential"
],
"globals":
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
,
"parserOptions":
"parser": "babel-eslint",
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures":
"modules": true
,
"plugins": [
"vue"
],
"rules":
"no-console": "off",
"@typescript-eslint/indent": "off"
;
【讨论】:
以上是关于为啥 vue 在第一次编译时无法识别 TS 语法,但在第二次编译时可以正常工作?的主要内容,如果未能解决你的问题,请参考以下文章
Vue.config.js 无法识别 require('webpack')
前端vue中ts无法识别引入的vue文件,提示找不到xxx.vue模块的解决引入新建页面或者通过router引入时报错
前端vue中ts无法识别引入的vue文件,提示找不到xxx.vue模块的解决引入新建页面或者通过router引入时报错