Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cant work with typescript #109

Closed
tcstory opened this issue Dec 22, 2015 · 37 comments
Closed

cant work with typescript #109

tcstory opened this issue Dec 22, 2015 · 37 comments

Comments

@tcstory
Copy link

tcstory commented Dec 22, 2015

structure of the project

image

webpack.config.js

module.exports = {
    entry: './src/js/app.js',
    output: {
        path: 'dist/',
        filename: './js/bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader'
            },
            {
                test: /\.vue$/,
                loader: 'vue'
            }
        ]
    }
}

app.ts

declare var require;
declare var Vue;

new Vue({
    el: 'body',
    components: {
        'nani': require('../components/nani.vue')
    }
})

nani.vue

<template><p>纳尼?你再说一次.</p></template>

<script lang="ts">
    export = {
        methods: {
            sayHello: function () {
                alert('hello')
            }
    }
</script>

each time I run webpack, it always report this error,

$ webpack                                                                                                                     ‹ruby-2.1.4›
ts-loader: Using [email protected]
Hash: 54f28de48a69455dfb02
Version: webpack 1.12.9
Time: 1239ms
         Asset     Size  Chunks             Chunk Names
./js/bundle.js  2.74 kB       0  [emitted]  main
   [0] ./src/js/app.js 178 bytes {0} [built]
    + 4 hidden modules

ERROR in ./~/ts-loader!./~/vue-loader/lib/selector.js?type=script&index=0!./src/components/nani.vue
Module build failed: Error: Could not find file: '/Users/tcstory/WebstormProjects/test/src/components/nani.vue'.
    at getValidSourceFile (/Users/tcstory/WebstormProjects/test/node_modules/typescript/lib/typescript.js:43586:23)
    at Object.getEmitOutput (/Users/tcstory/WebstormProjects/test/node_modules/typescript/lib/typescript.js:46680:30)
    at Object.loader (/Users/tcstory/WebstormProjects/test/node_modules/ts-loader/index.js:410:34)
 @ ./src/components/nani.vue 2:17-111

how to solve this problem?

@tcstory
Copy link
Author

tcstory commented Dec 22, 2015

visit the link to see the project
https://github.com/tcstory/vue-loader-test

@yyx990803
Copy link
Member

Interestingly this is because ts-loader is a big hack and is not a in-memory transform (i.e. it relies on actual files on disk), so it can't work with *.vue files... I don't think there's an easy way to make this work, unless someone who knows more about TypeScript can figure out why ts-loader is implemented that way.

@yyx990803
Copy link
Member

On another look, you may need to set the transpileOnly flag to true: https://github.com/TypeStrong/ts-loader#transpileonly-boolean-defaultfalse

@tcstory
Copy link
Author

tcstory commented Dec 27, 2015

:) thanks

@druppy
Copy link

druppy commented Feb 17, 2016

I too, have tried to setup a TS environment using vue components (I love the idea that it is based on, its small site, and the goal to keep it that way), and while using vue in a plain ts file setup is not a big problem (you can even user nice decorators) , the vue files is a problem as stated above.

Further more, the editor support for the vue files is a problem too, as some kind of .d.ts file are missing too.

It would be nice if the vue-loader could optionally write a ts (or a d.ts) file in the same path as the vue component. This would fix the above problem, but more importantly it would make better IDE support too, as the tsc now knows the components types too.

@QuentinFchx
Copy link

Do you think this problem could be solved by the shorthand ambient module declarations proposal ?

@DanielRosenwasser
Copy link

Hey @yyx990803 can you elaborate a little on the problems? I'm not that familiar with Webpack's internals, but it looks like TypeScript is being fed the .vue file itself. I don't necessarily know why that would occur, since we don't try to resolve plain calls to require AFAIK.

@davidmoshal
Copy link

davidmoshal commented Aug 2, 2016

just to clarify, will ts hot-reload with non-*.vue files?
i.e: with vue-typescript ?
in this case, vue-loader wouldn't be used at all.

I have managed to get vuex to hot-reload with typescript, but the UI does'nt reload

thanks

@erik-sytnyk
Copy link

erik-sytnyk commented Aug 5, 2016

You can make vue-loader work with TS, if you put ts code in separate file.

myComponent.vue:

<template>
    ...
</template>
<style>
    ...
</style>
<script lang="ts" src="./myComponent.vue.ts"></script>

myComponent.vue.ts:

TS code goes here

You can use both 'ts' and 'awesome-typescript' loaders, just override ts lang option in vue-loader settings.

Sample usage here:

https://github.com/yegor-sytnyk/contoso-express/ branch alt/vue

@HerringtonDarkholme
Copy link
Member

HerringtonDarkholme commented Aug 17, 2016

