【弃用】在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
概括一下


环境
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”的内容!