IPFS On Angular その2
【deprecated】IPFS On Angular(ブラウザでIPFSのノードを動かす)
こちらの内容のアップデート版です。
ざっくり言うと型を含めてAngukarでjs-ipfs(ipfs-core)を使用する場合の設定方法などの備忘録になります。
バージョン
"ipfs-core": "0.5.4"
"angular": "11.2"
インストール
# ブラウザで使う範囲だと `ipfs` ではなく `ipfs-core` で必要十分
$ yarn add ipfs-core
呼び出し箇所
簡単に呼び出せます。コンポーネントをまたいで使う場合はサービスにラップするといいでしょう。
// app.component.ts
// 省略
import * as ipfs from 'ipfs-core';
// 省略
export class AppComponent implements OnInit {
// 省略
async ngOnInit(): Promise<void> {
const node = await ipfs.create();
}
}
ちなみに自分で使う用にラッパーサービスのライブラリを作成して公開しています。よかったら使ってみてください。
アプリケーションの設定変更
angular.json
ここはその1と変わってないです。warnが出るので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
allowedCommonJsDependencies": ["ipfs-core"]
tsconfig.json
// error
An export assignment cannot be used in a module with other exported elements.
こちらのエラー解消のため、skipLibCheck
を有効にする必要があります。TS化が順調に進めば将来的には不要になるはずです。
また以下のビルドエラーの解消のためにstream
のpathを通しておく必要があります。
以前はdns
も必要と書いたのですがjs-ipfsのバージョンアップで不要になったようです(軽く調べたけどどのバージョンだったかよく分からなかった...)。
// example of errors
Error: ./node_modules/cbor/vendor/binary-parse-stream/index.js
Module not found: Error: Can't resolve 'stream' in ...
ipfsの内部でdefault import
が使われているので、allowSyntheticDefaultImports
をtrueにセットする必要があります。
// error
Error: node_modules/ipfs-core-types/src/bitswap.ts:2:13 - error TS1259: Module '"/home/ocknamo/workspace/ipfs/angular-ipfs-sample-app/node_modules/peer-id/src/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag
tsconfig.json
は以下のようになります。
// tsconfig.json
{
// 省略
"compilerOptions": {
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"paths": {
"stream": [
"node_modules/stream-browserify"
]
}
}
}
polyfill
もともとはpolyfills.ts
にNodejsのポリフィルを自力で書いていたんですが、起動まではいけるもののadd()
を実行すると実行時エラーでコケてしまうことが判明しました。
// こういうタイプエラーが大量に出るが、発生箇所を追ってみると`stream`をちゃんとshimできていないことが原因のようだった。
zone-evergreen.js:137 Uncaught TypeError: Cannot read property '_readableState' of undefined
対処方法としてとしては、自力でやることを諦め、node-polyfill-webpack-plugin
というwebpackプラグインを使用することにしました。その名の通りNodeのポリフィルを入れてくれるプラグインです。js-ipfsのwebpack実装サンプルで使われていたためこれにしました。
プラグインを入れる手順ですが、Angularに@angular-builders/custom-webpack
を導入して、必要なコンフィグファイルを用意するという順番になります。
Angularにカスタムwebpackプラグインを入れる。
@angular-builders/custom-webpack
を導入します。が、バージョンによって導入方法が変わるようで、ここに手順を書いてもすぐ陳腐化すると思われるため省略します。
簡単なので公式のドキュメントを読んだら入れられると思います。
extra-webpack.config.ts
事前にgrobal
はyarn add global
で、node-polyfill-webpack-plugin
はyarn add -D node-polyfill-webpack-plugin
で入れます。
import { Configuration, ProvidePlugin } from 'webpack';
import * as NodePolyfillPlugin from 'node-polyfill-webpack-plugin';
export default {
plugins: [
new NodePolyfillPlugin({}),
new ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
global: ['global'],
process: 'process/browser',
}),
],
} as Configuration;
Buffer, global, processの解決もProvidePlugin
を使ってここでやってしまいました。
NodePolyfillPluginに引数が必須になってたんですが、オプションで不要なPolyfullを指定できるようです。精査すればバンドルサイズを節約できるかもしれません。
実装サンプル
その他
-
console-browserify``util``assert
がCommonJS or AMD dependencies can cause optimization bailouts.
というwarnが出る。angular.json
のallowedCommonJsDependencies
に追加したら黙る。 - 記事を書くために再度いじっていたら
node-polyfill-webpack-plugin
のマイナーアップデートでimportするところが壊れた。マイナーアップデートなのに壊れていいのか。
Discussion