CodeFest 2019. Florian Rival (Facebook) — Beyond Web-Apps: WebAssembly, JS and React to rewrite native apps

16b6c87229eaf58768d25ed7b2bbbf52?s=47 CodeFest
April 08, 2019

CodeFest 2019. Florian Rival (Facebook) — Beyond Web-Apps: WebAssembly, JS and React to rewrite native apps

Can we port an existing native desktop application to a complete «JS powered» web-app matching (or even exceeding) the quality of the legacy desktop app? Sounds like a good challenge! This is what I decided to do with my game making software. Let’s see how web technologies and the JavaScript ecosystem can help. Spoiler alert: At the end, it works.

16b6c87229eaf58768d25ed7b2bbbf52?s=128

CodeFest

April 08, 2019
Tweet

Transcript

  1. Native Native Web Web Apps Apps React and WebAssembly to

    Rewrite Native Apps @FlorianRival1
  2. Since a long time 2

  3. I ❤ apps I ❤ apps Since a long time

    2
  4. 3

  5. “ open-source, cross-platform game creator designed to be used by

    everyone 3
  6. “ open-source, cross-platform game creator designed to be used by

    everyone An editor for games 3
  7. “ open-source, cross-platform game creator designed to be used by

    everyone An editor for games Visual programming 3
  8. “ open-source, cross-platform game creator designed to be used by

    everyone An editor for games Visual programming Output HTML5 games 3
  9. 4

  10. 5

  11. 6

  12. The editor is getting old The editor is getting old

    7
  13. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. 7
  14. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) 7
  15. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) Building UI is slow... 7
  16. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) Building UI is slow... ...and limited to old UI components... 7
  17. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) Building UI is slow... ...and limited to old UI components... ...and UX would need some enhancements 7
  18. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) Building UI is slow... ...and limited to old UI components... ...and UX would need some enhancements The entry barrier for new contributors is high (C++ ) 7
  19. The editor is getting old The editor is getting old

    Lots of cross-platforms issues with the UI toolkit, support for macOS and Linux is bad. Iterating on the software is slow (C++ ) Building UI is slow... ...and limited to old UI components... ...and UX would need some enhancements The entry barrier for new contributors is high (C++ ) It's time to react! It's time to react! 7
  20. Could web Could web technologies help? technologies help? 8

  21. “ React is perfect for React is perfect for making

    complex UI making complex UI 9 . 1
  22. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... 9 . 1
  23. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have 9 . 1
  24. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, 9 . 1
  25. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, dynamic panels, dynamic panels, 9 . 1
  26. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, dynamic panels, dynamic panels, 2d/3d visualizations 2d/3d visualizations 9 . 1
  27. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, dynamic panels, dynamic panels, 2d/3d visualizations 2d/3d visualizations, nested , nested dialogs, dialogs, 9 . 1
  28. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, dynamic panels, dynamic panels, 2d/3d visualizations 2d/3d visualizations, nested , nested dialogs, dialogs, drag'n'drop, search, drag'n'drop, search, 9 . 1
  29. “ React is perfect for React is perfect for making

    complex UI making complex UI Well, really?... Well, really?... Can we have Can we have list and trees of hundreds of list and trees of hundreds of elements, elements, dynamic panels, dynamic panels, 2d/3d visualizations 2d/3d visualizations, nested , nested dialogs, dialogs, drag'n'drop, search, drag'n'drop, search, 9 . 1
  30. color pickers, tabs, file trees, color pickers, tabs, file trees,

    a "real app" feeling a "real app" feeling, copy- , copy- paste things paste things, handle key- , handle key- board shortcuts board shortcuts , display , display and edit code in a rich editor and edit code in a rich editor show charts... show charts... 9 . 2
  31. color pickers, tabs, file trees, color pickers, tabs, file trees,

    a "real app" feeling a "real app" feeling, copy- , copy- paste things paste things, handle key- , handle key- board shortcuts board shortcuts , display , display and edit code in a rich editor and edit code in a rich editor show charts... show charts... Can we make ambitious Can we make ambitious apps? apps? 9 . 2
  32. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications 10
  33. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... 10
  34. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... what if we what if we 10
  35. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... what if we what if we already have a native already have a native codebase? codebase? 10
  36. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... what if we what if we already have a native already have a native codebase? codebase? Or have advanced Or have advanced 10
  37. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... what if we what if we already have a native already have a native codebase? codebase? Or have advanced Or have advanced simulations/computations, simulations/computations, 10
  38. “ JavaScript is perfect for JavaScript is perfect for most

    applications most applications Well, really?... Well, really?... what if we what if we already have a native already have a native codebase? codebase? Or have advanced Or have advanced simulations/computations, simulations/computations, or need consistent perfs? or need consistent perfs? 10
  39. X-platform toolkit (wxWidgets) GDevelop C++ codebase GDevelop C++ codebase 11

  40. X-platform toolkit (wxWidgets) GDevelop C++ codebase GDevelop C++ codebase Core

    classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler")
  41. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem GDevelop C++ codebase

    GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler")
  42. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    GDevelop C++ codebase GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler")
  43. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler")
  44. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler")
  45. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler") libGDevelop.js
  46. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase GDevelop C++ codebase Core classes (game, scene, object, textures...) 11 Game exporter (JS "transpiler") libGDevelop.js GDevelop JS codebase
  47. 12

  48. 13

  49. Writing WebAssembly Writing WebAssembly 14 . 1

  50. Writing WebAssembly Writing WebAssembly 14 . 1

  51. Writing WebAssembly Writing WebAssembly 14 . 1

  52. Writing WebAssembly Writing WebAssembly 14 . 1

  53. explained 14 . 2

  54. explained 14 . 2

  55. LLVM IR (bitcode) explained 14 . 2

  56. LLVM IR (bitcode) explained 14 . 2

  57. LLVM IR (bitcode) explained 14 . 2

  58. Using Emscripten Using Emscripten git clone https://github.com/emscripten-core/emsdk.git cd emsdk &&

    ./emsdk install latest && ./emsdk activate latest ./emcc tests/hello_world.c node a.out.js For large projects, Emscripten provides replacements that swap GCC or Clang by Emscripten in build system (automake, CMake...) 15
  59. Expose existing classes Expose existing classes 16

  60. Expose existing classes Expose existing classes class ObjectsContainer { Object&

    InsertObject(const Object& object, size_t position) { ... }; Object& GetObject(const gd::String& name) { ... }; } class Layout : public ObjectsContainer { public: void setName(const gd::String & name_) { name = name_; }; const gd::String & getName() { return name; }; // ... } 16
  61. Expose existing classes Expose existing classes class ObjectsContainer { Object&

    InsertObject(const Object& object, size_t position) { ... }; Object& GetObject(const gd::String& name) { ... }; } class Layout : public ObjectsContainer { public: void setName(const gd::String & name_) { name = name_; }; const gd::String & getName() { return name; }; // ... } interface Layout { void setName([Const] DOMString name); [Const, Ref] DOMString getName(); // Inherited from ObjectsContainer [Ref] Object insertObject([Ref] gdObject object, unsigned long pos); [Ref] Object getObject([Const] DOMString name); } "WebIDL" bindings for Emscripten WebIDL binder: 16
  62. Use Emscripten classes Use Emscripten classes 17

  63. Use Emscripten classes Use Emscripten classes Module().then(gd => { const

    layout = new gd.Layout(); layout.setName("My game level"); const object = new gd.Object(); object.setName("My character"); layout.insertObject(object, 0); console.log(layout.getName()); // "My game level" console.log(object.getObject("My character")); // Returns a gd.Object }); 17
  64. Use Emscripten classes Use Emscripten classes Module().then(gd => { const

    layout = new gd.Layout(); layout.setName("My game level"); const object = new gd.Object(); object.setName("My character"); layout.insertObject(object, 0); console.log(layout.getName()); // "My game level" console.log(object.getObject("My character")); // Returns a gd.Object }); Converted, including JS strings (to char*) Primitive types? 17
  65. Use Emscripten classes Use Emscripten classes Module().then(gd => { const

    layout = new gd.Layout(); layout.setName("My game level"); const object = new gd.Object(); object.setName("My character"); layout.insertObject(object, 0); console.log(layout.getName()); // "My game level" console.log(object.getObject("My character")); // Returns a gd.Object }); Converted, including JS strings (to char*) Primitive types? If I pass an object? Objects references are converted to pointers (or references) by the webIDL generated glue code 17
  66. Use Emscripten classes Use Emscripten classes Module().then(gd => { const

    layout = new gd.Layout(); layout.setName("My game level"); const object = new gd.Object(); object.setName("My character"); layout.insertObject(object, 0); console.log(layout.getName()); // "My game level" console.log(object.getObject("My character")); // Returns a gd.Object }); Converted, including JS strings (to char*) Primitive types? If I pass an object? std::iostream is binded to console.log Objects references are converted to pointers (or references) by the webIDL generated glue code Can I debug? 17
  67. 18

  68. Things to know Things to know 19

  69. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! 19
  70. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } 19
  71. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } Wasm memory 19
  72. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } Wasm memory 19
  73. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  74. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  75. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  76. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! For React: console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  77. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! For React: componentDidMount() { this._project = new gd.Project(); } componentWillUnmount() { gd.destroy(this._project); } console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  78. Things to know Things to know const layout = new

    gd.Layout(); // ... gd.destroy(layout); // Binded objects need manual destruction Memory management requires care! For React: componentDidMount() { this._project = new gd.Project(); } componentWillUnmount() { gd.destroy(this._project); } or use an Effect Hook console.log(layout); // { ptr: 6804120 } Wasm memory The content of gd.Layout 19
  79. Things to know (2) Things to know (2) 20

  80. Things to know (2) Things to know (2) Output files

    can be large (~3mb for GDevelop), but Output files can be large (~3mb for GDevelop), but gzip helps. gzip helps. 20
  81. Things to know (3) Things to know (3) 21

  82. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. 21
  83. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. abort(16). Build with -s ASSERTIONS=1 for more info. 21
  84. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. abort(16). Build with -s ASSERTIONS=1 for more info. What can go wrong? 21
  85. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. abort(16). Build with -s ASSERTIONS=1 for more info. Wrong type for a parameter What can go wrong? 21
  86. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. abort(16). Build with -s ASSERTIONS=1 for more info. Wrong type for a parameter Parameter forgotten What can go wrong? 21
  87. Things to know (3) Things to know (3) A complete

    test set is invaluable for ensuring that no errors are in the bindings. abort(16). Build with -s ASSERTIONS=1 for more info. Wrong type for a parameter Parameter forgotten Using a deleted object What can go wrong? 21
  88. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 22 GDevelop JS codebase
  89. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 22 GDevelop JS codebase
  90. Creating a complex UI? Creating a complex UI? 23

  91. Find a component library Find a component library 24

  92. Find a component library Find a component library Extensive list

    of high quality components 24
  93. Find a component library Find a component library Extensive list

    of high quality components Good theming support 24
  94. Find a component library Find a component library Extensive list

    of high quality components Good theming support Accessibility 24
  95. Find a component library Find a component library Extensive list

    of high quality components Good theming support Accessibility Documentation quality 24
  96. Large lists (with drag'n'drop) Large lists (with drag'n'drop) 25

  97. Virtualized lists Virtualized lists 26

  98. Virtualized lists Virtualized lists react-sortable-hoc react-virtualized 26

  99. Virtualized lists Virtualized lists const ObjectRow = () => <div>...</div>;

    const ObjectsList = (props) => props.map(group => <ObjectRow ... />) react-sortable-hoc react-virtualized 26
  100. Virtualized lists Virtualized lists const ObjectRow = () => <div>...</div>;

    const ObjectsList = (props) => props.map(group => <ObjectRow ... />) const SortableObjectRow = SortableElement(props => ( <ObjectRow ... /> )); const ObjectsList = (props) => ( <List rowRenderer={({ ... }) => { <SortableObjectRow /> }) /> ); const SortableObjectsList = SortableContainer(ObjectsList); <SortableObjectsList onSortEnd={({ oldIndex, newIndex }) => ...} ... react-sortable-hoc react-virtualized 26
  101. Panels/resizable editors Panels/resizable editors 27

  102. Use a Use a tiling window library tiling window library

    28
  103. react-mosaic Use a Use a tiling window library tiling window

    library 28
  104. Large trees (with drag'n'drop) Large trees (with drag'n'drop) 29

  105. Virtualization again! Virtualization again! 30

  106. Virtualization again! Virtualization again! react-sortable-tree 30

  107. Levels rendering or visualizations Levels rendering or visualizations 31

  108. Forget the DOM Forget the DOM 32

  109. Forget the DOM Forget the DOM 32

  110. Forget the DOM Forget the DOM 32

  111. Don't forget the DOM Don't forget the DOM 33

  112. Don't forget the DOM Don't forget the DOM 33

  113. Don't forget the DOM Don't forget the DOM <svg onPointerMove={...}

    onPointerUp={...} width={this.props.imageWidth} height={this.props.imageHeight} > <polygon fill="rgba(255,0,0,0.2)" stroke="rgba(255,0,0,0.5)" fileRule="evenodd" points={vertices.map(vertex => `${vertex.getX()},${vertex.getY()}` ).join(' ')} /> {vertices.map((vertex, j) => ( <circle onPointerDown={...} key={`vertex-${j}`} fill="rgba(255,0,0,0.75)" cx={vertex.getX()} cy={vertex.getY()} r={5} /> ))} </svg> 33
  114. When things aren't fast enough When things aren't fast enough

    34
  115. Profile the rendering Profile the rendering 35

  116. Profile the rendering Profile the rendering 35

  117. Profile the rendering Profile the rendering shouldComponentUpdate/memoization is often the

    answer 35
  118. Profile the rendering Profile the rendering shouldComponentUpdate/memoization is often the

    answer Measure performance in production (React development build is way slower) 35
  119. Inspect calls to WebAssembly Inspect calls to WebAssembly 36

  120. Inspect calls to WebAssembly Inspect calls to WebAssembly Beware of

    overhead in binding code/wasm call when calling functions, in particular if renderings 36
  121. Inspect calls to WebAssembly Inspect calls to WebAssembly Beware of

    overhead in binding code/wasm call when calling functions, in particular if renderings objects.filter(object => object.getType() !== "") // N wasm calls + string conversion .map(object => object.getVariables(project)); // N wasm calls + string conversion Won't be noticeable in most UI situations, but can be if used in renderings or long lists/trees 36
  122. Inspect calls to WebAssembly Inspect calls to WebAssembly Beware of

    overhead in binding code/wasm call when calling functions, in particular if renderings objects.filter(object => object.getType() !== "") // N wasm calls + string conversion .map(object => object.getVariables(project)); // N wasm calls + string conversion Won't be noticeable in most UI situations, but can be if used in renderings or long lists/trees It might be useful to store strings/values on the JS side if you know they won't change. 36
  123. When your codebase is growing When your codebase is growing

    37
  124. Stick to your components Stick to your components 38

  125. Stick to your components Stick to your components <FlatButton> Help

    </FlatButton> ☺ ☺ 38
  126. Stick to your components Stick to your components <FlatButton style={{fontSize:

    12}}> Help </FlatButton> <FlatButton> Help </FlatButton> ☺ ☺ Avoid custom/adhoc styles, that won't scale: 38
  127. Stick to your components Stick to your components <FlatButton style={{fontSize:

    12}}> Help </FlatButton> <FlatButton> Help </FlatButton> ☺ ☺ <HelpButton /> Avoid custom/adhoc styles, that won't scale: Make a component for it! #DesignSystem 38
  128. Don't unit test your visual Don't unit test your visual

    components... components... 39
  129. Don't unit test your visual Don't unit test your visual

    components... components... Well actually, do, but only for part where there Well actually, do, but only for part where there is is logic logic 39
  130. ...but create visual stories ...but create visual stories 40

  131. ...but create visual stories ...but create visual stories Storybook React

    Styleguidist 40
  132. Use types Use types 41

  133. Use types Use types Flow Typescript 41

  134. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript 41
  135. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript Help auto-completion Help auto-completion 41
  136. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript Help auto-completion Help auto-completion Avoid most silly (or not so silly) mistakes Avoid most silly (or not so silly) mistakes 41
  137. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript Help auto-completion Help auto-completion Avoid most silly (or not so silly) mistakes Avoid most silly (or not so silly) mistakes Help to "document" your objects Help to "document" your objects 41
  138. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript Help auto-completion Help auto-completion Avoid most silly (or not so silly) mistakes Avoid most silly (or not so silly) mistakes Help to "document" your objects Help to "document" your objects ... all of these which becomes really useful when you're back on some module you (or someone else) wrote a few months ago 41
  139. Use types Use types Will tell you that you (or

    someone else) forgot to Will tell you that you (or someone else) forgot to pass/remove a prop pass/remove a prop Flow Typescript Help auto-completion Help auto-completion Avoid most silly (or not so silly) mistakes Avoid most silly (or not so silly) mistakes Help to "document" your objects Help to "document" your objects ... all of these which becomes really useful when you're back on some module you (or someone else) wrote a few months ago Types shine when you or someone else is refactoring some parts of the app 41
  140. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 42 GDevelop JS codebase
  141. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 42 GDevelop JS codebase
  142. Consider your packaging options Consider your packaging options 43

  143. Consider your packaging options Consider your packaging options Web app

    Squoosh.app 43
  144. Consider your packaging options Consider your packaging options GDevelop Electron

    Web app Squoosh.app 43
  145. Consider your packaging options Consider your packaging options GDevelop Electron

    Web app Embed in a native app Squoosh.app Spotify Steam Chat 43
  146. Build over Electron APIs Build over Electron APIs 44

  147. Build over Electron APIs Build over Electron APIs class MaterialUIContextMenu

    extends React.Component { ... } class ElectronContextMenu extends React.Component { ... } 44
  148. Build over Electron APIs Build over Electron APIs class MaterialUIContextMenu

    extends React.Component { ... } class ElectronContextMenu extends React.Component { ... } export default class MaterialUIMenuImplementation { buildFromTemplate(template) { return template.map((item, id) => { if (item.type === 'separator') { return <Divider key={'separator' + id} />; } else if (item.type === 'checkbox') { return ( <MenuItem ... /> } else { return ( <MenuItem ... /> } } showMenu() { ... } } 44
  149. Build over Electron APIs Build over Electron APIs export default

    class ElectronMenuImplementation { buildFromTemplate(template) { this.menuTemplate = template; return undefined; } showMenu(dimensions) { if (!electron) return; const { Menu } = electron.remote; const browserWindow = electron.remote.getCurrentWindow(); this.menu = Menu.buildFromTemplate(this.menuTemplate); this.menu.popup({ window: browserWindow, x: Math.round(dimensions.left), y: Math.round(dimensions.top + dimensions.height), async: true, // Ensure the UI is not blocked on macOS. }); } } class MaterialUIContextMenu extends React.Component { ... } class ElectronContextMenu extends React.Component { ... } export default class MaterialUIMenuImplementation { buildFromTemplate(template) { return template.map((item, id) => { if (item.type === 'separator') { return <Divider key={'separator' + id} />; } else if (item.type === 'checkbox') { return ( <MenuItem ... /> } else { return ( <MenuItem ... /> } } showMenu() { ... } } 44
  150. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 45 GDevelop JS codebase
  151. X-platform toolkit (wxWidgets) GUI (windows, dialogs...) Filesystem React.js powered interface

    Node.js/browser adapters GDevelop C++ codebase Core classes (game, scene, object, textures...) Game exporter (JS "transpiler") libGDevelop.js 45 GDevelop JS codebase Result? Result?
  152. 46

  153. What are users saying? What are users saying? 47

  154. What are users saying? What are users saying? “ Wow,

    what a difference a year can make 47
  155. What are users saying? What are users saying? “ Wow,

    what a difference a year can make “ Amazing how much easier and streamlined the engine has become 47
  156. What are users saying? What are users saying? “ Wow,

    what a difference a year can make “ but I have to admit, once you worked a bit with it, it could be really more productive on many aspects than GD4 “ Amazing how much easier and streamlined the engine has become 47
  157. What are users saying? What are users saying? “ Wow,

    what a difference a year can make “ but I have to admit, once you worked a bit with it, it could be really more productive on many aspects than GD4 “ Amazing how much easier and streamlined the engine has become It works! It works! 47
  158. “ The The native web app native web app is

    is better better than the native app than the native app 48
  159. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, 48
  160. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook) 48
  161. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform 48
  162. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform, faster , faster startup time startup time 48
  163. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform, faster , faster startup time startup time, auto updates, , auto updates, 48
  164. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform, faster , faster startup time startup time, auto updates, , auto updates, more contributors, more contributors, 48
  165. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform, faster , faster startup time startup time, auto updates, , auto updates, more contributors, more contributors, "try it "try it online", online", 48
  166. “ The The native web app native web app is

    is better better than the native app than the native app Ultra fast iterations, Ultra fast iterations, ultra ultra fast testing (storybook) fast testing (storybook), near , near perfect cross-platform perfect cross-platform, faster , faster startup time startup time, auto updates, , auto updates, more contributors, more contributors, "try it "try it online", online", tablets/phones port tablets/phones port 48
  167. @FlorianRival @FlorianRival gdevelop-app.com gdevelop-app.com github.com/4ian/GDevelop github.com/4ian/GDevelop Ping me Ping me

    Check GD Check GD 49
  168. Thanks! ☺ Thanks! ☺ @FlorianRival @FlorianRival gdevelop-app.com gdevelop-app.com github.com/4ian/GDevelop github.com/4ian/GDevelop

    Ping me Ping me Check GD Check GD 49