Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS Single File Component with typescript: Unable to find module stuff.vue

I have a simple project structure:

/src/app2/main.ts /src/app2/components/lib.ts /src/app2/components/stuff.vue

With webpack, vue-loader, and ts-loader.

main.ts has:

import Vue = require('vue');
import  Component from './components/lib'

new Vue({
  el: '#app2'

});

When trying to build this with 1 webpack entry for /src/app2/main.ts, the error generated is:

ERROR in C:\temp\vuetest2\proj\src\app2\components\lib.ts
(2,25): error TS2307: Cannot find module './stuff.vue'.

ERROR in ./src/app2/main.ts
Module not found: Error: Can't resolve './components/lib' in 'C:\temp\vuetest2\proj\src\app2'
 @ ./src/app2/main.ts 3:12-39

If I change the entry point to src/app2/components/lib.ts, it will build. I'm at a loss as to why main.ts won't build.

Contents of lib.ts:

import Vue = require('vue');
import Stuff  = require('./stuff.vue');


let o = {
   Stuff
}

let componentLibrary = {
  components: o,
  registerExternal: function(v:any) {
    for(var k in o) {
        v.component(o[k].name, o[k]);
    }
  },
  registerInternal: function() {
    for(var k in o) {
        Vue.component(o[k].name, o[k]);
    }
  }
}

export default componentLibrary;

Stuff.vue is just a simple single file vue component.

like image 417
lucuma Avatar asked Feb 24 '17 21:02

lucuma


2 Answers

According to : https://github.com/vuejs/vue-class-component/blob/master/example/webpack.config.js

Try adding appendTsSuffixTo ts-loader option in your webpack.config.js

webpack2

{
    test: /\.ts$/,
    exclude: /node_modules|vue\/src/,
    use: [{
            loader: 'ts-loader',
            options: {
                appendTsSuffixTo: [/\.vue$/]
            }
        }]
},
like image 50
Riku Inoue Avatar answered Nov 04 '22 12:11

Riku Inoue


You can reference on this PR on github. Actually that's not a bug, just a usage problem.

I assume that you want to write SFC with <script lang="ts">, <script lang="tsx">, *.ts for utils functions & classes, and *.tsx for functional pure component.

ts-loader accpets only *.ts or *.tsx files to compile (otherwise it would cause an error that file not found). So ts-loader has two options: appendTsSuffixTo and appendTsxSuffixTo. These two options accept an array of regexp to match which files you want to compile. (Here we give ts-loader the *.vue files that already processed by vue-loader to compile).

I assume that you use *.ts.vue for <script lang="ts"> SFC vue file while *.tsx.vue for <script lang="tsx"> SFC vue file. ts-loader should be configured as below:

  {
    test: /\.tsx?$/,
    use: [
      {
        loader: 'babel-loader'
      },
      {
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.ts\.vue$/],
          appendTsxSuffixTo: [/\.tsx\.vue$/]
        }
      }
    ],
    exclude: /node_modules/
  },

This means, normal *.ts and *.tsx files pass to ts-loader will transpiled and then be sent to babel-loader for further compile. And other files end with .ts.vue will be suffixed .ts as *.ts.vue.ts, and end with .tsx.vue to be *.tsx.vue.tsx. These files all passed from vue-loader. Remember ts-loader only accept .ts and .tsx files.

But vue-loader is not smart enough, <script lang="xxx"> will trigger vue-loader append xxx-loader for further compile, and <script lang="tsx"> will make vue-loader append tsx-loader, which is not exist in the world.

Fortunately we can configure vue-loader's options:

  const loaders = {}
  loaders.tsx = ['babel-loader', 'ts-loader']
  loaders.ts = loaders.tsx
  {
    test: /\.vue$/,
    loader: 'vue-loader',
    options: { loaders }
  },

After that webpack config is completed. For tsx support, you should install some JSX types and write a related .d.ts file

You can check this repo on github for more details.

Good luck!

like image 40
Plasmatium Avatar answered Nov 04 '22 14:11

Plasmatium