简体   繁体   中英

How to load a typings file as text with Webpack and React?

For setting up a Monaco editor instance I want to add a typings file for a custom lib. When mounting the editor I call:

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

The variable typings is loaded by:

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

Side note: the eslint comment is necessary or it will mark the require call as failure.

I use react-app-rewired to allow editing my webpack config without ejecting the CRA based application. Now the config-overrides.js file contains:

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;
}

As you can see I actually handle 2 file types here: html and d.ts. The html part works nicely. A require call to load an.html file gives me the entire html file content (I need that to load an <iframe> with my custom runtime).

The require call for the typings file, however, returns an object (probably a module, hard to say as it appears empty in the debugger in vscode).

So the question is: how to change my config to make loading typings files (.d.ts) as text possible?

Why do you getting {} ? I think because babel-loader loader rule (which handles *.ts ) from cra conflicts with your raw-loader rule (which handles *.d.ts ) and webpack decides to use babel-loader there.

I found two ways to handle this problem using react-app-rewired , please take a look at this repo .

1) Use raw-loader in a more aggressive inline way.

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

Explanation: !! meaning - disable all other rules in the configuration for this file. import/no-webpack-loader-syntax restricts to use inline syntax so we need to disable it there.

2) Remove ModuleScopePlugin from cra default config and create your typings outside of src .
By default you can't import anything from outside of src . But with react-app-rewired - of course you can. Here is config example:

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;
}

Note : both of these ways have a downside - they disable babel loader rule (which compiles typescript in cra apps actually) for these .d.ts files and type checking can be broken for their instances, but I did't check that. The problem with your code is the typescript compiler behavior, it removes .d.ts files from the runtime so webpack didn't emit them and I didn't found any way to prevent it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM