如何在使用Webpack和react create-react-app时,通过Monaco加载npm模块类型定义。

3

出于教程目的,我想在React应用程序中使用Monaco加载一些模块类型定义。

实际上,我在经历了许多痛苦之后终于使其工作,但是这种方法非常不规范。因此,我不是在问如何做到这一点,而是要问如何正确地做到这一点。

我希望能通过Webpack解决的部分是,现在我编写了一个Node.js脚本,可以在私有npm模块的构建文件夹中查找并提取所有的.d.ts文件,并将它们保存在一个大型的.json文件中。

数据格式如下:

{ [filePath]: 'fileContentAsString' }

然后在React中,我导入那个JSON,并为每一个调用addExtraLib

for (const filePath in sdkTypesJson) {
  // We add every .d.ts file to Monaco
  monaco.languages.typescript.typescriptDefaults.addExtraLib(
    sdkTypesJson[filePath],
    'file:///' + filePath.replace('dist/src/', '')
  );
}

有没有一种webpack的方法,可以避免创建json文件呢?

1个回答

7

经过两天的痛苦和折磨,我发现以下方法最有效。

const files = require.context('!!raw-loader!./node_modules/my-module-name/dist/src/', true, /\.d.ts$/);

files.keys().forEach((key: string) => {
  // We add every .d.ts file to Monaco
  Monaco.languages.typescript.typescriptDefaults.addExtraLib(
    files(key).default,
    'file:///node_modules/@adsk/fd-modeling-sdk/' + key.substr(2)
  );
});

require.context告诉Webpack从该路径中匹配正则表达式的所有文件进行捆绑。这里我获取了包含模块类型描述的所有.d.ts文件。

!!raw-loader!告诉Webpack加载文件而不尝试执行它。这会导致浏览器崩溃。您需要为Webpack安装raw-loader模块。

然后,您可以在嵌入的Monaco实例中使用类似于vs-code中的代码,并使打字感知像在vs-code中一样工作。

import {
  function
} from '@my-module-name';

export default async function run(value: string) {
  alert('Code ran. Value passed is ' + value);
};

回到你的应用程序代码中,你可以从 Monaco 获取代码并评估代码。在我的情况下,当用户在 react 应用程序中按下“运行”按钮时。

const model = editor.current.getModel();

if (model && sdk.current && editorType === 'text') {
  // Be cool if Monaco worker could transpile the file to js. Don't work for some reason.
  // Monaco.languages.typescript.getTypeScriptWorker()
  //   .then(function(worker) {
  //     worker(model.uri)
  //       .then(function(client) {
  //         client.getEmitOutput(model.uri.toString()).then((output: any) => {
  //           console.log(output);
  //         });
  //       });
  //   });

  // @ts-ignore
  const js = window.ts.transpile(model.getValue());
  const setup = `const exports = { default: null };`;
  const final = setup + ' ' + js;

  try {
    const runMethod = eval(final);
    const newState = await runMethod('My value');
  } catch (error) {
    console.error(error);
    alert(error);
  }
}

在理论上,你应该能够要求 Monaco typescript 工作者为你转译文件,但我没办法让它正常工作。 因此,暂时我在我的 React index.html 文件中加载了 typescriptServices,使用以下代码行。
<script src="https://unpkg.com/typescript@latest/lib/typescriptServices.js"></script>

1
感谢您的回答!针对一个相关的问题,我在这里使用了它作为解决方案的基础:https://dev59.com/x1gQ5IYBdhLWcg3wPxrc#66948535。 - Don McCurdy
1
这是我发现可以使用addExtraLib的帖子,所以我们又回到了起点:D - jfmmm
有趣,我今天也做了完全相同的事情,但刚刚发现这个问题。 - Jide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接