-
Notifications
You must be signed in to change notification settings - Fork 570
Frequently Asked Questions
GopherJS reimplements most of the Go runtime in Javascript, so that's a start. A lot of things import the fmt
and reflect
packages, which represents a sizable chunk of code. In general, GopherJS code is so large for reasons similar to the reason Go executables are so large: they're statically linked. In the Go case, literally; in the GopherJS case, metaphorically speaking, but the idea is similar.
What can I do to reduce the downloaded code size, or ameliorate the cost of downloading so much code?
- Follow these performance tips
- Try not to import packages you don't really need, like
fmt
. - Check out jsgo.io, which splits up GopherJS code into per-package files that are cached behind a CDN, essentially making GopherJS code non-monolithic / non-"statically linked", and increasing the likelihood and usefulness of caching at the package level.
We do! But that's both harder than it sounds, and not as useful as it sounds. "It's hard to dead code eliminate in Go in the presence of the reflect
package. You can call arbitrary methods on types at runtime, for example. And importing pretty much anything ends up importing reflect
." -- @Zeebo "Even in the absence of reflection, interfaces make it hard to prove what methods can safely be eliminated." -- @myitcv
You will need to use webpack and an "npm" distribution for the library you want to include. First run
npm install --save-dev webpack [external_library]
where [external_library]
is the one you want to use (e.g. "pdfjs-dist").
In the external library code that is installed in node_modules
(e.g. "node_modules/pdfjs-dist")
find the "source code" version of the library (e.g. "node_modules/pdfjs-dist/lib/pdf.js").
This file will be the one that includes lines that start with exports.
followed by some symbol in the
library's API (e.g. exports.PDFWorker = pdfjsDisplayAPI.PDFWorker;
).
Create a webpack.config.js
file with the following contents in the top-level of your project:
const webpack = require("webpack");
module.exports = {
entry: {
pdf: "./node_modules/pdfjs-dist/lib/pdf.js"
},
output: {
filename: "[name].inc.js",
libraryTarget: "this",
path: __dirname
}
};
Note that you can add additional JavaScript source files after the line
pdf: "./node_modules/pdfjs-dist/lib/pdf.js"
. For example:
entry: {
pdf: "./node_modules/pdfjs-dist/lib/pdf.js",
"pdf.worker": "./node_modules/pdfjs-dist/lib/pdf.worker.js",
"pdf_viewer": "./node_modules/pdfjs-dist/web/pdf_viewer.js"
},
In your main.go
file, include a line like this, near the top of the file:
//go:generate gopherjs build main.go pdf.inc.js -o app.js
Add any additional libraries after pdf.inc.js
(e.g. pdf.worker.inc.js pdf_viewer.inc.js
). You
can also add -m
to the end of the go:generate
line to minify the Go code. The included JavaScript code (*.inc.js
) will have been minified by default in webpack version >= 4.
//go:generate gopherjs build main.go pdf.inc.js -o app.js -m
Now run webpack
on the command line in the top-level of your GopherJS project (where main.go
is located). This should generate pdf.inc.js
(and any other libraries) in that same top-level
directory.
Finally, run go generate ./main.go
, which will generate app.js
containing your compiled
GopherJS program, as well as all of the .inc.js
libraries you added.
In your Go code, you can refer the to the exported symbols (e.g. exports.PDFWorker
) using code
like this:
var pdfWorker = js.Global.Get("PDFWorker")
You need to re-run the go generate ./main.go
after any changes to your Go source code (in any of your Go files).