Wasm binary optimization
At some point your compiled Rust Wasm binary will grow too large and will be rejected by the canister on deploy. This could happen because the Rust source code that you've written has grown too large, or because your schema has grown too large. A large schema will lead to a large amount of generated Rust code.
To temporarily overcome this issue (only so much can be done during optimization, eventually the binary will be too big and the Internet Computer will need to address that), you can optimize your Rust Wasm binary.
Manual optimization
To do this manually, in the root of your directory run the following command once to install the optimizer:
cargo install ic-cdk-optimizer --root target
You should also change your dfx.json
file from:
{
"canisters": {
"graphql": {
"type": "custom",
"build": "cargo build --target wasm32-unknown-unknown --package graphql --release",
"candid": "canisters/graphql/src/graphql.did",
"wasm": "target/wasm32-unknown-unknown/release/graphql.wasm"
}
}
}
to:
{
"canisters": {
"graphql": {
"type": "custom",
"build": "cargo build --target wasm32-unknown-unknown --package graphql --release",
"candid": "canisters/graphql/src/graphql.did",
"wasm": "target/wasm32-unknown-unknown/release/graphql-optimized.wasm"
}
}
}
The only thing that changed was the wasm
property of the graphql
canister object, and it changed from "wasm": "target/wasm32-unknown-unknown/release/graphql.wasm"
to "wasm": "target/wasm32-unknown-unknown/release/graphql-optimized.wasm"
.
Each time you run dfx deploy
or dfx deploy graphql
, you will need to run the following command after:
./target/bin/ic-cdk-optimizer ./target/wasm32-unknown-unknown/release/graphql.wasm -o ./target/wasm32-unknown-unknown/release/graphql-optimized.wasm
Automatic optimization
It can be tedious to have to run the above command manually after each dfx deploy
. If you wish to figure out how to use cargo
scripts of some kind you can do that. You could also use make
or bash
or some other build process or scripting system.
Another way is to adopt npm scripts. Your package.json
could look something like this:
{
"scripts": {
"build": "cd canisters/playground && npm install && npm run build && cd ../frontend && npm install && npm run build",
"dfx-deploy": "npm run dfx-build-graphql && npm run dfx-optimize-graphql && dfx deploy",
"dfx-deploy-graphql": "npm run dfx-build-graphql && npm run dfx-optimize-graphql && dfx deploy graphql",
"dfx-build-graphql": "cargo build --target wasm32-unknown-unknown --package graphql --release",
"dfx-optimize-graphql": "./target/bin/ic-cdk-optimizer ./target/wasm32-unknown-unknown/release/graphql.wasm -o ./target/wasm32-unknown-unknown/release/graphql-optimized.wasm"
}
}
Then instead of running dfx deploy
or dfx deploy graphql
you would run npm run dfx-deploy
or npm run dfx-deploy-graphql
.
In the future it would be nice for the dfx.json
to allow for some sort of build scripts, which would make this process less messy. There is an open forum post about this here.