github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/_talks/2017/golang_uk.slide (about) 1 Creating interactive frontend apps with GopherJS and React 2 3 Paul Jolly 4 Co-founder, modelogiq 5 paul@myitcv.io 6 https://myitcv.io 7 @_myitcv 8 9 10 * Today we will 11 12 - Write a browser-based, interactive frontend app in Go 13 - Using myitcv.io/react, a wrapper around Facebook's React 14 - Learn to love `go`generate` 15 - Enjoy the benefits of writing frontend apps in Go, thereby solving many of the problems associated with using Javascript 16 - End up with teams of happy frontend Gophers 17 18 .image golang_uk/frontend_gopher.png 250 _ 19 20 21 * What do we mean by "frontend"? 22 23 For the purposes of this talk: 24 25 - A browser/equivalent (e.g. Electron) on a client device 26 - Rendering of HTML and CSS 27 - Backend could be local/remote/non-existent 28 29 30 * What do we mean by "interactive"? 31 32 For the purposes of this talk: 33 34 - Intra-page-load responsiveness 35 - Visual changes, i.e. re-rendering in response to user interactions 36 - May or may not involve backend calls; could be entirely frontend logic 37 38 39 * What do we mean by "app"? 40 41 For the purposes of this talk: 42 43 - HTML page/pages that are interactive 44 - Page `=>` a single page application - everything retrieved in a single page load 45 - Pages `=>` logic split across multiple pages (and hence page loads) 46 47 48 * Why is any of this important? 49 50 - Browser is an extremely good cross platform way of building frontend apps 51 - Billions of devices 52 - Zero cost to adoption 53 - Low cost from a development perspective (or should be at least!) 54 55 * Examples of interactive frontend apps 56 57 58 * 59 60 .iframe http://blog.myitcv.io/gopherjs_examples_sites/globalstate/?hideGithubRibbon=true 600 975 61 62 63 * 64 65 .iframe http://blog.myitcv.io/gopherjs_examples_sites/markdowneditor/?hideGithubRibbon=true 600 975 66 67 68 * 69 70 .iframe http://blog.myitcv.io/gopherjs_examples_sites/immtodoapp/?hideGithubRibbon=true 600 975 71 72 73 * 74 75 .iframe http://blog.myitcv.io/gopherize.me_site/?hideGithubRibbon=true 600 975 76 77 78 * 79 80 .iframe http://blog.myitcv.io/gopherjs_examples_sites/latency/?hideGithubRibbon=true 600 975 81 82 83 * How do we make HTML and CSS dynamic in this way? 84 85 DOM model represents a document with a logical tree. 86 87 Using Javascript we can then manipulate the DOM: 88 89 - add, change, and remove HTML elements and attributes 90 - change CSS styles 91 - react to existing events (e.g. mouse clicks, key press) 92 - create new events (e.g. timer events) 93 94 95 * Javascript? Really? 96 97 _“JavaScript_is_ubiquitous_on_the_web,_and_that’s_not_going_to_change_anytime_soon,_so_there’s_no_point_in_carrying_the_baggage_necessary_for_multiple_scripting_engines_that_never_materialized.”_ 98 99 A Mozilla maintainer, 2012. 100 101 102 * Javascript: the reality 103 104 - Javascript "won" the browser battle 105 - Easily picked up and learnt 106 - Standardised via ECMAScript 107 - `asm.js`, WebAssembly (possibly) represent tomorrow's world 108 109 110 * What's the option space for writing interactive frontend apps? 111 112 A very incomplete list: 113 114 - Javascript 115 - CoffeeScript (compiles to Javascript) 116 - Typescript (compiles to Javascript) 117 - ClojureScript (compiles to Javascript) 118 - Other languages that compile to Javascript/`asm.js`/WebAssembly 119 - ... 120 121 122 * A brief (incomplete) analysis of Typescript 123 124 - Typed superset of Javascript that compiles to Javascript 125 - Large language; extensive specification, more edge cases, harder to write tools that work with language 126 - Painful hangovers from Javascript 127 - Myriad compiler options to satisfy myriad backgrounds of newcomers 128 - Low development velocity 129 - No single-source-of-truth `gofmt` equivalent 130 131 132 * Is there another way? 133 134 - We want to write interactive frontend apps 135 - We *ultimately* have to use Javascript to do so 136 137 138 * 139 140 .image golang_uk/gophercolor.png 500 _ 141 142 .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]] 143 144 145 * GopherJS 146 147 * What is GopherJS? 148 149 - A compiler from Go to JavaScript 150 - Developed by Richard Musiol et al 151 - Principally targets the browser 152 153 154 155 * What does GopherJS support? 156 157 - Full language coverage, including goroutines 158 - Almost the entire standard library 159 - Performance is good in most cases 160 - Source map support (debugging) 161 - DOM package 162 - Javascript interoperability package 163 164 165 * React 166 167 168 * Why React? 169 170 _"A_Javascript_library_for_building_user_interfaces"_ 171 172 - Presents a nice abstraction of the DOM 173 - Makes you think in terms of components (reuse primitive) 174 - Pragmatic: doesn't mandate data or state patterns 175 - Widely used; existing Javascript components can be reused 176 177 178 * React Fundamentals 179 180 - Components - a description of what HTML/components we want to render via a `Render()` method 181 - Props - parameters to a component (optional) 182 - State - private to a component (optional) 183 - Virtual DOM 184 185 186 * Render() 187 188 - `Render()` is a function of a component's props and state 189 - Results in a hierarchy of component instances/HTML 190 191 .image golang_uk/react_component_tree.png 450 _ 192 193 194 * myitcv.io/react 195 196 * What is myitcv.io/react? 197 198 _Package_myitcv.io/react_is_a_set_of_GopherJS_bindings_for_Facebook's_React_ 199 200 - Wraps the Facebook-distributed React Javascript library 201 - Presents a Go-esque "interface" to declare components, props and state 202 - `reactGen`: a tool to initialise a new frontend app, but also a code generator as we declare our components, props and state 203 204 205 * Let's create a simple app 206 207 # The ubiquitous hello world 208 # 209 mkdir -p $GOPATH/src/example.com/helloworld && cd $_ 210 211 # Use the Boostrap template 212 # 213 reactGen -init bootstrap 214 215 216 * 217 218 .iframe http://blog.myitcv.io/gopherjs_examples_sites/helloworldbootstrap/ 600 975 219 220 * What did reactGen generate? 221 222 helloworld 223 ├── app.go 224 ├── gen_App_reactGen.go 225 ├── index.html 226 └── main.go 227 228 * index.html 229 230 Effectively the entry point for our app: 231 232 .code golang_uk/bootstrap_init/index.html 233 234 `helloworld.js` is the GopherJS compiled result of `example.com/helloworld` 235 236 237 * main.go 238 239 .code golang_uk/bootstrap_init/main.go 240 241 242 * app.go 243 244 .code golang_uk/bootstrap_init/app.go 245 246 247 * gen_App_reactGen.go 248 249 `gen_App_reactGen.go` is the result of `go`generate` seeing the directive: 250 251 //go:generate reactGen 252 253 `reactGen`: 254 255 - generates glue code between component, props and state declarations and the wrapped React library 256 - runs at the package level 257 - creates type-safe methods for accessing props and state in a component 258 - saves you writing lots of boilerplate code! 259 260 261 * go generate 262 263 .image golang_uk/go_generate.png _ 975 264 265 266 * Using a file watcher 267 268 .image golang_uk/go_generate_watch.png _ 975 269 270 e.g. `github.com/cespare/reflex` 271 272 273 * Writing our own React component 274 275 * A simple component: declaration 276 277 Components are defined as struct types with a `*Def` name suffix that embed `react.ComponentDef`: 278 279 import "myitcv.io/react" 280 281 // FooBarDef is the definition of the FooBar component. 282 // 283 type FooBarDef struct { 284 react.ComponentDef 285 } 286 287 288 * A simple component: props 289 290 The props type for a component use a corresponding `*Props` suffix: 291 292 // FooBarProps is the props type for the FooBar component. 293 // 294 type FooBarProps struct { 295 Name string 296 } 297 298 299 * A simple component: state 300 301 The state type for a component use a corresponding `*State` suffix: 302 303 // FooBarState is the state type for the FooBar component. 304 // 305 type FooBarState struct { 306 Age int 307 } 308 309 310 * What's reactGen done for us? 311 312 Amongst other things we now have some type-safe methods: 313 314 func (f FooBarDef) Props() FooBarProps 315 316 func (f FooBarDef) State() FooBarState 317 func (f FooBarDef) SetState(state FooBarState) 318 319 320 * A simple component: Render() 321 322 .code golang_uk/foo_bar/render.go 323 324 325 * A simple component: click handler 326 327 // ageClick implements the react.OnClick interface to handle when the "Bump age" button 328 // is clicked 329 // 330 type ageClick struct{ 331 FooBarDef 332 } 333 334 func (a ageClick) OnClick(e *react.SyntheticMouseEvent) { 335 s := a.State() 336 s.Age++ 337 a.SetState(s) 338 } 339 340 341 * A simple component: constructor function 342 343 This constructor function is our component's equivalent to, say, `react.Div(...)`: 344 345 // FooBar is the constructor for a FooBar component. 346 // 347 func FooBar(p FooBarProps) *FooBarElem { 348 return buildFooBarElem(p) 349 } 350 351 `buildFooBarElem()` is generated by `reactGen` 352 353 354 * Using our simple component 355 356 .code golang_uk/foo_bar/revised_app_render.go 357 358 359 The result? 360 361 * 362 363 .iframe http://blog.myitcv.io/gopherjs_examples_sites/blog/2017_04_16/ 600 975 364 365 366 * React dev tools work 367 368 .image golang_uk/foo_bar/react_tools.png _ 975 369 370 371 * 372 373 .iframe http://blog.myitcv.io/gopherize.me_site/?hideGithubRibbon=true 600 975 374 375 * gopherize.me React component hierarchy 376 377 .image golang_uk/gopherize.me_comps.png _ 975 378 379 380 * Backends for our frontend 381 382 383 * Where do we stand? 384 385 - Written an interactive frontend app in Go 386 - Used `myitcv.io/react` and `reactGen` to declare components, props and state 387 - A new found love for `go`generate` 388 - But no "data" in our application... 389 390 391 * Option space for backends 392 393 - No backend 394 - JSON/REST API 395 - Base64 encoded Protobuf 3 over HTTP 1.1 396 - gRPC over HTTP 2 397 - ... 398 399 You have (almost) the entire standard library at your disposal 400 401 402 * 403 404 .iframe https://grpcweb.jbrandhorst.com/ 600 975 405 406 407 * That's all Gophers 408 409 .image golang_uk/wrap.png 500 _ 410 411 * Credits and thanks 412 413 - [[https://github.com/neelance][Richard Musiol]], [[https://github.com/shurcooL][Dmitry Shuralyov]] and others in the GopherJS community 414 - [[https://twitter.com/lejatorn][Mathieu Lonjaret]] and [[https://twitter.com/bradfitz][Brad Fitzpatrick]] - [[https://camlistore.org/][Camlistore]] 415 - [[https://twitter.com/tjholowaychuk][TJ Holowaychuk]] 416 - [[https://twitter.com/JohanBrandhorst][Johan Brandhorst]] for his excellent work on gRPC-backend example 417 - [[https://twitter.com/ashleymcnamara][Ashley McNamara]] and [[https://twitter.com/matryer][Mat Ryer]] - [[https://gopherize.me/]] 418 419 420 * More details/getting started/etc 421 422 - [[https://github.com/myitcv/react/wiki][`myitcv.io/react` wiki]] 423 - [[http://blog.myitcv.io/][My blog]] 424 - [[https://gophers.slack.com/messages/gopherjs][GopherJS Slack Channel]] 425