Vue + webpack + TS: 生成声明时找不到.vue.d.ts

Vue + webpack + TS: cannot find .vue.d.ts when generating declaration

我正在开发一个用 Typescript 编写并使用 VueJS 的库。我还在构建部分使用 webpack。

我在生成 TypeScript 声明文件 (.d.ts) 时遇到问题。

首先,让我们谈谈我的源代码。我有 Typescript 文件(显然)和 Vue 组件。每个 Vue 组件由 2 个文件组成:一个 .vue 文件和一个 .ts 文件。

举个例子

我有以下代码:

// index.ts
export { default } from './components/Foobar.vue';

// components/Foobar.vue
<template><p>Hello!</p></template>
<script lang="ts" src="./Foobar.ts"></script>

// components/Foobar.ts
@Component
export default class Foobar extends Vue {

}

构建的输出将是这样的:

lib/
dist/
    index.js // my lib
    index.d.ts // aggregated .d.ts with dts-bundle
    lib/ // all my .d.ts are here !
        index.d.ts
        components/
            Foobar.d.ts

问题是 dts-bundle 无法输出 dist/index.d.ts 因为生成的声明 (dist/lib/**/*.d.ts) 无效。它们由 ts-loader 生成。

如果我们查看 dist/lib/index.d.ts,我们会发现以下内容:

// dist/lib/index.d.ts
export { default } from './components/Foobar.vue'

问题当然是:/dist/lib/components/Foobar.vue 存在。此组件的定义是 Foobar.d.ts,而不是 Foobar.vue.d.ts

将每个声明捆绑在一起时,dts-bundle 失败,因为它找不到 /dist/lib/components/Foobar.vue.d.ts.

我该如何解决?

我只需要更换这个

// dist/lib/index.d.ts
export { default } from './components/Foobar.vue'

由此

// dist/lib/index.d.ts
export { default } from './components/Foobar'

我认为这是一个非常常见的错误,我只是在我的 webpack 配置上做错了什么。这是我的 webpack 配置:

{
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',

  entry: 'path/to/index.ts',

  output: { /* ... */}

  resolve: {
    symlinks: true,
    extensions: [
      '.ts',
      '.vue',
      '.js',
      '.json',
    ],
    modules: [
      'node_modules',
    ]
  },

  module: {
    noParse: /^(vue|vuex)$/,
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader',
            options: {
              cacheDirectory: // cache path
            }
          },
          {
            loader: 'vue-loader',
            options: {
              cacheDirectory: // cache path
            }
          },
        ]
      },
      {
        test: /\.ts$/,
        use: [
          {
            loader: 'cache-loader',
            options: {
              cacheDirectory: // cache path
            }
          },
          {
            loader: 'babel-loader'
          },
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [
                /\.vue$/
              ],
            }
          }
        ]
      }
      // ...
  }

  plugins: [
    new ProgressPlugin(),
    new FriendlyErrorsWebpackPlugin({
      clearConsole: false
    }),
    new VueLoaderPlugin(),
    new ForkTsCheckerWebpackPlugin({
      vue: true,
      tslint: 'custom path to my file',
      formatter: 'codeframe',
    }),
    new CopyWebpackPlugin(
      [
        {
          from: 'assets',
          to: 'dist',
          ignore: [
            '.gitkeep',
            '.DS_Store'
          ]
        }
      ]
    ),      
    new DtsBundlePlugin({
      name: `MyModule`,
      main: path.join(LIB_PATH, entry.output.path, 'lib', 'index.d.ts'),
      out: path.join(LIB_PATH, entry.output.path, 'index.d.ts'),
      verbose,
    })
  ],
}

我正在做一个最小复制回购,我会及时编辑这个问题。

同时,如果我需要提供具体信息,请告诉我。

感谢您的帮助。

好的,我终于搞定了。

vue-loader 用于将 vue monofiles 拆分为不同的 webpack 资产。目标是让 webpack 在 vue monofile 的每个部分(脚本、样式和模板)执行不同的加载器。

在我的例子中,我没有使用“real”vue monofile,因为 typescript 部分在另一个文件中,而不是 .vue 文件。然后用 <script lang="ts" src="./MyComponent.ts"></script>.

引用

由于 ts-loader 和 vue-loader 的工作方式,这样做会导致声明生成失败。

我所要做的就是使用普通的单文件组件。但是因为我需要让我的 ts 远离我的 .vue(因为打字稿中的一个已知错误),我不得不显式导入我的 ts 模块而不是引用我的 ts 文件,就像这样:

<script lang="ts">
    export { default } from './MyComponent.ts';
</script>

希望我说清楚了。