Как загрузить текстовый файл с помощью Webpack и React?

Для настройки экземпляра редактора Monaco я хочу добавить файл типизации для пользовательской библиотеки lib. При установке редактора вызываю:

    public componentDidMount(): void {
        languages.typescript.javascriptDefaults.addExtraLib(
            typings,
        );
    }

Переменная typings загружается:

// eslint-disable-next-line @typescript-eslint/no-var-requires
const typings = require("../../../modules/scripting/typings/my-runtime.d.ts");

Боковое примечание: комментарий eslint необходим, иначе он будет отмечать require назвать отказом.

Я использую response-app-rewired, чтобы разрешить редактирование конфигурации моего веб-пакета без извлечения приложения на основе CRA. Теперь файл config-overrides.js содержит:

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

module.exports = function override(config, env) {
    config.plugins.push(new MonacoWebpackPlugin({
        languages: ["typescript", "javascript", "mysql", "json", "markdown"]
    }));

    config.module.rules.push(
        {
            test: /\.(html|d\.ts)$/i,
            use: [
                {
                    loader: 'raw-loader',
                    options: {
                        esModule: false,
                    },
                },
            ],
        },
    );

    return config;
}

Как видите, здесь я обрабатываю файлы двух типов: html и d.ts. HTML-часть работает хорошо. Требование вызова для загрузки файла.html дает мне все содержимое файла html (мне нужно, чтобы загрузить<iframe> с моей пользовательской средой выполнения).

Однако вызов require для файла типизации возвращает объект (вероятно, модуль, трудно сказать, поскольку он выглядит пустым в отладчике в vscode).

Возникает вопрос: как изменить мою конфигурацию, чтобы можно было загружать файлы типизации (.d.ts) как текст?

1 ответ

Решение

Почему ты получаешь {}? Я думаю потому чтоbabel-loader правило загрузчика (которое обрабатывает *.ts) из cra конфликтует с вашим raw-loader правило (которое обрабатывает *.d.ts) и webpack решает использовать babel-loader там.

Я нашел два способа решить эту проблему, используя react-app-rewired, взгляните на это репо.

1) Используйте raw-loader более агрессивным встроенным способом.

// eslint-disable-next-line import/no-webpack-loader-syntax
const dogTypings = require('!!raw-loader?esModule=false!./dog.d.ts');

Пояснение: !! смысл - отключить все остальные правила в конфигурации для этого файла. import/no-webpack-loader-syntax ограничивает использование встроенного синтаксиса, поэтому нам нужно отключить его там.

2) Удалите ModuleScopePlugin из cra конфигурация по умолчанию и создавайте свои типы за пределами src.
По умолчанию вы не можете ничего импортировать извнеsrc. Но сreact-app-rewired- конечно вы можете. Вот пример конфигурации:

const { resolve } = require('path');
const { removeModuleScopePlugin } = require('customize-cra')

module.exports = function override(config, env) {
    const newConfig = removeModuleScopePlugin()(config, env);

    newConfig.module.rules.push(
        {
            test: /\.(d\.ts)$/i,
            include: resolve(__dirname, 'typings'),
            use: [
                {
                    loader: 'raw-loader',
                    options: {
                        esModule: false,
                    },
                },
            ],
        },
    );

    return newConfig;
}

Примечание: у обоих этих способов есть обратная сторона - они отключают правило загрузчика babel (которое компилирует машинописный текст вcra приложения на самом деле) для этих .d.tsфайлы и проверка типов могут быть нарушены для их экземпляров, но я этого не проверял. Проблема с вашим кодом заключается в поведении компилятора машинописного текста, он удаляет.d.ts файлы из среды выполнения, поэтому webpack не испускал их, и я не нашел способа предотвратить это.

Другие вопросы по тегам