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 full-size slide

  2. Since a long time
    2

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. The editor is getting old
    The editor is getting old
    7

    View full-size slide

  9. 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 full-size slide

  10. 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 full-size slide

  11. 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 full-size slide

  12. 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 full-size 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.
    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 full-size 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++ )
    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 full-size 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...
    ...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 full-size slide

  16. Could web
    Could web
    technologies help?
    technologies help?
    8

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. “ 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 full-size slide

  20. “ 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 full-size slide

  21. “ 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 full-size slide

  22. “ 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 full-size 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
    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 full-size 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, 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 full-size 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,
    2d/3d visualizations
    2d/3d visualizations, nested
    , nested
    dialogs,
    dialogs, drag'n'drop, search,
    drag'n'drop, search,
    9 . 1

    View full-size slide

  26. 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 full-size slide

  27. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  31. “ 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 full-size slide

  32. “ 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 full-size slide

  33. “ 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 full-size slide

  34. “ 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  37. 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 full-size slide

  38. 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 full-size slide

  39. 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 full-size slide

  40. 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 full-size slide

  41. 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 full-size slide

  42. 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 full-size slide

  43. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View full-size slide

  44. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View full-size slide

  45. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View full-size slide

  46. Writing WebAssembly
    Writing WebAssembly
    14 . 1

    View full-size slide

  47. explained
    14 . 2

    View full-size slide

  48. explained
    14 . 2

    View full-size slide

  49. LLVM IR
    (bitcode)
    explained
    14 . 2

    View full-size slide

  50. LLVM IR
    (bitcode)
    explained
    14 . 2

    View full-size slide

  51. LLVM IR
    (bitcode)
    explained
    14 . 2

    View full-size slide

  52. 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 full-size slide

  53. Expose existing classes
    Expose existing classes
    16

    View full-size slide

  54. 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 full-size slide

  55. 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 full-size slide

  56. Use Emscripten classes
    Use Emscripten classes
    17

    View full-size slide

  57. 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 full-size slide

  58. 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 full-size slide

  59. 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 full-size slide

  60. 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 full-size slide

  61. Things to know
    Things to know
    19

    View full-size slide

  62. 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 full-size slide

  63. 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 full-size slide

  64. 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 full-size slide

  65. 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 full-size slide

  66. 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 full-size slide

  67. 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 full-size slide

  68. 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 full-size 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!
    For React:
    console.log(layout); // { ptr: 6804120 }
    Wasm memory The content of gd.Layout
    19

    View full-size 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!
    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 full-size 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!
    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 full-size slide

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

    View full-size slide

  73. 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 full-size slide

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

    View full-size slide

  75. 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 full-size slide

  76. 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 full-size slide

  77. 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 full-size slide

  78. 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 full-size slide

  79. 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 full-size slide

  80. 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 full-size slide

  81. 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 full-size slide

  82. 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 full-size slide

  83. Creating a complex UI?
    Creating a complex UI?
    23

    View full-size slide

  84. Find a component library
    Find a component library
    24

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  90. Virtualized lists
    Virtualized lists
    26

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  93. 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 full-size slide

  94. Panels/resizable editors
    Panels/resizable editors
    27

    View full-size slide

  95. Use a
    Use a tiling window library
    tiling window library
    28

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  98. Virtualization again!
    Virtualization again!
    30

    View full-size slide

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

    View full-size slide

  100. Levels rendering or visualizations
    Levels rendering or visualizations
    31

    View full-size slide

  101. Forget the DOM
    Forget the DOM
    32

    View full-size slide

  102. Forget the DOM
    Forget the DOM
    32

    View full-size slide

  103. Forget the DOM
    Forget the DOM
    32

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  106. 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 full-size slide

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

    View full-size slide

  108. Profile the rendering
    Profile the rendering
    35

    View full-size slide

  109. Profile the rendering
    Profile the rendering
    35

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  112. Inspect calls to WebAssembly
    Inspect calls to WebAssembly
    36

    View full-size slide

  113. 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 full-size slide

  114. 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 full-size slide

  115. 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 full-size slide

  116. When your codebase is growing
    When your codebase is growing
    37

    View full-size slide

  117. Stick to your components
    Stick to your components
    38

    View full-size slide

  118. Stick to your components
    Stick to your components

    Help



    38

    View full-size slide

  119. Stick to your components
    Stick to your components

    Help


    Help



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

    View full-size slide

  120. 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 full-size slide

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

    View full-size slide

  122. 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 full-size slide

  123. ...but create visual stories
    ...but create visual stories
    40

    View full-size slide

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

    View full-size slide

  125. Use types
    Use types
    41

    View full-size slide

  126. Use types
    Use types
    Flow Typescript
    41

    View full-size slide

  127. 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 full-size slide

  128. 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 full-size slide

  129. 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 full-size slide

  130. 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 full-size slide

  131. 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 full-size slide

  132. 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 full-size slide

  133. 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 full-size slide

  134. 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 full-size slide

  135. Consider your packaging options
    Consider your packaging options
    43

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  139. Build over Electron APIs
    Build over Electron APIs
    44

    View full-size slide

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

    View full-size slide

  141. 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 full-size slide

  142. 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 full-size slide

  143. 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 full-size slide

  144. 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 full-size slide

  145. What are users saying?
    What are users saying?
    47

    View full-size slide

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

    View full-size slide

  147. 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 full-size slide

  148. 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 full-size slide

  149. 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 full-size slide

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

    View full-size slide

  151. “ 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 full-size slide

  152. “ 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 full-size slide

  153. “ 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 full-size slide

  154. “ 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 full-size slide

  155. “ 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 full-size slide

  156. “ 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 full-size slide

  157. “ 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 full-size slide

  158. “ 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 full-size slide

  159. @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 full-size slide

  160. 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 full-size slide