Skip to content
GopherJS compiler, serving framework and CDN.
Go JavaScript Other
Branch: master
Clone or download

Latest commit

Latest commit d658ffe Dec 5, 2019


Type Name Latest commit message Commit time
Failed to load latest commit information.
assets Upgrade to Go 1.12, add syscall/js to initialise script Dec 5, 2019
config Upgrade to go1.11, add local setup instructions Sep 27, 2018
initialise Add syscall/js, better logging Dec 5, 2019
server Deploy tweaks Dec 5, 2019
testing Add cache Oct 17, 2018
LICENSE First commit Jan 16, 2018 Upgrade to go1.11, add local setup instructions Sep 27, 2018 Upgrade to go1.11, add local setup instructions Sep 27, 2018
go.sum Update go.mod Dec 5, 2019

GopherJS is an amazing tool, but I've always been frustrated by the size of the output. All the packages in the dependency tree (including the standard library) are compiled to a single JS file. This can cause the resultant file to be several megabytes.

I've always thought a better solution would be to split the JS up by package and store it in a centralized CDN. This architecture would then allow aggressive caching: If you import fmt, it'll be delivered as a separate file fmt.js, and there's a good chance some of your visitors will already have it in their browser cache. Additionally, incremental updates to your app will only change the package you're updating, so your visitors won't have to download the entire dependency tree again. makes this simple.


  • Compiles Go to JS using GopherJS.
  • Splits the JS up by Go package.
  • Stores the JS in a CDN for you (GCP / Cloudflare).
  • Aggressively caches the JS.
  • Creates a page on that runs the JS.
  • Creates a single loader JS file you can use on your site.

How it works

Visit<path> to compile or re-compile your package. Here's a very simple hello world. Just click Compile.

After it's finished, you'll be shown a link to a page that runs the code on The compile page will also give you a link to a single JS file on - this is the loader JS for your package. Add this in a <script> tag on your site and it will download all the dependencies and execute your package.

URLs on that start may be abbreviated: will be available at and also Package URLs on always use the full path.

Production ready?

The package CDN (everything on should be considered relatively production ready - it's just static JS files in a Google Storage bucket behind a Cloudflare CDN so there's very little that can go wrong. Additionally, the URL of each file contains a hash of it's contents, ensuring immutability.

The index pages (everything on should only be used for testing and toy projects. Remember you're sharing a domain with everyone else, so the browser environment (cookies, local storage etc.) should be used with caution! For anything important, create your own index page on your site and add the loader JS (on to a <script> tag.

Ths compile server (everything on should be considered in beta... Please add an issue if it's having trouble compiling your project.


The power of aggressive caching is apparent when loading pages which share common packages... The examples in the ebiten game library are a great demonstration of this:


You can customize the HTML delivered by the page by adding a file named index.jsgo.html to your package. Use {{ .Script }} as the script src. See todomvc for an example.


If a function window.jsgoProgress exists, it will be called repeatedly as packages load. Two parameters are supplied: count (the number of packages loaded so far) and total (the total number of packages).

The default index page on is to display a simple count / total message in a span. However, by supplying a custom index.jsgo.html, more complex effects may be created - see the html2vecty example for a bootstrap progress bar.


If there's any non git repositories (e.g. hg, svn or bzr) in your dependency tree, it will fail. This is unlikely to change. Workaround: vendor the dependencies and it'll work fine.

How to contact me

If you'd like to chat more about the project, feel free to add an issue, mention @dave in your PR, email me or post in the #gopherjs channel of the Gophers Slack. I'm happy to help!

Run locally?

If you'd like to run jsgo locally, take a look at these instructions.

You can’t perform that action at this time.