Webpack 和 TypeScript 无法解析 Vue 的声明文件

Posted

技术标签:

【中文标题】Webpack 和 TypeScript 无法解析 Vue 的声明文件【英文标题】:Webpack and TypeScript can't resolve declaration file for Vue 【发布时间】:2018-05-25 00:56:22 【问题描述】:

我有一个项目,我为一些前端的东西引入了 Vue,但我仍然有很多 TypeScript 和 jQuery 的遗留代码。所有遗留代码都在“ts”文件夹中,新的 Vue 单文件组件和一些引导 ts 文件在“src”中。它在 VSCode 中看起来一切正常,甚至在命令行上直接调用 'tsc' 也可以正常工作,但是一旦我从 'ts' 文件夹中导入声明/定义(模块),WebPack 就会不断抱怨。

项目文件夹结构

+ root
  + php/css/etc
  + ts
    + models
      - LegacyTypeScriptModules.ts
      - PlanDate.ts
    + js-defs
      - tools.d.ts
    - tsconfig.json (to be able to build only legacy code)
  + src
    + components
      - RecentChanged.vue
    + pages
      - Welcome.vue
    - App.vue
    - main.ts
    - tsconfig.json (main configuration)
  - package.json
  - tsconfig.json (only fixing experimentalDecorators issue in VSCode)
  - tslint.json
  - webpack.config.js

错误信息 npm build

./ts/models/PlanDate.ts 中的错误 找不到模块:错误:无法解析“/Users/username/dev/project-root/ts/models”中的“js-defs/tools” @ ./ts/models/PlanDate.ts 1:0-45 @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/RecentChanged.vue @ ./src/components/RecentChanged.vue @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/pages/Welcome.vue @ ./src/pages/Welcome.vue @ ./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.ts

“src”文件夹中的主 tsconfig.json


    "compilerOptions": 
        "target": "es5",
        "strict": true,
        "module": "es2015",
        "moduleResolution": "node",
        "lib": [
            "dom",
            "es2015",
            "es2015.iterable"
        ],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "baseUrl": ".",
        "paths": 
            "*": [
                "*",
                "./*",
                "../ts/*"
            ]
        
      ,
      "include": [
          "**/*",
          "../ts/**/*"
      ]

webpack.config.js

module.exports = 
  entry: './src/main.ts',
  output: 
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  ,
  module: 
    rules: [
      
        test: /\.ts$/,
        loader: "ts-loader",
        exclude: /node_modules|vue\/src/,
        options: 
          appendTsSuffixTo: [/\.vue$/]
        
      ,
...
  resolve: 
    alias: 
      'vue$': 'vue/dist/vue.esm.js',
    ,
    extensions: ['.js', '.vue', '.json', '.ts'],
    modules: [
      'node_modules', 
      path.resolve(__dirname, 'src'),
      path.resolve(__dirname, 'ts')
    ],
...

导入旧版 ts 模块的第一个 Vue 文件

import Vue from 'vue'
import  ChangedItem  from '../../ts/models/ChangedItem'
import  PlanDate  from "../../ts/models/PlanDate"
import  Customer  from "../../ts/models/Customer"
import  Component, Prop  from 'vue-property-decorator'

@Component
export default class RecentChanged extends Vue 
...

给出错误的类/模块

import  IDate, IDateSink, IDateSource from "./interfaces/IDate";
import  addDays, pad  from "js-defs/tools";

export class PlanDate implements IDate 
...

找不到的模块

import  IMainOptions  from "models/interfaces/IOptions";

export declare function addDays(d: IDate, n: number, keepTime?: boolean): IDate;
export declare function pad(inputString: any, width: number, paddingCharacter?: string): string;

请注意,第一个问题已经是我似乎无法让绝对路径在 Vue SFC 中工作,所以我已经不得不妥协到一个丑陋的相对路径。 (也许已经是问题的第一个迹象?)Vue 中的这个绝对路径问题在 VSCode、tsk 和 WebPack 上是一致的,但我对此有单独的问题。 我也遇到了遗留打字稿类中的 some 绝对路径的问题,但我可以想象这是因为它似乎只能从 'ts' 文件夹或更深的文件夹中工作,但我认为这与 WebPack 无关似乎没有抱怨导入“IDate”。

由于裸打字稿编译器在查找声明模块时没有问题,而且 VSCode 语言服务器也没有抱怨,我认为这是 WebPack 的配置文件中的问题,但也许我缺少/忽略了一些东西。

我尝试了声明模块的绝对路径和 相对 路径,但都失败了。还尝试了其他不依赖于其他遗留模块的遗留类,它们确实似乎可以工作。所以看起来模块解析在声明文件上失败了。 在 webpack.config.js 中,我已经尝试过 resolve.aliasresolve.modules 之类的东西,但它们不起作用,或者我不知道如何定义路径。

更新

在下面给出的第一个 cmets 和答案之后,我很确定这与我自己的声明文件的定义方式、我应该如何导入它或我如何配置 WebPack 以正确找到它有关。有人能告诉我如何在 Vue+WebPack+TypeScript 中使用声明文件而不会出现“找不到模块”或“未发出输出”错误吗?

【问题讨论】:

您确定可以将定义文件作为模块导入吗? 我尝试了更多仅依赖于其他类的类,但这似乎确实有效,因此它可能与定义文件有关。不接受扩展名或语法等内容。 这有什么好运气吗?在这里使用定义文件,遇到了同样的错误。 很遗憾没有,所以我将所有内容都转换为 TS,这样就不需要定义文件了。 【参考方案1】:

可能是因为文件的扩展名为 d.ts,而您的配置设置为在导入时仅查找 .ts 扩展?

【讨论】:

如果我像这样将它添加到配置中:resolve: extensions: ['.js', '.vue', '.json', '.ts', '.d.ts' ] .我收到另一个错误:./ts/js-defs/tools.d.ts 中的错误模块构建失败:错误:Typescript 没有为 /Users/username/dev/project-root/ts/js-defs/tools 发出输出.d.ts。在successLoader (/Users/username/dev/project-root/node_modules/ts-loader/dist/index.js:47:15) 在 Object.loader (/Users/username/dev/project-root/node_modules/ts- loader/dist/index.js:29:12)。 WebPack 是否需要有这些功能的实际 js 文件? 那是我的假设,定义文件肯定只用于类型检查? 那么我应该如何处理我自己的js代码的定义文件呢?当我确保这些函数是由浏览器中的另一个 js 文件定义时,这对 tsc 总是很有效。 那么addDayspad 函数实际定义在哪里? 是的。我还让问题更具体到声明文件,因为其他模块似乎解决得很好。关于如何在 Vue+WebPack+TypeScript 中使用声明文件有什么想法吗?

以上是关于Webpack 和 TypeScript 无法解析 Vue 的声明文件的主要内容,如果未能解决你的问题,请参考以下文章

Electron 和 TypeScript:“fs”无法解析

TypeScript+Webpack 解析符号链接文件夹中的依赖项

无法解析 Typescript 模块

Webpack 生产构建失败:“无法解析 'aws-sdk'”

使用 Webpack 2 和 awesome-typescript-loader 的 baseUrl 和路径解析

无法解析 webpack 中的“tslint-loader”