4

I am facing a weird bug where the vue cli fails to recognize TypeScript syntax on the first time it is executed, but works okay on the second one.

If you delete node_modules/.cache and then execute the command:

yarn build

You get this error on the first call:

 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.

If you execute the same command again, the compilation goes fine:

 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.

If you delete the cache and repeat the process, the cycle repeats.

For reference, these are the relevant source files:

TextDate.vue:

<template>
  <v-menu
    ref="menu"
    v-model="menu"
    offset-y
    transition="scale-transition"
    max-width="290px"
    min-width="290px"
    :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"
  ]
}

2 Answers 2

1

The correction was actually simple, though very hard to find: https://github.com/vuejs/vue-cli/issues/5227

In order to solve the problem, it was necessary to modify .eslintrc.js, adding "parser": "babel-eslint" to the 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"
    }
};
Sign up to request clarification or add additional context in comments.

Comments

1

Using @typescript-eslint/parser to parserOptions.parser in eslintrc solves the problem.

https://github.com/vuejs/vue-cli/issues/5227#issuecomment-788639361

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.