@DanielRosenwasser It seems vue-loader will transform .vue file into JavaScript, where content <script> tag will be transformed into seome require call like
require("!!ts!./../../node_modules/vue-loader/lib/selector.js?type=script&index=0!./nani.vue")

Mind the selector.js in the middle. It comes from vue-loader and extract content in the script tag of a vue file. Then selector.js feed the extracted content to callback, which calls ts-loader defined here.

Here comes the problem. ts-loader do compile file by using filePath, not content. vue-loader feeds to ts-loader file path like *.vue rather than *.ts. TSC rejects vue file and ignores extracted content.

@DanielRosenwasser
Copy link

From what I understand of Webpack, sounds like if vue-loader was able to know to create a .ts intermediate file, things would "just work", but I could be wrong.

@HerringtonDarkholme
Copy link
Member

I found as long as the filename ends with .ts, typescript will compile. ts-loader has already used a languageService so no intermediate file is needed. I could be wrong because I haven't tested multiple files but from reading the source I guess it would work.

@HerringtonDarkholme
Copy link
Member

If anyone is still interested in using TypeScript in *.vue, vue-ts-loader is a choice to have a look.

@DanielRosenwasser
Copy link

@HerringtonDarkholme what changes are there between vue-ts-loader and ts-loader? It looks like there are only baseline changes.

@HerringtonDarkholme
Copy link
Member

The key change is just a suffix hack. HerringtonDarkholme/vue-ts-loader@d581d46

And all *.vue files are served to tsc by getScriptSnapshot call rather than readFile on disk. So when a vue file is feed to tsc, it has already been processed by vue-loader.

This is the easiest and fastest way I can come up.

ts-loader needs much maintenance. most test baselines are outdated

@DanielRosenwasser
Copy link

DanielRosenwasser commented Aug 28, 2016

I see - would it not be better to have vue-loader generate a different extension for output files when the language="typescript"?

@DanielRosenwasser
Copy link

Oh - I think I see. Loaders don't have control over "generating" files. That file exists on its own and no new distinct files are created (even virtually). Is that correct?

@HerringtonDarkholme
Copy link
Member

Exactly.

I think a good approach is to support non-ts file by loading extension in tsc. And that should be done by vue-ts-loader so that vue-loader has a uniform interface.

@DanielRosenwasser
Copy link

So ts-loader should just accept arbitrary file extensions? I think that'd be the right call.

Maybe @mhegazy and @jbrantly can weigh in here on any risks of (or previous issues with) that. Also CCing @TheLarkInn.

@yyx990803
Copy link
Member

Closing, but here's a guide if anyone is trying to get latest vue-loader working with TS2: http://herringtondarkholme.github.io/2016/10/03/vue2-ts2/

@doun
Copy link

doun commented Mar 7, 2017

add ts-loader with options: AppendTsSuffixTo works. @DanielRosenwasser

@riku179
Copy link

riku179 commented Mar 11, 2017

@doun How did you do that? Please tell me the details.

@riku179
Copy link

riku179 commented Mar 11, 2017

@doun It's my fault. I gone well when I remove { modules: false } options in babel.
Here is my webpack2 config.

module: {
        rules: [
            {
                test: /\.js/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
                    // presets: ['es2015', { modules: false }] <- fail
                    presets: ['es2015']
                }
            },
            {
                test: /\.ts$/,
                exclude: /node_modules|vue\/src/,
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            appendTsSuffixTo: [/\.vue$/]
                        }
                    },
                ]
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    esModule: true,
                }
            },
        ]
    }

@DmacMcgreg
Copy link

Has anyone gotten vue2 + typescript2 working with hot reloading using .vue component files?

@druppy
Copy link

druppy commented Apr 3, 2017

Yeps, it works nicely. I think the trick it that webpack uses websockets, and there are a few scripts out there that mix this in a not always functional way.

@Coridyn
Copy link

Coridyn commented Apr 17, 2017

Has anyone gotten vue2 + typescript2 working with hot reloading using .vue component files?

@druppy Yes, I just got it working when I was converting a project over from JavaScript to TypeScript.

See my comment on how I fixed this Error: Could not find file error with ts-loader and appendTsSuffixTo option.

@pixel1234561
Copy link

pixel1234561 commented Apr 29, 2017

Still won't work for me. Using ts-loader v2.0.3.
references.d.ts:

declare module "*.vue" {
  import Vue from 'vue'
  export default typeof Vue
}

tsconfig.json:

{
  "compilerOptions": {
    "lib": [
      "dom",
      "es5",
      "es2015",
      "es2015.promise"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "target": "es5",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true
  },
  "exclude": [
    "node_modules"
  ]
}

webpack.conf.js:

...
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          esModule: true
        }
      },
...

Getting this output:

