gRPC WebのクライアントはNode向けのcommonJS形式で出力されますが、commonJSはレガシーなフォーマットになりつつあります。
node-resoleveとcommonjsプラグインを利用してrollupでバンドルすることでESMを出力できます。
package.json
の記述例は以下のとおりです。
{
"dependencies": {
"grpc-web": "^1.2.1"
},
"devDependencies": {
"rollup": "^2.50.3",
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"rollup-plugin-terser": "^7.0.2",
"google-protobuf": "^3.17.0"
}
}
gRPC Webが生成するクライアントコードはsome_pb.js
とsome_grpc_web_pb.js
の2種類です。オプションによりd.ts
なども出力できますが、今回の例では、commonjs形式のアウトプットのみ利用します。
rollup.config.js
の記述例は以下のとおりです。
import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";
import {terser} from "rollup-plugin-terser";
const settings = (name) => {
return {
input: `./src/${name}.js`,
output: {
file: `dist/${name}_esm.js`,
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
terser()
]
}
}
export default [
settings('some_pb'),
settings('some_grpc_web_pb')
]
この例ではterser()
を利用していますが、なくても問題ありません。出力コードサイズもとくに変わりません。
configが揃ったら、rollup
コマンドでビルドできます。
出力されたESMモジュールはアプリケーションからインポートのうえ、規約に沿って利用できます。
ESMのインポート
// export default宣言のモジュールになっているため、命名してインポート
import some_message from './dist/some_pb_esm.js';
import some_service from './dist/some_grpc_web_pb_esm.js';
let client = new some_service.SomePromiseClient('https://example.com:50051', null);
let request = new some_messate.SomeRequest();
request.setParam('some parameter defined by proto');
client.someQuery(request);
export default
形式である点を除けば、とくに使い方は変わりません。
ESM形式に変換しておくことで、たとえばdenoからも利用でき、じっさいにdeno bundle
の出力コードが動作しました。
ただし、内部的にIIFE形式になっているためTree Shakingが効かず、ミニマムでも500kBほどのパッケージになります。
⁋ 2021/06/17↻ 2024/11/26
中馬崇尋
Chuma Takahiro
Chuma Takahiro