[UPDATE: Added links to slides for some of the talks]
ClojureScript is my new toy, so I was glad to see the San Francisco ClojureScript Meetup plan a new event, and all of the talks were about Om, which made it even better. It was a great event at Etsy’s SF office. Thanks to Melissa and Sean Grove for organizing it!
Here are my notes:
- http://www.meetup.com/SF-Clojurescript-Meetup/events/201007552/
- Official Meetup Hashtag: #sfcljs – https://twitter.com/search?q=%23sfcljs
- Etsy (host) is hiring: https://www.etsy.com/careers/
- Diogo
- Slides: http://htmlpreview.github.io/?https://github.com/diogo149/om-no/blob/master/notes.html
- Project: Social network with data mining, in stealth
- switched from Om to Reagent
- hit a wall after 5k+ LOC, months
- What was good about Om
- Global undo – really easy, but didn’t apply to the app
- One atom to contain global app state
- The Bad
- reify and build/build-all was error prone – you have to keep straight which fns return reified functions and which are normal
- API is verbose
- he built syntactic sugar for it, but that shows weakness with API
- Too slow – much slower than Angular JS
- No anonymous fns as components
- didn’t throw error messages, just re-mounted and caused site to flicker
- Can’t compose components, because components track their parent
- Cursors – pointers into app state
- async transact! can change the value or order of the app state, making the cursor point to the wrong data
- Local state mixed with global state
- you can’t wholesale replace new app state, b/c you don’t know where it’s mixed with local state that you would lose
- cursors behave like maps
- you can pass maps like cursors, except for when you want to transact!
- Need to Know principle
- In React, components work best when they know as little as possible, so they don’t re-render for unnecessary changes
- In Om, app state is a tree, so you need knowledge of lowest common ancestor
- same data in multiple places
- hard to be both consistent and performant
- Reagent
- principle of least surprise
- more Clojure-y – lazy components, normal functions,
- data model works better with React.js
- easier to work with data as a direct acyclic graph
- We were able to teach a new employee the codebase without knowledge of app or Reagent – testament of a good API
- Simpler for small apps, more scaleable for large apps
- Reagent – https://github.com/holmsand/reagent
- Anton – http://textik.com/
- Slides: http://www.slideshare.net/AntonAstashov/textik
- ASCII diagram generator
- Pet project, so he needed something he could build in an hour a day
- Normal design of front-end web apps
- observe changes in view models by any other observer models, sometimes cascading
- Works well, but hard to figure out what happened in exception
- Many inputs, many code paths
- Prefer one-way flow of events → data → rendering → events
- One global code path
- Full state of the app when exceptions happen
- Like React for fast view layer, use Quiescent for cljs
- lightweight, ~200 LOC
- Simple
- Opinionless
- Cons
- slowly developing – few recent commits, pending pull requests
- you have to maintain your own fork for e.g. animations
- Has bugs that are fixed in Om
- Lifecycle
- Init – call Render
- View – render, register event handlers that send payload to core.async channel
- core.async used b/c you can’t have circular dependencies on namespaces, since view would require dispatch and vice versa
- Dispatch – listen to channel, call mutators, call render
- Mutators – change data (only layer where data is changed)
- Data → return to Dispatch
- Code – https://github.com/astashov/tixi
- Minimal app using Quiescent, this architecture – https://github.com/astashov/mintik
- Quiescent – https://github.com/levand/quiescent
- Danny from CircleCI – Om From a Designer’s Point of View
- Does not like writing Om, but likes how everything is in one language, so it’s easier to reason about (vs HAML, CoffeeScript, CSS, etc)
- Can be harder to find where the data is coming from
- Only sort of gets the lifecycle, design of components
- Learning is coming faster than expected
- Workflow + tools are the same except for a ~10sec delay when making changes
- Using production data, and has to use the whitespace compiler to produce a single Javascript file
- Sublime, Chrome Dev tools, etc
- This is not a natural tool for a designer – most would need someone to help with the more programmery/Clojure-y stuff
- Syntax for Hiccup etc isn’t a big change from HTML/CSS
- Could use a more applicable cheat sheet for designers
- Uses CSS or SVG animations
- Surprised by React making assumptions/transformations on markup – e.g. moving an anchor to be a sibling of inline tag, from inside of it
- Design process would be easier if he ran a local dev environment, but that’s a big new dependency that requires maintenance
- Daniel from CircleCI – Converting a Site from Knockout to Om
- Can now use CircleCI for open source projects – free container, public build pages
- Open sourced front-end code: https://github.com/circleci/frontend
- You connect to your own CircleCI backend data, so you can push changes/fixes to be merged into the main, public repo, while protecting your data
- Still working out details of the open source workflow
- (this was more showing code than presentation)
- Old site used Knockout.js, 2-way data binding
- data binding in JS, HAML-coffee templates in CoffeeScript, etc, so there were language mismatches, string interpolation
- Converter from HAML-coffee to Hiccup – not perfect, but close enough
- Difference between whitespace automatically included vs required
- Event handlers put messages into core.async channels
- Took about 2.5 months full time development to convert
- How it works
- All state is serializable in a single Atom
- Build messages – something we know about the build that we want to tell you (~100 messages)
- Gave a representative sample of serialized state to designer
- In theory you can store and replay messages to rebuild state
- core.async – e.g. Stripe checkout – complete/cancel puts message into channel, and the page blocks on that
- Problems with Om
- haven’t figured out testing, still just using webdriver tests
- Rendering too much to the virtual DOM – parents have to know about child data, even if they don’t need it
- hasn’t been too big a problem yet
- Slow enough that you can drop characters on input, because of how much rendering goes on when everything is in global app state
- More of a problem in tests
- Needed to pull input data out of app state and into local component state