As I’m writing more and more Motoko, it would be nice to have a playground to quickly test code. The quickest way I’ve found to test a function is to run this after each modification:
dfx deploy && dfx canister call my_can myFunc
Even with minimal code, this takes roughly 30 seconds before the output of myFunc is reported.
If you’ve only made changes to a single canister you can run: dfx build my_can && dfx canister install my_can -m upgrade && dfx canister call my_can myFunc
You can check the options for any of these commands with the --help flag too, eg: dfx canister install --help
@Ori For some reason, when I try to build just the one canister I’m working on, it fails with
import error, canister alias "credits" not defined
even though I do have a canister named credits in the project that can be built successfully with
dfx build credits
Everything builds and runs successfully when I use dfx build or dfx deploy, so I’m not sure why building just a single canister fails when it is importing another canister.
Yup. The first command, dfx build serve fails, complaining that credits is not found. serve is one canister that imports the credits canister which is in the same project and both exist in the canister_ids.json file:
% dfx build serve
Building canisters...
The build step failed for canister 'ryjl3-tyaaa-aaaaa-aaaba-cai' with an embedded error: The command '"/Users/mikem/.cache/dfinity/versions/0.6.16/moc" "/Users/mikem/OneDrive/Projects/Web/videate/credits/src/serve/main.mo" "-o" "/Users/mikem/OneDrive/Projects/Web/videate/credits/.dfx/local/canisters/serve/serve.did" "--idl" "--actor-idl" "/Users/mikem/OneDrive/Projects/Web/videate/credits/.dfx/local/canisters/idl/" "--actor-alias" "serve" "ryjl3-tyaaa-aaaaa-aaaba-cai" "--package" "base" "/Users/mikem/.cache/dfinity/versions/0.6.16/base"' failed with exit status 'exit code: 1'.
Stdout:
Stderr:
/Users/mikem/OneDrive/Projects/Web/videate/credits/src/serve/main.mo:19.1-19.34: import error, canister alias "credits" not defined
serve uses import Credits "canister:credits"; to import the credits canister and the credits code is parallel to the serve code. Both are able to be deployed with dfx deploy commands; building works just fine in that case.
Oh interesting. Odd that the deploy command works without the dependency, but the build command doesn’t. I thought deploy just used build under the hood. Something else is going on?
Hi all! I’d like to revive this thread now that a year and a half has gone by to see what the community is doing to quickly test code changes.
Is it still best practice to use dfx build myCanister && dfx canister install myCanister -m upgrade each time I make changes to myCanister? It certainly works a lot faster than dfx deploy myCanister.
How about testing frontend code, for example React, that lives in a canister? Just use the above set of commands to quickly rebuild and upgrade the asset canister? Is that the fastest way to see quick UI changes, like if you change a color and want to see how it looks, or change some javascript/tsx to modify UI behavior, without having to do the upgrade as above and then refresh the page (actually refreshing never works since it always ends up going to the root so I always need to manually load the proper URL) and go through the process of logging in with Internet Identity and navigating to the page with the changes? Has anyone found a way to skip all that and maybe even have the site hot reload to see the changes immediately on save without requiring logging in again or navigating to the correct page? Any other tips to speed up development time, especially when working with UIs?
I found that using a pre-built Internet Identity Wasm will allow for quicker testing by using the II_DUMMY_CAPTCHA and II_DUMMY_AUTH feature flags to speed up the Internet Identity account creation and login process (see the Development or Test prebuilt Wasm modules), but I feel like there must be some more tips out there to further speed up UI development and iteration time.
Maybe I’m expecting too much at this point, but I would love to have a page just hot reload with my code changes. Developing for mobile devices using Google’s Flutter has spoiled me, I guess. How close can we get to that when developing on the IC?
Oh cool! If I run my canisters using npm start, I can access the frontend canisters using port 3000, which will hot reload when I save a .tsx file.
My next challenge: Internet Identity now doesn’t work due to the port mismatch, so I can’t test using hot reload on any pages accessible only after successful login.
After logging in with Internet Identity, when I’m returned to my page, the following error prints out in the console that ran npm start:
[webpack-dev-server] [HPM] Error occurred while proxying request localhost:3000/api/v2/status to http://localhost:8000/ [ECONNREFUSED] (https://nodejs.org/api/errors.html#errors_common_system_errors)
Seems like webpack can’t connect to my local Internet Identity canister. It didn’t have a problem loading the Internet Identity login page on port 8000, but for some reason seems to be trying to proxy it through 3000 along with my frontend stuff.
The solution to this similar issue was to run the application server in one terminal and the webpack (via yarn) in another, but I am already doing that: I ran dfx start in one terminal (which makes port 8000 work for the backend canisters) and I ran npm start in another (which makes port 3000 work for the frontend canisters).
I also noticed that when I use npm start, I no longer need to specify the canisterId for my asset canister. It loads my asset canister no matter what I specify for the canisterId query parameter.
Anyone know how to resolve this port issue? What’s the proper workflow for being able to hot reload your pages that are only available after logging in through a locally running Internet Identity canister?
@kpeacock you do a lot of IC frontend development, surely you are able to hot reload pages post-login? How are you able to get around the port issue described above and succeed with the login?
@paulyoung I’d love to see your process, as I’m still facing this issue. My current workaround is to develop the pages by placing them before sending the user to login, then moving them after they look good.
I’m currently struggling with the following error when trying to do the proxying by modifying webpack.config.js:
Error occurred while proxying request r7inp-6aaaa-aaaaa-aaabq-cai.localhost:3000/api/v2/status to http://r7inp-6aaaa-aaaaa-aaabq-cai.localhost:8000/ [ENOTFOUND] (https://nodejs.org/api/errors.html#errors_common_system_errors)
I’ll have to pick this up tomorrow. It seems my next steps might be to use esbuild or icx-proxy as you do. I have no experience working with those, but I’ll play around tomorrow. Thanks for your help!