This is the principle repository for (Holloway) Chew, Kean Ho's experimentation to develop a pure Go web application supporting Progressive Web Application offline mode alongside using pure Go to develop web application entirely.
The goal of unifying web application development for client-side rendering using a proper programming language like Go has been aspired but low implementations due to little efforts. That's why the primary goal is to:
- Develop the foundational Go library so that the customers (Go web developer)
to deploy web app.
- ☑️ - Power on with
ExperimentingGoWASM
Go workspace withvendor/hestiaGo
andvendor/presentoGo
packages. - ☑️ - Develop Monteur's test, build, package, and release recipes for GoWASM.
- Develop baseline foundation for using GoWASM.
- ☑️ - Develop
<body>
manipulations directly in GoWASM (output). - ☑️ - Develop
<body>
manipulations directly in GoWASM (input). - ☑️ - Develop
<body>
manipulations directly in GoWASM (event-driven). - ☑️ Explore and conclude the necessity of using TinyGo.
- ☑️ - Power on with
- Develop client-side rendering capability using Hugo for
cost reduction between the server sides and the end-user sides.
- ☑️ - Power on with Presento Theme with NoCSS but rendering capabilities.
- ☑️ - Develop necessary partial functions to isolate Hugo's risky functions and also to prevent supply-chain vendor locked-in whenever possible.
- ☑️ - Develop plain HTML+Javascript pages necessary to bring up Go-WASM.
- ☑️ - Power on Go-WASM+HTML+Javascript on Hugo.
- ☑️ - Deploy Gunzip against Go-WASM to reduce its size with Monteur.
- ☑ - Develop necessary foundation for Go-WASM client-side rendering.
- Develop the necessary CSS/Sass frontend rendering libraries to keep the
foundation reasonably and visually appealing at minimum.
- ☑️ - Analyize (1) and (2) to see exactly where to develop the CSS/Sass and why. Make sure it's documentable.
- ☑ - Develop the core component to render the page without device screen locking.
- Use scalable tools that can roll out updates for multiple technologies
modularly and without much fears.
- ☑️ - deployed ZORALab's Monteur to manage the repository systematically, customizable at scale.
- ☑️ - deployed Hugo Themes module to manage Hugo specific and scalable setup.
Here are the list of 3rd-party dependencies used so far:
- ZORALab's Monteur - https://monteur.zoralab.com
- Go - https://go.dev
- Hugo - https://gohugo.io/
- GolangCI-Lint - https://golangci-lint.run/
- TinyGo - https://tinygo.org/docs/guides/webassembly/
After decent research, it was found that many network CDN and load balancer service providers (e.g. CloudFlare) automatically serves the content in compressed mode with GZip or Brotil (see https://support.cloudflare.com/hc/en-us/articles/200168396-Does-Cloudflare-compress-resources-).
For self-hosting CDN servers like Nginx or Apache, they already are serving compression executions when enabled (see: https://docs.nginx.com/nginx/admin-guide/web-server/compression/).
Hence, there is no need to worry about manual compression.
To determine where pure-Go WASM rendering to serve, a detailed scan through of how consumption behavior affects the web technologies and how it serves.
Here, we look into what and how consumptions influences the web languages:
Available Formats | Caused By | Content By | Designed By | Behavior By |
---|---|---|---|---|
html , css , js |
normal use | html |
css |
js |
html , css |
js-block | html |
css |
css |
html , css |
ad-block | html |
css |
css |
html , js |
React-type | html |
js |
js |
html , js |
Angular-type | html |
js |
js |
js |
single-page | js |
js |
js |
html |
baremetal | html |
Conclusion for Designing Pure-Go WASM Library
- The UI library must be capable of generating its necessary HTML content codes.
- The UI library must be capable of generating its necessary CSS styling codes.
- The CSS codes MUST be flexible for various deployments notably as:
- inline HTML
- as
css
file (external) - inside
js
- as inline
css
(inside HTML) js
rendering codes.
- The CSS codes MUST be flexible for various deployments notably as:
- The content codes must be flexible enough to store in both
html
andjs
formats. - the behavior part is split into 2 parts:
- UI related behavior (e.g. bouncing, dancing, etc) shall be handled solely
by
css
. - Data processing or routing (e.g. trigger loading screen, transmitting
submission to server, etc) should be solely handled by
js
.
- UI related behavior (e.g. bouncing, dancing, etc) shall be handled solely
by
- The UI library MUST leverage the compiler's unused code shedding capability for any of the user choice of output.
Here, we look into different UI tech availability for rendering the a display output:
Technologies | Source |
---|---|
vanilla web |
https://html.spec.whatwg.org/#introduction |
qt |
https://doc.qt.io/qt-6/wasm.html |
wails |
https://wails.io/ |
lorca |
https://github.com/zserge/lorca |
pwa |
https://web.dev/progressive-web-apps/ |
webview |
https://github.com/webview/webview |
seed |
https://github.com/qlova/seed |
qt (Go) |
https://github.com/therecipe/qt |
tcell |
https://github.com/gdamore/tcell |
Conclusion:
- The UI package MUST leave room for horizontal scaling outside of web technologies alone.
- The package MUST be a factory of similar design to generate the technology specific codes while allowing the compiler to shed unused ones seamlessly.
Here, we look into different devices rendering the same content page:
Conclusion:
- UI library web rendering SHALL NOT DEPENDS on device-oriented media query breakpoint.
- Any media query SHALL be oriented to the design module with its own definitions of breakpoint indepnendent of device dimension.
- As the hardware industry rolls out odd screen sizes, there is a need to develop a new approach to avoid breakpoint dimension whenever possible.
- All media tags (e.g. images, videos, etc) shall have pixel density awareness.
Here are the tracking issues critical to the research success:
- Tinygo WASM Memory Leak (first detected after implementing Chain kernel example) - tinygo-org/tinygo#1140
- Go WASI Implementation (first detected near experimentation conclusion)
The FIRST technology chosen was ZORALab's Monteur to manage the repository development continuously and controls with confidences when deploying the repository in a decentralized manner.
The first step you need to do would be installing Monteur as per instructed in their official website.
Once the monteur
program is available, proceed to your own copy and perform:
$ monteur setup
Monteur shall setup all the repository's dependencies and configurations
seamlessly. Repeat this monteur setup
command whenever there is an update from
Monteur Setup Job recipes OR something went wrong with the current setup in
your repository.
The second step is to bring up your local development. Monteur setup local filesystem inside the repository. Hence, whenever you open a new terminal to wanting to develop this repository, simply do the following:
$ source .monteurFS/config/main
Once done, the terminal you're in is now configured to be repository specific. You're now ready to develop the repository. All instructions beyond this step assumes you always this step.
NOTE
Whenever you find any software that is missing in action, you're likely forgotten this step.
The SECOND technology selected was hugo
for simple static site generations.
The repository is designed in a way that it can operate in offline or bad
connectivity environments. To do that, execute:
.configs/hugo/server.cmd
Once done, please visit the URL site presented in the terminal. The default is: http://localhost:8080
If you need to work on something else, you need to setup a new terminal again.
The THIRD technologies selected were go
and golangci-lint
for their
simplicity and portability sake. In order to work on the Go project, you need
to open a new terminal, perform the Step (2) for it, and then change directory
into wasmExpGo
. That is the root location of the Go source codes and its
workspace.
cd wasmExpGo
While the workspace is for this repository, the file structures are arranged
into 3 different Go modules
: wasmExpGo
, hestiaGo
, and presentoGo
. The
minimal file structure is as follows:
.
├── app
│ └── wasm
│ └── main.go
├── go.mod
├── hestiaGo
│ ├── go.mod
│ └── version.go
└── presentoGo
├── go.mod
└── version.go
Each module has its specific roles to prevent vendor locked-in threat while maintaining Go's quality in package modularlities. They key roles are:
wasmExpGo
- the repository specific packages.hestiaGo
- the common library packages that will be upstreamed to: https://github.com/ZORALab/HestiapresentoGo
- the frontend UI rendering packages that will be upstreamed to: https://github.com/ZORALab/Presento
To prevent supply-chain nightmare from affecting any project, go.mod
plays a
critical role here to make sure all the source codes know where to find the
packages.
Generally speaking, all import statements SHALL use the replace
clause
to denote its sourcing navigations. Here is a simple example:
// Copyright 2022 "Holloway" Chew, Kean Ho <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
package main
import (
"fmt"
"hestiaGo"
"presentoGo"
)
func main() {
fmt.Printf("Hello World\n")
fmt.Printf("Hestia Version: %s\n", hestiaGo.VERSION)
fmt.Printf("Presento Version: %s\n", presentoGo.VERSION)
}
Notice that both hestiaGo
and presentoGo
are not imported using
github.com/hollowaykeanho/...
. Instead, they are using their navigator.
Then in wasmExpGo
's go.mod
, it has replace clauses as follows:
module github.com/hollowaykeanho/ExperimentingGoWASM/wasmExpGo
go 1.18
replace (
github.com/hollowaykeanho/ExperimentingGoWASM/wasmExpGo => ./
hestiaGo => ./hestiaGo
presentoGo => ./presentoGo
wasmExpGo => ./
)
The module
clause remains as default since we want to maintain go get
capability. However, in source codes, we use wasmExpGo
instead just like the
other 2.
Then, in each 3rd-party libraries, their modules are in accordance to their
respective go.mod
settings:
module https://github.com/ZORALab/Hestia/hestiaGo
go 1.18
replace (
github.com/ZORALab/Hestia/hestiaGo => ./
hestiaGo => ./
)
With Monteur Test CI Job made available, given the correct recipe, Monteur can perform either pinpoint or recursive testing against Go packges. All the user needs to do is:
$ monteur test
And then all the necessary result data files are generated into the package directory itself.
With Monteur Build CI Job made available, given the correct recipe, Monteur can peform percise Go build in a reproducible manner. All the user needs to do is:
$ monteur build
With Monteur Package CI Job made available, given the correct recipe, Monteur can peform proper packaging in a reproducible manner. All the user needs to do is:
$ monteur package
With Monteur Release CI Job made available, given the correct recipe, Monteur can peform proper manage the Go WASM systematically. All the user needs to do is:
$ monteur release
At this point, Go development is considered completed.
With Monteur Compose CI Job made available, given the correct recipe, Monteur can properly compose Hugo's website artifact for web publications. All the user needs to do is:
$ monteur compose
At this point, Hugo development is considered completed.
With Monteur Publish CI Job made available, given the correct recipe, Monteur can properly publish the composed website artifact to the public. All the user needs to do is:
$ monteur publish
At this point, the development is considered deployed.
The repository is licensed under MIT License.