首页 > 解决方案 > Vue + webpack + TS:生成声明时找不到.vue.d.ts

问题描述

我正在开发一个用 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,
    })
  ],
}

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

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

感谢您的帮助。

标签: typescriptwebpackvue.js

解决方案


好的,我终于设法得到它。

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

就我而言,我没有使用“真正的”vue 单文件,因为打字稿部分位于 .vue 文件之外的另一个文件中。然后用 引用<script lang="ts" src="./MyComponent.ts"></script>

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

我所要做的就是使用普通的单文件组件。但是由于我需要让我的 ts 远离我的 .vue(因为 typescript 中的一个已知错误),我必须显式导入我的 ts 模块而不是引用我的 ts 文件,如下所示:

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

我希望我说清楚了。


推荐阅读