Haxe London meetup slides presenting an alternative to ES6/TypeScript/Webpack using Haxe:
- Haxe React / React-router integration
- and reference architectures (Redux, MVC),
- demonstrating natural code splitting
- and Webpack-free hot-reload techniques.
1. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe React
architecture and workflow
2. typedef React = State -> View Haxe Meetup, 2 March 2017
Definition
• What Haxe is:
• Haxe is an open source toolkit based on a modern high level strictly typed
programming language, a state-of-the-art light-speed cross-compiler, a
complete cross-platform standard library, and ways to access to each
platform's native capabilities.
• What Haxe is NOT:
• Haxe is not a high level framework. It's a toolkit that can be used to build
cross-platform tools and frameworks.
3. typedef React = State -> View Haxe Meetup, 2 March 2017
Write or reuse?
• Massive.co has contributed many state of the art open-source
libraries for the Haxe language
• Unit testing, code coverage, MVC, dependency injection, event signals,…
• It is a big effort and responsibility to write and maintain OSS
4. typedef React = State -> View Haxe Meetup, 2 March 2017
Crossplatform or not?
• The Haxe language can target many platforms
• JavaScript, Flash, C++, C#, Java, Python, Lua, Php…
• We usually make sure to write dependency-free, universal, libraries
• But ultimately our business is focusing on HTML/JS
5. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe on JavaScript
• JavaScript is our VM – one of the fastest, most stable, and richest
• Other companies are building/maintaining very solid libraries
6. typedef React = State -> View Haxe Meetup, 2 March 2017
Why Haxe on JavaScript?
• JavaScript is predominantly ES6 and TypeScript nowadays
• Yet people (and companies) continue betting on other langs
• Dart, Elm, PureScript, ScalaJS, OcamlJS,…
• And we love Haxe because it’s faster, smarter and easy to learn
7. typedef React = State -> View Haxe Meetup, 2 March 2017
React on Haxe
• Most popular view-layer library
• No need for Facebook hatin’
• It’s opensource and well maintained
• and many companies contribute to creating
something much wider than its core
8. typedef React = State -> View Haxe Meetup, 2 March 2017
React on Haxe
• Building great Haxe support alone is a big effort
• Core library by Massive.co (@dpeek then @elsassph)
• https://github.com/massiveinteractive/haxe-react
• React-native and other externs by @kevinresol and @zabojad
• https://github.com/haxe-react
• https://github.com/tokomlabs/haxe-react-addons
9. typedef React = State -> View Haxe Meetup, 2 March 2017
First, understand JavaScript
• Learn how things work in vanilla
JavaScript first
• Play with React using ‘create-react-app’
10. typedef React = State -> View Haxe Meetup, 2 March 2017
First, understand JavaScript
• Anything you can do in JavaScript can be
expressed in Haxe (depending on how
dirty you’re willing to feel)
• For articles on Haxe-JS interop:
http://philippe.elsass.me
11. typedef React = State -> View Haxe Meetup, 2 March 2017
React
12. typedef React = State -> View Haxe Meetup, 2 March 2017
React JavaScript syntax
• XML in your JavaScript?
(heresy!)
• It’s called JSX
• It’s only metadata
13. typedef React = State -> View Haxe Meetup, 2 March 2017
React JavaScript syntax
14. typedef React = State -> View Haxe Meetup, 2 March 2017
React JavaScript syntax
• Fancy binding syntax (uni-directional)
15. typedef React = State -> View Haxe Meetup, 2 March 2017
React: all the cool kids are doing it
• React is a Virtual DOM engine from Facebook/Instagram
• Only view layer, not an architecture (unlike Angular)
• Straightforward and robust
• Not limited to HTML DOM – there are renderers for canvas, PixiJS…
• Not limited to the browser – react-native is maturing
16. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe-React
• Nearly as fancy, macro-powered, syntax
17. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe-React
• Supports the same binding syntax
18. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe-React
• Or Haxe string-interpolation syntax (advantage: completion)
19. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe-React
• Optimiser can generate inline objects at compile time in place of
React.createElement() calls for optimal performance
20. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe-React
• JSX parser is complete with a few minor limitations
• Generator supports all the advanced features* like spread operator,
default values or functional stateless components
• Optimiser does better than JS compilers
* React is feature rich, learn it properly
21. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: initial render
• Initial render in HTML
• Should be called only once, targeting a root DOM element
• Multiple roots allowed
22. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: initial render
• Without components, the rendered DOM will never change
23. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: initial render
• Only components are able to trigger re-renders
• A dynamic application will need at least one in the initial render
24. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: Component
• A component must have a render function returning one element.
25. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: Component
• Components can hold “state”; state changes schedule a re-render
26. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: Component
• Components can receive read-only “props” from their parent
27. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: Component
• A stateless component can be advantageously replaced by a function
28. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: avoid inheritance
• High-Order Component: extend other components
29. typedef React = State -> View Haxe Meetup, 2 March 2017
React basics: avoid inheritance
• Component wrapper with provided children elements
30. typedef React = State -> View Haxe Meetup, 2 March 2017
Advanced React: containing updates
• Warning: state changes can be costly!
• State changes schedule a re-render
• Children may re-render in depth, unless you prevent it:
• Carefully add ”key” attributes
• extend PureComponent
• override shouldComponentUpdate(nextProps, nextState):Bool
• Prevent re-render only if needed, and as early as possible
31. typedef React = State -> View Haxe Meetup, 2 March 2017
React: production-ready
• React works great, right now, it’s stable
and well supported. Enjoy.
• React’s approach is inspiring many
other frameworks, some using JSX.
• Haxe React is in serious shape and used
in large productions at Massive.
32. typedef React = State -> View Haxe Meetup, 2 March 2017
React architectures
33. typedef React = State -> View Haxe Meetup, 2 March 2017
Architecture
• React is just a view layer – it doesn’t enforce any architecture
• Basic props and callbacks don’t scale
• Haxe React comes with 2 examples: Redux and MMVC
34. typedef React = State -> View Haxe Meetup, 2 March 2017
Architecture: Redux
https://github.com/elsassph/haxe-react-redux
• Disclaimer: Redux is NOT an architecture itself
• Redux is a popular state library for Model-Intent architectures
• Sample follows one possible architecture pattern with Redux
• Warning: expect to do a lot of refactoring
35. typedef React = State -> View Haxe Meetup, 2 March 2017
Architecture: MVC
https://github.com/elsassph/haxe-react-mmvc
• Massive’s MMVC offers a battle-tested architecture inspired by
RobotLegs, used on large scale, large complexity applications
• Macro-based Dependency Injection, Command and View mediation
• MMVC fits naturally with React Components: just add an interface
36. typedef React = State -> View Haxe Meetup, 2 March 2017
Advanced React : the “context”
• Architecturing React apps requires more than “props”
• Libraries and framework need to provide data to any child
• This mechanism is the React “context”
• Recommendation: do not use this “context” liberally
37. typedef React = State -> View Haxe Meetup, 2 March 2017
Advanced React : the “context”
• This mechanism should be used through black boxes:
• “Provider” React components inject values in context
• “Consumer” React components query those values
• Examples of uses:
• Redux: components need to access the store
• MMVC: components mediation
• React-router: components need to trigger navigation
38. typedef React = State -> View Haxe Meetup, 2 March 2017
Code splitting
To reduce the initial payload
To load features on-demand
39. typedef React = State -> View Haxe Meetup, 2 March 2017
Code splitting
• Haxe compiler historically outputs a single, optimized, JS file
• Traditional JavaScript do concat and minify JS files into one
• Problem: single big JS bundle = bad user experience
40. typedef React = State -> View Haxe Meetup, 2 March 2017
Code splitting
• Modern JavaScript has embraced the
multi-file approach and figured:
• Bundling with code splitting
• Hot module replacement during development
• Can we benefit from that in Haxe?
41. typedef React = State -> View Haxe Meetup, 2 March 2017
Modular JS
https://github.com/*/modular-js
Goal: comply with JavaScript bundlers
42. typedef React = State -> View Haxe Meetup, 2 March 2017
Modular JS
• Create one JS file for each Haxe class
• Then use a JavaScript bundler as with regular JS (profit!)
• Risks:
• Experimental with multiple approaches/forks
• Custom JavaScript generator
• No sourcemaps
• Requires excellent understanding of JS bundlers
• Unclear code-splitting strategy (and no project examples)
43. typedef React = State -> View Haxe Meetup, 2 March 2017
Modular JS - AMD
• Asynchronous module system (RequireJS)
• https://github.com/explorigin/modular-js (creator, unmaintained)
• https://github.com/jcward/modular-js (used in production)
• Bundlers: SystemJS, Webpack
44. typedef React = State -> View Haxe Meetup, 2 March 2017
Modular JS - CommonJS
• As popularized by nodejs, used by ES6/TypeScript
• https://github.com/kevinresol/modular-js
• https://github.com/MatthijsKamstra/modular-js (fork)
• Bundlers: SystemJS, Webpack, Browserify
45. typedef React = State -> View Haxe Meetup, 2 March 2017
Modular JS – Why choose it?
• Modular-js is a sensible choice if you’re 100% going JS.
• But it requires you to become an expert in Haxe JS output, the custom JS
generator, JS in general, and your JS bundler of choice.
• Competes with Haxe Modular
46. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular
https://github.com/elsassph/haxe-modular
Goal: staying true to Haxe
47. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular – Goals
https://github.com/elsassph/haxe-modular
• Use (tweak) regular Haxe compiler output
• No JS bundler dependency (but could)
• Adaptable to other Haxe targets
48. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular – The promise
https://github.com/elsassph/haxe-modular
• Automatically split monolithic Haxe JS (and sourcemap!) output
• Hot-reload capable (React reload built-in)
• Bundle NPM dependencies together separately
• Will be used in production at Massive
• Risks:
• Experimental
49. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular – Usage
• Explicitly load a components on demand:
• The class (and its dependencies) will be loaded (once) asynchronously when
requested
50. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular – Usage
• With React-router:
• The view class (and its dependencies) will be loaded (once) when navigating
to a specific “route”
51. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe Modular – How?
• Bundle.load(classRef) or RouteBundle.load(classRef) are macros
• classRef is memorised and code replaced by Require.load(bundleId)
• Normal Haxe JS output is sent to a temp file to be processed post-build
55. typedef React = State -> View Haxe Meetup, 2 March 2017
HMR
Hot Module Replacement
aka Hot Reload, Live Reload,…
56. typedef React = State -> View Haxe Meetup, 2 March 2017
Hot Module Replacement – What?
• Server monitors local files
• Client has socket connection to server
• Server send changes to client
• Client reloads files in a smart way
57. typedef React = State -> View Haxe Meetup, 2 March 2017
Hot Module Replacement – What?
• Not rocket science
• Requires app code to be broken into reloadable chunks
58. typedef React = State -> View Haxe Meetup, 2 March 2017
Hot Module Replacement – How?
• Must have feature; makes or breaks JS bundlers and frameworks
• Reload code but also assets, like images and CSS.
• It’s not magic: the application needs special logic to handle changes
and refresh itself
59. typedef React = State -> View Haxe Meetup, 2 March 2017
Haxe + React + Hot reload
Hinweis der Redaktion
It’s difficult to maintain all we made opensource
It’s difficult to maintain all we made opensource
We don’t want to write everything ourselves again
(we’ll get back to the packages later)
Reinventing something like React or Vue is a fulltime job
It’s good to try “vanilla” in case something weird happens
This doesn’t create any components! It’s only metadata.
It has a cost, every render call will create all these objects which will be compared with the existing DOM
Braces can contain any Haxe expression
Babel offers only a more optimized function. Netflix is experimenting with post-compilation optimizer with serious limitations.
React is suitable for progressive conversion of regular JS apps to React: components/screens can be progressively converted
This will be fully static DOM
React-native has a similar approach but you basically have to provide a root component class reference
Mutating this.state is not allowed.
The state property can be strongly typed.
Think XML attributes == JSX props
Each time a parent renders, the child will re-render with the new props
Props can be strongly typed.
Props become an argument instead of being a class field
Don’t use inheritance in React Components, use composition.
This HOC could be stateful or a simple stateless function component.
When providing children elements to a component, it will receive props.children
React tries to prevent useless re-renders but you often have to be explicit
PureComponent does a shallow comparison of the state and props
Haxe React could be adapted to other libraries but it’s not in our short term plans yet.
Admittedly we are only introducing Haxe JSX in production.
Here’s the plan
You can go framework-less but it will quickly become a mess
Redux is extremely inspiring, even used in Angular projects
Good React architectures need a better backbone than props
It’s like a Service Provider pattern
Practices have evolved in the JS world and Haxe compiler team is considering to support it.
Custom generator is flexible but high-maintenance, ideally should be built-in the compiler
Crazy.
Futuristic approach to fully blend in the JS ecosystem
Incompatible (I think) with Babel – the reference JS processor
Compatible with Babel.
Risk is still lower than modular-js: normal Haxe compiler with light patch
Risk is still lower than modular-js: normal Haxe compiler with light patch
Again: using this syntax will automatically split the output to extract this feature as an async
React-router require a specific syntax for asynchronous routes – this API returns a function that can be called to load the module
Require.load is a direct API to load a JS module asynchronously. You can load any JS file in the global context with it.
Each JS look like a regular Haxe output with a little bit of wiring code to allow scopes to join.
Analysis and generation run on node.js, leveraging very powerful JS libs. It can process over 2Mbs of JS output in 1.5s on my small ultrabook.
Reloading some parts of your application code without refreshing your browser.
It’s relatively easy to reload CSS or static images – just need a small client-side code to handle asset updates
This has made Webpack the king of JS bundlers, even if others are catching up