HerringtonDarkholme / vue-ts-loader

Type-check your script in your vue-loader
MIT License
91 stars 9 forks source link

Importing relative files is buggy #1

Open digitalheir opened 7 years ago

digitalheir commented 7 years ago

Consider my .vue component

<!-- best-grill.vue -->
<template>
    <span>Asuka best girl, status: {{asukaBest}}</span>
</template>
<script>
import {Vue, Component} from 'av-ts'

@Component
export default class BestGrill extends Vue {
  asukaBest: boolean = true;
}</script>
<style>
</style>

It's nice. But I want TypeScript support in my IDE. Luckily, the .vue component spec says:

If you prefer splitting up your *.vue components into multiple files, you can use the src attribute to import an external file for a language block:

<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>

I try:

<!-- best-grill.vue -->
<template>
    <span>Asuka best girl, status: {{asukaBest}}</span>
</template>
<script src="./best-grill.ts"></script>
<style>
</style>
// best-grill.ts
import {Vue, Component} from 'av-ts'

@Component
export default class BestGrill extends Vue {
  asukaBest: boolean = true;
}

Sometimes this works, and sometimes it doesn't.

The situation where I found it does work:

  1. Set up webpack with hot reload
  2. Define component with inline <script>
  3. Webpack recompiles, OK
  4. Change <script> to refer to relative file, ie. <script src="./file.ts"/>
  5. Webpack recompiles, OK

It doesn't work on fresh compiles, however:

  1. Change <script> to refer relative file, ie. <script src="./file.ts"/>
  2. Webpack does not compile:

ERROR in ./src/app.ts (4,20): error TS2307: Cannot find module './best-grill.vue'.

digitalheir commented 7 years ago

PS workaround:

<script>
import component from './best-grill.ts';
export default component;
</script>

instead of

<script src="./best-grill.ts"></script>

pls respond

druppy commented 7 years ago

I am a bit confused about this my self, but have you tried to user ts-loader instead ?

I have this webpack setup :

loaders: {
    { test: /\.vue$/, loader: 'vue'},
    { test: /\.ts$/, loader: 'ts'} 
    ....

 ts: {
        appendTsSuffixTo: [/\.vue$/]
    }

Inside each vue file i now use <script lang='ts'>

It seems to me that the author of ts-loader and this plugin have been working together, but I have not seen any official announcement :-)

digitalheir commented 7 years ago

EDIT: ah, it's in the ts-loader documentation. I will switch to that lib, then.


Is that inside your Vue loader options or directly in the Webpack config? I don't really understand what's happening with appendTsSuffixTo: [/\.vue$/]?

I tried to use ts-loader as the custom loader (as specified here, ie, vue: {loaders: {js: 'ts-loader'}}. It surprisingly didn't work at all.

Maybe my config had an error if this setup works for you. I just figured there was something special about TypeScript in Vue files that led the author to create this project instead of re-using ts-loader.

HerringtonDarkholme commented 7 years ago

Sorry for the late response. @digitalheir I think the workaround is the only way to mixing external link and inline script.

Webpack loader is just a bunch of awful hacking overlaying above another bunch of awful hacking. The workaround is actually a good alternative.

thorning commented 7 years ago

I am not very familiar with webpack, but I have been using the following without problems:

module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: { js: 'ts-loader', },
          // esModule: true
          //if a custom element (anything but img) needs to resolve a path, add it to this
          transformToRequire : {
            'image-cropper' : 'src'
          }
        }
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  }

I used to use vue-ts-loader instead of ts-loader and that worked as well.

my .vue components typically look like this

<template lang="pug" src="./app.pug"/>

<script src="./app.ts"/>

<style lang="stylus" src="./app.styl" scoped/>