Как динамически загружать схему json в машинописный текст с помощью веб-пакета

У меня есть схема json, описывающая объект Person. Я хотел бы иметь возможность загружать эту схему в файл машинописного текста напрямую следующим образом:

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

Для этого я создал загрузчик, который преобразует файл json в объявление интерфейса typescript (используя json-schema-to-typescript), а затем передать результат ts-loader.

Мой веб-пакет настроен следующим образом:

webpack.config.js (выдержка)

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

Следуя этому вопросу, я настроил объявление, чтобы файл json считался строкой :

declaration.d.ts:

declare module '*.schema.json' {
  const schema: string;
  export default schema;
}

Мой загрузчик меняет имя файла, который он обрабатывает на лету, поэтому 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;
}

Однако, когда я создаю свой проект, Person не распознается как объект, и компиляция завершается ошибкой:

index.js

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

const person: Person = {
  lastName: 'Doe',
  firstName: 'John',
};
console.log(person);

компиляция не работает с:

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

Хотя я определяю экспорт файла .schema.json как строку в своем объявлении, мой загрузчик динамически меняет имя файла (this.resourcePath) на файл ts, поэтому ts-загрузчик должен видеть его как стандартный файл ts и экспортировать объект Person. .

Что я делаю не так?


person Luke Skywalker    schedule 16.12.2017    source источник
comment
может помочь, stackoverflow.com/q/31173738/794088   -  person petey    schedule 20.12.2017
comment
Поскольку Person не является экспортом по умолчанию, попробуйте: import { Person } from './schema/person.schema.json';   -  person Daniel    schedule 20.12.2017
comment
@Даниэль, на самом деле ему нужно export default interface Person   -  person Aluan Haddad    schedule 27.12.2017


Ответы (1)


Используйте appendTsSuffixTo

Я думаю, что ваша установка будет работать, если вы используете параметр ts-loader appendTsSuffixTo, а не чем самостоятельное изменение имени файла в пользовательском загрузчике. Как отмечено в комментариях, вам также может потребоваться настроить способ импорта или экспорта Person.

Используя appendTsSuffixTo, вы удалите this.resourcePath = this.resourcePath + '.ts'; (или аналогичный код) из своего загрузчика. Затем настройте конфигурацию вашего веб-пакета примерно так:

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

Вы также можете избавиться от typings.d.ts, используя этот подход.

Но почему?

Мне было не сразу понятно, почему ваш подход не сработает; интуитивно казалось, что это должно быть эквивалентно использованию appendTsSuffixTo. Поэтому я немного отладил ts-loader, чтобы увидеть, что происходит.

Если я сам изменю resourcePath, в ts-loader/dist/index.js все будет выглядеть нормально, но в ts-loader/dist/servicesHost.js все пойдет не так.

В частности, я вижу, что resolveModuleName() возвращает undefined для моего файла example.schema.json, когда я просто меняю this.resourcePath в своем загрузчике. Однако я вижу, что это правильно разрешается при использовании appendTsSuffixTo.

Я не являюсь участником (и не экспертом) ts-loader, но я считаю, что при изменении this.resourcePath в загрузчике ваш файл .schema.json действительно будет компилироваться, но затем не будет разрешен, где бы он ни был импортирован.

Другие соображения

Запустить сборку веб-пакета — это одно; предоставление приятного опыта разработчика в среде IDE — это другое. См. этот ответ на тесно связанный вопрос, чтобы узнать больше об этом, и этот репозиторий Github для рабочего примера кода, который может оказаться полезным.

person Mike Patrick    schedule 23.12.2017