We used what I would call the package object predef pattern, which basically involved, rolling your own predef to have certain functions / extension classess / objects always in scope through package objects added to each sub-project. And the build would cross-compile both jvm scala and scalajs. It would not take more than a second or two unless one of those predef files were touched (which would fire off effectively a full rebuild).