ERROR in ./~/ts-loader!./~/vue-loader/lib/selector.js?type=script&index=0!./src/app.vue
Module build failed: Error: Could not find file: '/home/andrew/Documents/projects/mine-vue/src/app.vue'.
    at getValidSourceFile (/home/andrew/Documents/projects/mine-vue/node_modules/typescript/lib/typescript.js:85887:23)
    at Object.getEmitOutput (/home/andrew/Documents/projects/mine-vue/node_modules/typescript/lib/typescript.js:86252:30)
    at getEmit (/home/andrew/Documents/projects/mine-vue/node_modules/ts-loader/dist/index.js:99:43)
    at Object.loader (/home/andrew/Documents/projects/mine-vue/node_modules/ts-loader/dist/index.js:27:11)
 @ ./src/app.vue 7:2-94
 @ ./src/main.ts

But if i just replace ts-loader with vue-ts-loader and change script attr to lang="vue-ts" in .vue it works fine:

      {
        test: /\.tsx?$/,
        loader: 'vue-ts-loader'
      },

Any ideas?

@DanielRosenwasser
Copy link

Hey all, here's a sample repo of TypeScript working with .vue files. It's still a bit of a work in progress, but it'll get the job done for you. https://github.com/DanielRosenwasser/typescript-vue-todomvc

It currently uses some augmented .d.ts files that I've been working on, and right now type checking requires that you write

export default Vue.extend({
  // ... component options here ...
});

instead of just

export default {
  // ... component options here ...
};

You'll also always need an export default from a .vue file so that TypeScript knows that it's a module.

If you use it, try it out with the Vetur VS Code plugin, which can actually give you some of the same experience TypeScript does in .ts files.


vue-loader specific things:

  • Of note: you'll need to write <script lang="ts"> for your script tags

  • You'll need to use the appendTsSuffixTo option

  • To import from .vue files, you'll need a declare module "*.vue"-type thing. Specifically this:

    declare module '*.vue' {
      import Vue from 'vue';
      declare const component: typeof Vue;
      export default component;
    }

    which I realize could probably have just been written as

    declare module '*.vue' {
      import Vue from 'vue';
      export default Vue;
    }

@aromancev maybe your code doesn't work because you're default-exporting the type of Vue, not Vue itself.

@pixel1234561
Copy link

@DanielRosenwasser yes, that was the case. Thanks!

@StevenDoesStuffs
Copy link

StevenDoesStuffs commented May 7, 2017

Any idea how to use babel loader in conjunction with ts-loader, because this wont work:

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

...

{ // vue
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
        loaders: {
            scss: ExtractTextPlugin.extract(cssExtract(false))
        },
        options: {
            esModule: true
        }
    }
}

@blocka
Copy link

blocka commented May 11, 2017

@StevenTheEVILZ why would you need babel if you have TS?

@mythz
Copy link

mythz commented May 12, 2017

@DanielRosenwasser I've noticed your example repo is using custom vue / vue-router dependencies, does it still require them? if so do you know when they'll be able to work with the official vue/vue-router packages?

@StevenDoesStuffs
Copy link

@blocka because babel allow you to use es6 api features (non-syntax features) such as iterators, generators, async functions, promises, etc. It automatically polyfills it in for you. That's why lots of people use babel with typescript.

@blocka
Copy link

blocka commented May 14, 2017

@StevenTheEVILZ babel doesn't automatically pollyfill any run-time behavior for you.

@StevenDoesStuffs
Copy link

Something about babel-loader polyfills because I can use iterator. But now I realize that the above actually works, and it's not babel causing the problem, it's typescript. Sorry about that.

@StevenDoesStuffs
Copy link

Does this compile the ts in components twice?

{
    test: /\.vue$/,
    loader: 'vue-loader', // doesn't want to be use for whatever reason
    options: {
        loaders: {
            scss: cssExtract(false),
            ts:  [{
                loader: 'babel-loader',
            }, {
                loader: 'ts-loader',
                options: {
                    appendTsSuffixTo: [/\.vue$/]
                }
            }]
        },
        options: {
            esModule: true
        }
    }
},
{ // ts
    test: /\.tsx?$/,
    use: [{
        loader: 'babel-loader',
    }, {
        loader: 'ts-loader',
        options: {
            appendTsSuffixTo: [/\.vue$/]
        }
    }],
    exclude: /node_modules/, // not sure if needed
}, 

@ericop
Copy link

ericop commented Jun 1, 2017

I'm with @mythz in wondering if there is a way to get this working on the vue master branch. @DmacMcgreg asks a good question, and I'm wondering if there is an answer to it using the existing "production APIs" . @DanielRosenwasser 's todoMCV is cool because it's a working example. I just wish Vue truly had first class support for TypeScript in it's best features, like https://vuejs.org/v2/guide/single-file-components.html .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests