GithubHelp home page GithubHelp logo

purescript-sdom's Introduction

purescript-sdom

An experiment in replacing the virtual DOM and avoiding diffing.

Motivation

The virtual DOM (VDOM) has become a very popular approach to developing applications in the browser, popularized by libraries like React. A simplified VDOM approach can be summarized briefly as follows:

  • Choose a type state of application states.
  • Write a function state -> VDOM from application states to a virtual DOM representation of the UI.
  • Each time we reach a new state, use a function diff :: VDOM -> VDOM -> Patch to compute the changes to the rendered virtual DOM.
  • Use a function Patch -> Eff (dom :: DOM) Unit to apply those changes to the real DOM.

The VDOM approach has many benefits. However, many web apps which use a VDOM don't actually require one.

Consider something like a web form which might contain text inputs and validation messages. If you didn't have a virtual DOM, you would just lay out the form statically, set the initial attributes and text values, and add event handlers to update them. The elements themselves would never change.

A VDOM approach in this case might be considered overkill - why should I have to diff two trees of components in order to update a simple label, when I can always easily figure out which label to update.

A key benefit of the VDOM is that it hides the complexity of the DOM API behind a simpler API with a clean denotation: an application is a function from states to a conceptual representation of the UI. However, operationally it is very heavy. The potential problem is that the diff function above might be quite expensive to compute. With well-chosen keys on every node, it might be possible to tune this computation, but there are other options available.

This library introduces the SDOM, or "static DOM". The idea is that by restricting components so that the "shape" of the UI becomes static, we can keep the clean denotation of the VDOM approach, but simplify the operational side dramatically. The SDOM consists of a static tree of components, with only the leaves (text nodes and attributes) changing over time. The SDOM approach also allows for limited forms of dynamic behavior, such as a component which renders a (uniform) array of subcomponents.

In practice, this is not so much of a restriction, and the limited form of dynamic behavior is enough to emulate most common UI patterns. Indeed, working with the SDOM is quite reminiscent of template-based approaches to UI development, but keeping the "one way binding" approach which is commonly associated with the VDOM.

More

For a more extensive motivation of the SDOM approach, an explanation of the underlying approach and how it was developed, you may want to check out this blog post.

purescript-sdom's People

Contributors

ianbollinger avatar paf31 avatar ritschwumm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

purescript-sdom's Issues

initial build with select example fails

building and running the counter example works fine but the select example gives the error below

> * Building project in /projects/git/purescript-sdom/examples/select
> Compiling Main
> Error found:
> in module Main
> at src/Main.purs line 53, column 9 - line 53, column 26
> 
>   Unknown value Components.select

Add defaultMain function

the examples show some duplication in the main function, while it could just read:

main = hangOn 'container' myComponent

if we had a hangOn convenience function. This would also get rid of some immaterial imports.
One issue could be how best to handle error cases. Many fatal error cases are likely to be handled in some standard fashion. So providing one general handler (and allowing to replace it) should be fine.

Clarification in the project docs

Hi, I'm not quite sure if my following take on the project is correct or not.
Either way, this kind of information would have helped me to better understand the approach:

SDOM components conceptually create their visual representation from a
model (state), analogous to approaches like React. However, very much unlike React,
this state is never materialized in a separate data structure. There is no separate
"presentation model" on the value level - only on the type level.
All model data resides directly in the DOM.
Event handlers read from the DOM and write to the DOM. They do not update
any other state. Reading and writing is type-safe wrt the model type.

Support async event handlers?

I don't use this lib yet, so no time constraint on responding to this issue. I've been looking at it a lot and am finding it great reference.

If I'm reading the code right, the eventListeners/handlers currently are synchronous. I wonder if Phil has already considered the async handler situation in this lib and precluded async handlers.

(Event -> i -> o)

It's inevitable that this lib will need to support async handlers. Maybe change the type of a handler to something like this:

type EventHandler m i o = (Event -> i -> ContT Unit m o)
-- Could prescribe `Run`. Surely no complaints - everyone likes trying a new thing. :-)
type EventHandlerRun effs i o = EventHandler (Run effs)

It would require updating runStaticDOM and I think it would be used like this:

element "button"
        (mempty)
        (singleton "click" \_ xs -> pure $ (length xs) : xs)
        -- or --
        (singleton "click" \_ xs -> do
          x <- fetchXInContT
          pure x : xs
        [ text $ const "+ Add" ]

Feasibility of 'Baking' HTML Server-Side With SDOM

By 'baking' I mean rendering and storing beforehand an asset that would otherwise be generated at run time.

That is, would it be feasible to, as part of the transpile/build step, render and store the static portions of the HTML produced by the SDOM in the HTML file and replace the corresponding rendering procedures in the code with bindings to the generated HTML?

Would doing so have any performance benefits?

The idea of 'baking' HTML from a VDOM has been on my mind since I first looked into Elm, but it seems particularly relevant to your SDOM library, since the SDOM clearly delineates the static and dynamic parts of the page.

build error starting canvas example

$ pulp run
* Building project in /projects/git/purescript-sdom/examples/canvas
* Build successful.
/projects/git/purescript-sdom/examples/canvas/output/DOM.HTML/foreign.js:5
  return window;
  ^

ReferenceError: window is not defined
    at exports.window (/projects/git/purescript-sdom/examples/canvas/output/DOM.HTML/foreign.js:5:3)
    at /projects/git/purescript-sdom/examples/canvas/output/Control.Monad.Eff/foreign.js:12:16
    at /projects/git/purescript-sdom/examples/canvas/output/Control.Monad.Eff/foreign.js:12:16
    at /projects/git/purescript-sdom/examples/canvas/output/Control.Monad.Eff/foreign.js:12:20
    at Object.__do [as main] (/projects/git/purescript-sdom/examples/canvas/output/Main/index.js:76:199)
    at Object.<anonymous> (/private/var/folders/88/cz3jknpx4n52zb0wrnrqlyf00000gp/T/pulp-run11829-62143-1krespk.qsl4.js:1:79)
    at Module._compile (module.js:641:30)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
* ERROR: Subcommand terminated with exit code 1

How to have channel event handling code depend on component state

This might be a better fit for SO, but I'm hoping you could help with how I could create events which depend on the state of a component. For instance in the linked example :

https://github.com/paf31/purescript-sdom/blob/master/examples/async/src/Main.purs#L62

how could I make the interval value depend on State?

Thanks a lot for your time and the thought provoking work on comonadic and incremental UI! Can't wait to dig more into your work.

Optimize constant attributes

Attributes which never change don't need event handlers, so we can optimize them just like text_ optimizes constant text nodes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.