Use Go and Webpack to generate static websites like a standard Go web application. You can even run gostatic
apps, as a web app.
Meant to be simple, so defaults are given (SASS, image optimization, S3 deployment, etc.). You can rip out the defaults and use your own Go HTML templates, CSS preprocessor, etc.
- Docker Desktop (if no Docker, see
Dockerfile
for system requirements) - Optional direnv to automatically export/unexport ENV variables. You can export them yourself via
source ./.envrc
.
You can install the gostatic
binary via go get
and run it:
go get github.com/s12chung/gostatic
...
gostatic new some_project_name
This is will create a new project in the current directory. After:
# without direnv, call: source ./.envrc
make docker-install
This will build docker and do all the installation inside docker. After, it’ll copy all downloaded code libraries from the docker container to the host, so that when the container and host sync filesystems, the libraries will be there.
You can run a developer instance through Docker via:
make docker
For production:
make docker-prod
By default, this will generate all static website files in the generated
directory and host the directory in a file server at http://localhost:3000
.
The following is managed through a Makefile
:
- A Go executable
- A Webpack setup
watchman
- A file diff watcher by Facebook to auto compile everything conveniently for developmentaws-cli
- Handles Amazon S3 Deployment
First, Webpack compiles/optimizes all the assets (JS, CSS, images) in the generated/assets
directory (make build-assets
). It also generates a Manifest.json
and a images/responsive
folder of JSON files. These JSON files give the Go executable file paths to assets from the Webpack compilation.
After, the Go executable generates all the route files in the generated
directory (make build-go
) . See the Go section below.
The Go executable also hosts the generated
directory in a file server (make file-server
).
You can also run your project as a web app (make server
), which uses Go std lib net/http
internally.
I run them through Docker, which handles all the system dependencies: Go, nodejs, image optimization, etc. See Dockerfile
to see system dependencies. Your local system probably has some of them already, as Docker is running Alpine, a minimal Linux distribution.
The following packages are used in the bare bones Hello World app provided for you:
cli
- Basic CLI interface for for your main.goapp
- Does high level commands of thecli.App
interface (generate, file-server, server) by taking your routes to generate files concurrently or serving it via httphtml
- Wrapper around Go std libhtml/template
to render templates, handle layouts, etc.webpack
- Lets Go see into the generated asset paths,Manifest.json
, andimages/responsive
folder of JSON files from Webpackrouter
- Maps the URL paths to your functions like a http router, so that it can generate files or host a web app
It's best to start at go/content/content.go and add more routes:
func (content *Content) renderHTML(ctx router.Context, name string, layoutD interface{}) error {
bytes, err := content.HTMLRenderer.Render(name, layoutD)
if err != nil {
return err
}
ctx.Respond(bytes)
return nil
}
// SetRoutes is where you set the routes
func (content *Content) SetRoutes(r router.Router, tracker *app.Tracker) error {
r.GetRootHTML(content.getRoot)
r.GetHTML("/404.html", content.get404)
r.Get("/robots.txt", content.getRobots)
return nil
}
func (content *Content) getRoot(ctx router.Context) error {
return content.renderHTML(ctx, "root", layoutData{"", "Hello World!"})
}
func (content *Content) get404(ctx router.Context) error {
return content.renderHTML(ctx, "404", layoutData{"404", nil})
}
func (content *Content) getRobots(ctx router.Context) error {
userAgents := []*robots.UserAgent{
robots.NewUserAgent(robots.EverythingUserAgent, []string{"/"}),
}
ctx.SetContentType(mime.TypeByExtension(".txt"))
ctx.Respond([]byte(robots.ToFileString(userAgents)))
return nil
}
See router.Router
interface and the app.Setter
interface.
There are helpful packages in s12chung/gostatic-packages too.
A default webpack config is given to you, which handles assets in the assets
directory. Below are defaults, via npm packages:
gostatic-webpack
- wraps the two libs below to configure Webpack forgostatic
(manifest, entrypoints, Webpack optimizations, etc.)gostatic-webpack-css
- handles the.css
and.scss
(SASS) files in theassets/css
directorygostatic-webpack-images
- handles favicon files placement, image and compression in theassets/favicon
andassets/images
directory
Packages that you can easily rip out are:
gostatic-webpack-babel
- handles javascript transpiling of thejs
directory
The assets/js-extract
directory is intended for importing things you want Webpack to extract out (CSS, Images, etc.).
gostatic
projects are designed to be hosted on Amazon S3. See wiki on S3 to setup S3 in the AWS Management Console, outside of the code.
Within your project, store the Access Key ID
and Secret Access Key
in aws/credentials
of the project (see aws/config
too), so aws-cli
can use them. Set the S3_BUCKET
in .envrc
, so Makefile
can see it. Then to upload everything to S3:
make docker-deploy
I usually use:
make push-docker-deploy
because it ensures my origin master is synced with my homepage. In the future, I’ll make gostatic
projects deploy via Travis CI, so whenever origin master updates, the page updates.
You can host your project directly from Amazon S3. This is easier, but you won't have SSL and a CDN. See S3 instructions on wiki.
I find it best to use Amazon CloudFront CDN with Amazon Certificate Manager to provide SSL. See CloudFront instructions on wiki.
Also, note about CNAMEs on Root domains, which can break your emails.
Here are my projects built with gostatic
:
- s12chung/go_homepage - my homepage, where most of this code was extracted from
- s12chung/photoswipestory - a static website as a photo book type project for a birthday present (so not my best code)
Much inspiration was taken from brandur/sorg.