如何使用webpack动态加载json模式到typescript

Luk*_*ker 5 loader jsonschema typescript webpack

我有一个描述对象Person的json模式.我希望能够以这种方式直接将该模式加载到typescript文件中:

import Person from './schema/person.schema.json';
Run Code Online (Sandbox Code Playgroud)

为此,我创建了一个加载器,它将json文件转换为typescript接口声明(使用json-schema-to-typescript),然后将结果传递给ts-loader.

我的webpack以这种方式配置:

webpack.config.js(摘录)

module: {
  rules: [
    {
      test: /\.ts$/,
      loader: 'ts-loader',
    },
    {
      test: /\.schema\.json$/,
      loader: 'ts-loader!jsonschema-loader',
      exclude: /(node_modules)/,
    },
  ]
},
Run Code Online (Sandbox Code Playgroud)

在这个问题之后我配置了一个声明,以便json文件被认为是一个字符串:

declaration.d.ts:

declare module '*.schema.json' {
  const schema: string;
  export default schema;
}
Run Code Online (Sandbox Code Playgroud)

我的加载器改变了它动态处理的文件名,所以ts-loader认为它加载的是person.schema.ts.而且,我检查了我的装载机的结果是否正确.这里是:

/**
 * This file was automatically generated by json-schema-to-typescript.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
 * and run json-schema-to-typescript to regenerate this file.
 */

export interface Person {
  firstName: string;
  lastName: string;
  /**
   * Age in years
   */
  age?: number;
  [k: string]: any;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我构建项目时,Person不会被识别为对象,并且编译失败:

index.js

import Person from './schema/person.schema.json';

const person: Person = {
  lastName: 'Doe',
  firstName: 'John',
};
console.log(person);
Run Code Online (Sandbox Code Playgroud)

编译失败:

ERROR in ./src/index.ts
(3,15): error TS2304: Cannot find name 'Person'.
Run Code Online (Sandbox Code Playgroud)

虽然我在声明中将.schema.json文件的导出定义为字符串,但我的加载器会动态地将文件名(this.resourcePath)更改为ts文件,因此ts-loader应将其视为标准ts文件并导出Person对象.

我究竟做错了什么?

Mik*_*ick 3

使用appendTsSuffixTo

ts-loader我认为如果您使用的appendTsSuffixTo 选项,而不是在自定义加载程序中自己更改文件名,您的设置将会起作用。正如评论中所述,您可能还需要调整Person导入或导出的方式。

使用appendTsSuffixTo,您可以this.resourcePath = this.resourcePath + '.ts';从加载器中删除(或类似的代码)。然后将你的 webpack 配置调整为如下所示:

  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: {
            appendTsSuffixTo: [/\.schema.json$/]
          }
      },
      {
        test: /\.schema\.json$/,
        loader: 'ts-loader!my-own-loader',
        exclude: /(node_modules)/,
      },
    ]
  },
Run Code Online (Sandbox Code Playgroud)

您也可以摆脱typings.d.ts使用这种方法。

但为什么?

我并不清楚为什么你的方法不起作用;直觉上它似乎应该等同于使用appendTsSuffixTo. 所以我调试了一下,ts-loader看看发生了什么。

如果我修改我resourcePath自己,在 中看起来大部分情况都很好ts-loader/dist/index.js,但在 中事情开始出错ts-loader/dist/servicesHost.js

具体来说,当我刚刚更改加载程序时,我会看到文件的resolveModuleName()返回。但是,我发现使用时它可以正确解析。undefinedexample.schema.jsonthis.resourcePathappendTsSuffixTo

我不是 的贡献者(或专家)ts-loader,但我对此的看法是,在this.resourcePath加载器中修改时,您的.schema.json文件确实会编译,但无论在何处导入,都无法解析。

其他考虑因素

让你的 webpack 构建运行是一回事;在 IDE 中提供良好的开发人员体验是另一回事。有关此问题的更多想法,请参阅此密切相关问题的答案,以及此 Github 存储库中的工作示例代码,可能会有所帮助。