Friday, November 30, 2012

Deploying Full Stack Dart to Heroku

‹prev | My Chain | next›

I was able to deploy Dart Comics, my sample Dart application, to Heroku. At this point I have the server-side Dart running properly, but the client-side Dart not so much.

Actually, the Dart code that is in the public directory of my application is being received just fine by Dartium. The problem is that the Hipster MVC client library is nowhere to be found:

That is not all that surprising considering that the Dart Pub dependency install script has only been run for server-side dependencies—not for my client libraries. Since this is Heroku, I cannot shell into my server an install things. Instead I need a buildpack to get this installed at build time.

As far as I know, it is only possible to run one buildpack at a time on Heroku, so I fork the Dart buildpack to pub install not only the server-side, but also the client-side pub packages. As my first attempt, I try to simply pub install in the public/scripts directory by adding the following to the compile script:
message "-----> Install client packages"

cd $BUILD_DIR/public/scripts

#start pub from the /app folder to have correct symlink paths
/app/dart-sdk/bin/pub install

After committing that change to my fork, I configure my app to use this buildpack instead of the official Dart buildpack:
➜  dart-comics git:(master) heroku config:add BUILDPACK_URL=    
Setting config vars and restarting dart-comics... done, v11
With that, I am ready to try it out. I do not know how to force deploy, so I make a minor change and push it:
➜  dart-comics git:(master) gp heroku master
Counting objects: 11, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 983 bytes, done.
Total 7 (delta 3), reused 0 (delta 0)

-----> Heroku receiving push
-----> Fetching custom git buildpack... done
-----> Dart app detected
-----> Installing Dart VM, build: latest
-----> Copy Dart binaries to app root
-----> Install server packages
Resolving dependencies...
Dependencies installed!
-----> Install client packages
Resolving dependencies...
Downloading hipster_mvc 0.2.0...
Dependencies installed!
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size: 6.2MB
-----> Launching... done, v12 deployed to Heroku

   a49850f..5529e3b  master -> master
Nice! That definitely picked up my Hipster MVC client-side package and installed it. Unfortunately that is not quite the end of the story because the Hipster MVC files are still not seen on the server.

After a bit of digging, I find that, although the public/scripts/packages is linked properly:
~/public/scripts $ ls -lh packages
hipster_mvc -> /app/tmp/repo.git/.cache/pub-cache/hosted/
The public/scripts/web/packages directory that really matters is still linked to the build directory:
~/public/scripts $ ls -lh web/packages
web/packages -> /tmp/build_2srdmesaavhar/public/scripts/packages
To fix this, I overwrite the public/scripts/web/packages symlink in the compile buildpack script:
# ...
message "-----> Install client packages"

cd $BUILD_DIR/public/scripts

#start pub from the /app folder to have correct symlink paths
/app/dart-sdk/bin/pub install

# still have to brute force web/packages
cd $BUILD_DIR/public/scripts/web
ln -sf ../packages

I am unsure if that would work as a general purpose solution, but in my case, I only have the single dependency so this ought to be OK.

And that does the trick. Now when I reload the application, all of the Dart files load, the Hipster MVC libraries included. With that, I can use my Dart browser to load a Dart application backed by a Dart MVC framework. This, in turn, talks to a Dart web server on Heroku that talks to a Dart datastore. That's a whole lot of Dart:

And, in Heroku-style, I do it all with a single git push.

Day #585

No comments:

Post a Comment