【弃用】在Angular中使用IPFS(在浏览器中运行IPFS节点)

【附加记录】由于内容过时,请参考此处。IPFS 在 Angular 上的第二部分。

首先

我想在浏览器上运行IPFS节点,并且想要使用类型。

我认为在其他地方已经写了IPFS方面的内容,所以不再介绍。 我认为阅读官方网站是最好的选择。
https://ipfs.io/

最近,IPFS的JS实现js-IPFS 0.51.0中添加了TypeScript的类型定义。

这之前只有志愿者制作的类型定义文件,所以非常值得庆幸。因为Angular也是用typescript编写的前端框架,所以在Angular上推动IPFS的类型安全操作也逐渐增加了动力。
由于遇到了不少困难,所以为了其他人的参考,我将错误代码和对应的解决方法都列出来了。

顺便提一下,在浏览器上运行IPFS的示例有很多,我正在参考官方提供的一些。
https://github.com/ipfs/js-ipfs/tree/master/examples

概括一下

Screenshot from 2020-12-13 17-13-30.png
Screenshot-ipfs-on-ng.png

环境

angular-cli的版本为10.2.0,angular的版本为10至11,js-ipfs的版本为0.52.1。

步驟 (bù

创建应用程序

快速使用angular-cli

ng new

接下来将按照指示进行制作。
本次应用程序的名称定为angular-ipfs-sample-app。

安装IPFS

cd angular-ipfs-sample-app
yarn add ipfs

这一次我们把整个IPFS都安装了,但从0.50版本开始,好像只需要安装IPFS核心功能就可以了,这样只需要安装核心功能就能节省捆绑大小。

请参考:https://blog.ipfs.io/2020-10-29-js-ipfs-0-50/

实现调用位置。

最后我们实现了将其变为可通过DI注入的服务,不过如果只需要调用,以下的实现就足够了。

import { Component, OnInit } from '@angular/core';

import * as ipfs from 'ipfs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'Connected to IPFS';
  id = '';
  agentVersion = '';

  async ngOnInit(): Promise<void> {
    console.log('IPFS Starting');
    console.time('IPFS Started');
    try {
      // ipfsのノードを作成
      const node = await ipfs.create();
      // 作成したノードのデータを取得
      const { id, agentVersion } = await node.id();
      this.id = id;
      this.agentVersion = agentVersion;
    } catch (error) {
      console.error(error);
    }
    console.timeEnd('IPFS Started');
  }
}

尽管视图最终会进行各种美化处理,但最朴素的表达方式如下所示。

<h1>IPFS Angular</h1>
<span class="title">{{title}}</span>
<div>id: {{id}}</div>
<div>Agent Version: {{agentVersion}}</div>

请参考最终形式。我已经创建了一个IPFS服务并进行了DI和样式修正,但由于此次是次要内容,所以省略掉了。

修改的内容等

如果按照现在的方式进行操作,是最轻松的方法。但是,js-ipfs依赖于nodejs库,因此必须解决这个依赖才能使其正常运行,否则会出现构建错误或运行时错误。我将提供使用正确类型和最低限度的必要配置来使其正常运行。请注意,我已经忘记了错误的呈现顺序,因此这些参考信息是无序的。

angular.json可以被用作Angular项目的配置文件。

由于IPFS还依赖于commonjs模块,因此会出现以下警告。

Warning: /home/ocknamo/workspace/ipfs/angular-ipfs-sample-app/src/app/services/ipfs.service.ts depends on 'ipfs'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

修改 angular.json 文件以允许使用 commonjs。

"allowedCommonJsDependencies": [
              "ipfs"
            ]

tsconfig.json 文件

由于出现构建错误,需要解决类型问题。

首先,

// error
An export assignment cannot be used in a module with other exported elements.

因为这里出现了大量的错误,所以需要启用skipLibCheck。

接下来会收到关于没有 nodejs 的流的错误信息。

// error
Error: ./node_modules/cbor/vendor/binary-parse-stream/index.js
Module not found: Error: Can't resolve 'stream' in ...

让我们通过这条路径走吧。

"stream": [
  "node_modules/stream-browserify"
  ]

决不能随意使用”yarn add stream”等方式来错误解决问题。(npm上的stream包只是偶然具有相同名称,并且没有维护)

DNS也会出错。

// error
Warning: ./node_modules/multiaddr/src/resolvers/dns.js
Module not found: Error: Can't resolve 'dns' in ...

DNS 在浏览器中应该没有关系,所以(可能)在模拟中解决。

"dns": [
  "node_modules/node-libs-browser/mock/dns.js"
],

tsconfig.json的最终结果将成为这样。

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "compileOnSave": false,
  "compilerOptions": {
    // 省略
    "skipLibCheck": true,
    "paths": {
      "stream": [
        "node_modules/stream-browserify"
      ],
      "dns": [
        "node_modules/node-libs-browser/mock/dns.js"
      ]
    }
  }
}

src/polyfills.ts的原始代码在中国文化中有如下表达方式:

源码/polyfills.ts

因为在执行时还有很多错误非常麻烦,所以让我们设置一些多元化的填充方案吧。

// errors
Uncaught ReferenceError: global is not defined
// AND OR
Uncaught ReferenceError: Buffer is not defined
// AND OR
Uncaught ReferenceError: process is not defined
// AND OR
Uncaught TypeError: process.nextTick is not a function

在polyfills.ts的末尾添加以下内容。

(window as any).global = window;
global.Buffer = global.Buffer || require('buffer').Buffer;
(window as any).process = {
  env: { DEBUG: undefined },
  version: [],
  nextTick: require('next-tick')
  };

顺便说一下,如果你想通过使用一个随意的箭头函数来模拟nextTick而不出错的话,那你将会陷入困境。所以请确保正确解决依赖关系。我已经为此花费了相当多的时间。

不好的模式

  nextTick: () => {},

其他

如果需要调用window.ipfs,则需要覆盖类型,并在src/@types/中创建类型定义文件并加载它。

interface Window {
  ipfs: any;
}

由于tsconfig.app.json中原本已经设置了include,所以只需使用此选项即可进行加载。

"include": [
  "src/**/*.d.ts"
]

結束

如果您能提供更好的应对方法或评论,我将不胜感激。

下一篇计划写关于”Angular ON IPFS”的内容!

广告
将在 10 秒后关闭
bannerAds