Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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.

CodeFest

April 08, 2019
Tweet

More Decks by CodeFest

Other Decks in Technology

Transcript

  1. Native
    Native Web
    Web Apps
    Apps
    React and WebAssembly to Rewrite Native
    Apps
    @FlorianRival1

    View Slide

  2. Since a long time
    2

    View Slide

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

    View Slide

  4. 3

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  9. 4

    View Slide

  10. 5

    View Slide

  11. 6

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  20. Could web
    Could web
    technologies help?
    technologies help?
    8

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  39. X-platform toolkit (wxWidgets)
    GDevelop C++ codebase
    GDevelop C++ codebase
    11

    View Slide

  40. X-platform toolkit (wxWidgets)
    GDevelop C++ codebase
    GDevelop C++ codebase
    Core classes (game,
    scene, object,
    textures...)
    11
    Game exporter (JS
    "transpiler")

    View Slide

  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")

    View Slide

  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")

    View Slide

  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")

    View Slide

  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")

    View Slide

  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

    View Slide

  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

    View Slide

  47. 12

    View Slide

  48. 13

    View Slide

  49. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View Slide

  50. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View Slide

  51. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View Slide

  52. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View Slide

  53. explained
    14 . 2

    View Slide

  54. explained
    14 . 2

    View Slide

  55. LLVM IR
    (bitcode)
    explained
    14 . 2

    View Slide

  56. LLVM IR
    (bitcode)
    explained
    14 . 2

    View Slide

  57. LLVM IR
    (bitcode)
    explained
    14 . 2

    View Slide

  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

    View Slide

  59. Expose existing classes
    Expose existing classes
    16

    View Slide

  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

    View Slide

  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

    View Slide

  62. Use Emscripten classes
    Use Emscripten classes
    17

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  67. 18

    View Slide

  68. Things to know
    Things to know
    19

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  79. Things to know (2)
    Things to know (2)
    20

    View Slide

  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

    View Slide

  81. Things to know (3)
    Things to know (3)
    21

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  90. Creating a complex UI?
    Creating a complex UI?
    23

    View Slide

  91. Find a component library
    Find a component library
    24

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  96. Large lists (with drag'n'drop)
    Large lists (with drag'n'drop)
    25

    View Slide

  97. Virtualized lists
    Virtualized lists
    26

    View Slide

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

    View Slide

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

    View Slide

  100. Virtualized lists
    Virtualized lists
    const ObjectRow = () => ...;
    const ObjectsList = (props) => props.map(group => )
    const SortableObjectRow = SortableElement(props => (

    ));
    const ObjectsList = (props) => (
    rowRenderer={({ ... }) => {

    })
    />
    );
    const SortableObjectsList =
    SortableContainer(ObjectsList);
    onSortEnd={({ oldIndex, newIndex }) => ...}
    ...
    react-sortable-hoc
    react-virtualized
    26

    View Slide

  101. Panels/resizable editors
    Panels/resizable editors
    27

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  105. Virtualization again!
    Virtualization again!
    30

    View Slide

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

    View Slide

  107. Levels rendering or visualizations
    Levels rendering or visualizations
    31

    View Slide

  108. Forget the DOM
    Forget the DOM
    32

    View Slide

  109. Forget the DOM
    Forget the DOM
    32

    View Slide

  110. Forget the DOM
    Forget the DOM
    32

    View Slide

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

    View Slide

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

    View Slide

  113. Don't forget the DOM
    Don't forget the DOM
    onPointerMove={...}
    onPointerUp={...}
    width={this.props.imageWidth}
    height={this.props.imageHeight}
    >
    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) => (
    onPointerDown={...}
    key={`vertex-${j}`}
    fill="rgba(255,0,0,0.75)"
    cx={vertex.getX()}
    cy={vertex.getY()}
    r={5}
    />
    ))}
    33

    View Slide

  114. When things aren't fast enough
    When things aren't fast enough
    34

    View Slide

  115. Profile the rendering
    Profile the rendering
    35

    View Slide

  116. Profile the rendering
    Profile the rendering
    35

    View Slide

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

    View Slide

  118. Profile the rendering
    Profile the rendering
    shouldComponentUpdate/memoization is often the answer
    Measure performance in production (React development
    build is way slower)
    35

    View Slide

  119. Inspect calls to WebAssembly
    Inspect calls to WebAssembly
    36

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  123. When your codebase is growing
    When your codebase is growing
    37

    View Slide

  124. Stick to your components
    Stick to your components
    38

    View Slide

  125. Stick to your components
    Stick to your components

    Help



    38

    View Slide

  126. Stick to your components
    Stick to your components

    Help


    Help



    Avoid custom/adhoc styles, that won't scale:
    38

    View Slide

  127. Stick to your components
    Stick to your components

    Help


    Help




    Avoid custom/adhoc styles, that won't scale:
    Make a component for it! #DesignSystem
    38

    View Slide

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

    View Slide

  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

    View Slide

  130. ...but create visual stories
    ...but create visual stories
    40

    View Slide

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

    View Slide

  132. Use types
    Use types
    41

    View Slide

  133. Use types
    Use types
    Flow Typescript
    41

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  142. Consider your packaging options
    Consider your packaging options
    43

    View Slide

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

    View Slide

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

    View Slide

  145. Consider your packaging options
    Consider your packaging options
    GDevelop
    Electron
    Web app Embed in a native app
    Squoosh.app Spotify
    Steam Chat
    43

    View Slide

  146. Build over Electron APIs
    Build over Electron APIs
    44

    View Slide

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

    View Slide

  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 ;
    } else if (item.type === 'checkbox') {
    return (
    ...
    />
    } else {
    return (
    ...
    />
    }
    }
    showMenu() { ... }
    }
    44

    View Slide

  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 ;
    } else if (item.type === 'checkbox') {
    return (
    ...
    />
    } else {
    return (
    ...
    />
    }
    }
    showMenu() { ... }
    }
    44

    View Slide

  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

    View Slide

  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?

    View Slide

  152. 46

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide