Vue-cli: Can't import external TS file after upgrading to 4

Created on 6 Dec 2019  路  5Comments  路  Source: vuejs/vue-cli

Version

4.1.1

Reproduction link

https://github.com/lsotoangeldonis/vue-cli-4-ts-import-bug/tree/master

Environment info

System:
    OS: Linux 4.4 Ubuntu 18.04.1 LTS (Bionic Beaver)
    CPU: (8) x64 Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
  Binaries:
    Node: 10.13.0 - ~/n/bin/node
    Yarn: Not Found
    npm: 6.12.0 - ~/n/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0
    @vue/babel-plugin-transform-vue-jsx:  1.1.2
    @vue/babel-preset-app:  4.1.1
    @vue/babel-preset-jsx:  1.1.2
    @vue/babel-sugar-functional-vue:  1.1.2
    @vue/babel-sugar-inject-h:  1.1.2
    @vue/babel-sugar-v-model:  1.1.2
    @vue/babel-sugar-v-on:  1.1.2
    @vue/cli-overlay:  4.1.1
    @vue/cli-plugin-babel: ^4.1.1 => 4.1.1
    @vue/cli-plugin-eslint: ^4.1.1 => 4.1.1
    @vue/cli-plugin-pwa: ^4.1.1 => 4.1.1
    @vue/cli-plugin-router:  4.1.1
    @vue/cli-plugin-typescript: ^4.1.1 => 4.1.1
    @vue/cli-plugin-vuex:  4.1.1
    @vue/cli-service: ^4.1.1 => 4.1.1
    @vue/cli-shared-utils:  4.1.1 
    @vue/component-compiler-utils:  3.0.2
    @vue/eslint-config-airbnb: ^4.0.1 => 4.0.1
    @vue/eslint-config-typescript: ^4.0.0 => 4.0.0
    @vue/preload-webpack-plugin:  1.1.1
    @vue/web-component-wrapper:  1.2.0
    bootstrap-vue: ^2.1.0 => 2.1.0
    eslint-plugin-vue: ^5.2.3 => 5.2.3
    portal-vue:  2.1.6
    typescript: ^3.5.3 => 3.5.3
    vue: ^2.6.10 => 2.6.10
    vue-affix: ^0.5.2 => 0.5.2
    vue-analytics:  5.17.0
    vue-authenticate: ^1.4.1 => 1.4.1
    vue-axios: ^2.1.4 => 2.1.4
    vue-carousel: ^0.18.0 => 0.18.0
    vue-class-component: ^7.1.0 => 7.1.0
    vue-content-placeholders: ^0.2.1 => 0.2.1
    vue-eslint-parser:  undefined (5.0.0)
    vue-fb-customer-chat: ^0.1.4 => 0.1.4
    vue-functional-data-merge:  3.1.0
    vue-hot-reload-api:  2.3.4
    vue-js-popover: ^1.1.8 => 1.1.8
    vue-loader:  15.7.2
    vue-loading-overlay: ^3.2.0 => 3.2.0
    vue-masonry: ^0.11.7 => 0.11.7
    vue-moment: ^4.0.0 => 4.0.0
    vue-progressive-image: ^3.2.0 => 3.2.0
    vue-property-decorator: ^8.2.1 => 8.2.1
    vue-router: ^3.0.7 => 3.0.7
    vue-search-select: ^2.8.3 => 2.8.3
    vue-search-select-css: ^1.0.33 => 1.0.33
    vue-style-loader:  4.1.2
    vue-tel-input: ^2.4.1 => 2.4.1
    vue-template-compiler: ^2.5.21 => 2.6.10
    vue-template-es2015-compiler:  1.9.1
    vuex: ^3.1.1 => 3.1.1
    vuex-module-decorators: ^0.9.9 => 0.9.9
    vuex-persistedstate: ^2.5.4 => 2.5.4
  npmGlobalPackages:
    @vue/cli: 4.1.1

Steps to reproduce

npm install -g @vue/cli

vue upgrade

What is expected?

Normal import of .ts files inside .vue files using
//

All 5 comments

Ok, so i figured this out, If helps someone, be sure of always include the extension when importing subcomponents (nested components) from another component like such:

image

notice the ".vue" extension.
Was missing before and break everything, don't know why this was working before update tho.

It's because of this change
https://github.com/vuejs/vue-cli/pull/3909
We should have better documented it to mention that .ts(x) also take precedence over .vue.

I honestly think this is quite a bad change for TS users, especially since not evident from the migration docs. Our whole codebase is importing Vue files without extensions in the import path, and after the update it broke.

Maybe not many people noticed because TS doesn't seem too popular with Vue - and considering how difficult it is to make it work correctly, it's no wonder it's not popular!

If anyone reads this and wonders how to fix the issue without editing hundreds of files, this does the trick:

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.resolve.extensions
      .clear()
      .add('.vue')
      .add('.tsx')
      .add('.ts')
      .add('.mjs')
      .add('.js')
      .add('.jsx')
      .add('.json')
      .add('.wasm');
}

It basically regenerates the extension list, but it puts vue as first value.
Just calling .prepend('vue') will probably also solve it, but I'd rather not have dupe values in the resulting configuration.

The downside of this is, if in an update a new supported extension gets added, then this piece of code will remove it unless also updated.

@LolliDepp thank you for that! you saved us.
we were getting Failed to mount component: template or render function not defined after the upgrade to @vue/cli 4

we have a mix of Single File Components (SFC) (.vue) and multi-file components (template in .vue with script and style tags pointing to external .ts and .scss files (that's our way of getting better TypeScript support with better performance (Vetur becomes slower as the day progresses)

Closing the issue because related PR was merged

Was this page helpful?
0 / 5 - 0 ratings