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.