如何使用 Webpack 在摩纳哥加载 npm 模块类型定义并做出反应 create-react-app

Posted

技术标签:

【中文标题】如何使用 Webpack 在摩纳哥加载 npm 模块类型定义并做出反应 create-react-app【英文标题】:How to load npm module type definition in Monaco using Webpack and react create-react-app 【发布时间】:2020-11-28 07:34:46 【问题描述】:

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

实际上,在经历了很多痛苦之后,我设法让它工作了,但是以一种非常老套的方式。所以我问的不是怎么做,而是如何做对。

我希望我能用 Webpack 解决的部分是,我现在制作了一个 Node.js 脚本,它获取了它可以在私有 npm 模块的 build 文件夹中找到的所有 .d.ts 文件,并将它们保存在一个大的 . json 文件。

这种格式

 [filePath]: 'fileContentAsString' 

然后在反应中我导入该 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】:

在经历了两天的痛苦和痛苦之后,我发现这是最好的工作。

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 安装 raw-loader 模块。

然后,您可以在嵌入式 Monaco 实例中使用这样的代码,并让输入 Intellisense 像在 vs-code 中一样工作。

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

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

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

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 打字员为您转译文件,但我无法让它工作。

所以我现在用这一行在我的 react index.html 文件中加载了typescriptServices

<script src="https://unpkg.com/typescript@latest/lib/typescriptServices.js"></script>

【讨论】:

感谢您的回答!对于一个相关的问题,我在这里使用它作为解决方案的基础:***.com/a/66948535/1314762。 这是我发现可以使用addExtraLib的帖子,所以我们绕了一圈:D 好玩,我今天也做了一模一样的事,却发现了这个问题。

以上是关于如何使用 Webpack 在摩纳哥加载 npm 模块类型定义并做出反应 create-react-app的主要内容,如果未能解决你的问题,请参考以下文章

如何在 NPM 包中使用 webpack 动态导入?

将常规 npm 包加载到 webpack/angular cli [找不到模块]

使用 webpack 在 monaco-editor 包中构建字体文件

如何在 webpack 中同时使用 ES6 加载器和 brfs 转换?

webpack使用笔记

关于webpack的理解和npm的使用