jorgebucaran / hyperapp

1kB-ish JavaScript framework for building hypertext applications
MIT License
19.06k stars 781 forks source link

Road to 1.0 #244

Closed jorgebucaran closed 6 years ago

jorgebucaran commented 7 years ago
nitin42 commented 7 years ago

Although all these may increase the lib size but they can be dispatched through separate packages like InfernoJS does ?

jorgebucaran commented 7 years ago

@nitin42

nitin42 commented 7 years ago

Oh! I really wanted to work on hyperapp and right now I am going through the Elm Architecture doc. Where can I start ?

From recycling of DOM nodes I meant to say that re-using the dom nodes upon their disposal.

nitin42 commented 7 years ago

Or I can work on the website ? This will also led me to understand the core concepts and the design principles of the lib by writing about the api and their functionality. Let me know what you think !

jorgebucaran commented 7 years ago

Where can I start ?

I think here is a good place to start.

Or I can work on the website?

Be my guest! πŸ‘

nitin42 commented 7 years ago

Ok so I will be rendering the docs on web. Meanwhile I will go through the link you provided and will start contributing !

nitin42 commented 7 years ago

Is there something on (HyperApp core) which I can hack? Other discussions are already on πŸ”₯ ! I am interested in investing my time by working on HyperApp but don't know where to start. Like cli tool discussion does not have an answer and I feel growing that discussion further is unneeded. Same goes for other discussions. Anything ?

lukejacksonn commented 7 years ago

@nitin42 you could try build an app with HyperApp; find a limitation and try improve it or find something that you find writing over and over again and try abstract that process out to a custom element or mixin?

Or help build out functionality of example applications such as the Hacker News PWA. So we can get it up on https://hnpwa.com/

nitin42 commented 7 years ago

HNPWA seems a good idea!!

nitin42 commented 7 years ago

I could implement :

I think I should start working!

zaceno commented 7 years ago

Should we use Github's "milestone" feature for 1.0? Not sure how it works, but this seems like the sort of use case they made that feature for.

andrewiggins commented 7 years ago

@jbucaran What's the plan for the relationship between picodom and hyperapp? If hyperapp wants to eventually consume picodom as a dependency, should that be part of 1.0 milestone?

jorgebucaran commented 7 years ago

@andrewiggins At this point both vdom engines are the same, but I presume they might eventually begin to differ since both have different "core values". HyperApp is opinionated about state management, while picodom isn't.

I also don't want to consume picodom in hyperapp, but it might happen. The probability is very low though.

brandonros commented 7 years ago

Why do we need both actions and events?

Take this really vanilla app:

app({
  state: {
    images: []
  },
  view: function(state) {
    return h('div', {}, state.images.map(function(image) {
      return h('img', {src: 'images/' + image.url});
    }));
  },
  actions: {
    updateImages: function(state, actions, data) {
      state.images = data;

      return state;
    }
  },
  events: {
    updateImages: function(state, actions, images) {
      actions.updateImages(images);
    }
  }
});

setTimeout(function() {
  emit('updateImages', []);
}, 5000);

This is cool, but why not allow this:

app({
  state: {
    images: []
  },
  view: function(state) {
    return h('div', {}, state.images.map(function(image) {
      return h('img', {src: 'images/' + image.url});
    }));
  },
  actions: {
    updateImages: function(state, actions, data) {
      state.images = data;

      return state;
    }
  }
});

setTimeout(function() {
  emit('action', {name: 'updateImages', data: []});
}, 5000);
jorgebucaran commented 7 years ago

@brandonros Why do we need both actions and events?

Architecture

I think the separation is important from an architecture point of view.

Now, you can also create custom events, in which case you are responsible for calling yourself, but they also work in the same way as the default events.

Return Values

Actions return a partial state or a thunk, or maybe just call several other actions. Actions can be async functions too.

Events reduce over some data by successively calling each event handler of the specified event.

Consider the following example.

const emit = app({
  events: {
    someEvent: [
      (state, actions, data) => data + 1,
      (state, actions, data) => data + 1,
      (state, actions, data) => data + 1
    ]
  }
})

And this is the result of firing someEvent with some data.

console.log(
  emit("someEvent", 10)
) // => 13

One-to-many

An event can have more than one callback associated with it.

myEvent: [handler1, handler2, handler3]

An action is always a single call.


These are some of my thoughts. I am sure that:

setTimeout(function() {
    emit('action', {name: 'updateImages', data: []});
}, 5000);

Would be interesting, and we can consider the implications of making emit work in both ways, allowing you also to emit default events.

brandonros commented 7 years ago

@jbucaran I think it the time it took you to write this response, you could have made emit('action', {name: 'updateImages', data: []}); work. :)

jorgebucaran commented 7 years ago

@brandonros It didn't take so long and this is good documentation for subscribers too! :)

So, what about this:

const Sender = emit => ({
  events: {
    send(state, actions, { name, data }) {
      return actions[name](data)
    }
  }
})

const emit = app({ 
  mixins: [Sender]
})

Then use it to call actions directly outside your app.

emit("send", { name: "updateImages", data: [...] })

Making it work for action might be possible too, but would require some "hacking" since action is one of the default events.

brandonros commented 7 years ago

@jbucaran Thank you for taking the time to supply that example. I appreciate that and I hope it helps somebody else.

I've got one more "idea" that I came up with using this, just playing around with it.

I really don't like having to set up Browserify or Webpack or all of that crap. I'm trying to avoid Babel + JSX as well, just for exercise.

Back in the jQuery days, I used to do a lot of:

$('body').html('<div>a really big <span>html string</span></div>')

I saw you guys had the ability to use the (html`html string here`), but that requires Browserify.

Is it possible to get compiled/ported so you can just include a page, and then call h(html('long string')) or something similar?

brandonros commented 7 years ago

I just spent 15 minutes trying to figure out why the "load" event isn't working.

Your codepad says it is 'init' instead of load. Please update the docs. https://github.com/hyperapp/hyperapp/blob/master/docs/events.md

andyrj commented 7 years ago

Load is in 0.11 which should be out anytime now... Master is ahead of npm publish by a bit.

brandonros commented 7 years ago

Thunks do not work and when I try to install it to help debug to provide more information (all I can get is a minified version), I get rollup.config.js not found

Edit: I see what you mean about master. Can you put the rollup.config.js in the repo please?

Edit: I was trying to build an old version. Ignore, thanks!

andyrj commented 7 years ago

I recall someone else running into that when npm installing the package from master git repo. I have always had to make local copy and create a symlink in node_modules to the local repo to test newest version. Hopefully 0.11 will be out soon.

Swizz commented 7 years ago

@brandonros As h implement the normalised hyperscript representation, that allow you to use hyperscript-helpers. That allow you to use an elm like syntax to create your virtual dom node.

import { h, app } from "hyperapp"
import helpers from "hyperscript-helpers"

const { div, h1 } = helpers(h)

app({
  state: {
    title: "Hi.",
  },
  view: state => 
    div(null, [
      h1(null, state.title)
    ])
})

I am also working on my own implementation, to create a more optimised (tree shaking, right h call) experience for Hyperapp and Picodom users.

zaceno commented 7 years ago

@brandonros If you want to go completely standalone, this works (as long as you're targeting mostly es6 compatible browsers):

<html>
  <head>
    <script src="https://unpkg.com/hyperx"></script>
    <script src="https://unpkg.com/hyperapp"></script>
  </head>
  <body>
    <script>
      const {app, h} = hyperapp
      const html = hyperx(h, {attrToProp: false})

      /*
        now you can produce virtual trees like this:
        html`
          <div class="foo">
            <p>AAA</p>
            <p>BBB</p>
          </div>`
      */

      //initialize your app:
      app({...})
    </script>
  </body>
</html>

The reason this method is not usually mentioned or recommended is because there is a performance penalty to compiling the hyperx strings in browser when it could be handled by a browserify transform or webpack loader.

It's also possible to do something similar for a standalone html page written with JSX, but I can't remember the module name. babel-standalone I think.

jorgebucaran commented 7 years ago

@nitin42 Recomposing components (like lodash) for expressing state updates

What is this? I don't use lodash and I am not familiar with the concept "recomposing components" either. But it sounds interesting.

naugtur commented 7 years ago

I think @nitin42 is referring to this:

var _ = require('lodash/core');
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
var fp = require('lodash/fp');
jorgebucaran commented 7 years ago

Thanks @naugtur, but now I am more confused! πŸ˜„

EDIT: Not sure I understand what this has to do why hyperapp either.

lyquocnam commented 7 years ago

waiting for SSR so much πŸ˜„

jorgebucaran commented 7 years ago

@lyquocnam There are ways to hydrate pre-rendered HTML. We already use it at work πŸ’―.

lyquocnam commented 7 years ago

@jbucaran have any examples about Hyperapp with backend and SSR ?

Edit: ~hyperApp~ -> Hyperapp

jorgebucaran commented 7 years ago

@lyquocnam Nope, no non-trivial SSR example, but we created hyperapp/server and could use some help. πŸ˜„

/cc @andrewiggins @SkaterDad @corysimmons

corysimmons commented 7 years ago

Swamped for about the next month then I can work on some SSR solution. Anyone is welcome to beat me to it. 😬

TheLarkInn commented 6 years ago

Hey there!!! Sean from the webpack team. Please let me know if we can help support any AoT compilation needs via a webpack loader. :-D There are lots of great examples out there already but we are here to support ya'll!!!!

Also, not sure what your lazy loading story looks like, but as long as your api accepts a Function -> Promise<YourComponentPrimative> then it can support webpack code splitting for syntaxes like

import();

okwolf commented 6 years ago

Now that #311 has been merged, what's remaining before achieving 1.0 status?

jorgebucaran commented 6 years ago

@okwolf Almost nothing! πŸ„

naugtur commented 6 years ago

@TheLarkInn what would it take for hyperapp to have default support for bundle splitting with async imports similarly to what Vue supports?

Seems to me it's just about accepting a promise where a component or custom tag is expected, but I only saw that at a conference ;)

selfup commented 6 years ago

I think that would have to be a Mixin of some sort since we don't ship with polyfills πŸ€”

Just thinking out loud here πŸ˜›

Or we could just check if Promise is a thing and then check if a certain view is a Promise

corysimmons commented 6 years ago

Webpack is buggy and bundles are huge or require a ton of config (there are literally books on how to use that project.............). It seems almost all "JS fatigue" revolves around that project...

This seems to go against what Hyperapp is trying to do (i.e. not overcomplicate simple things).

I'd vote not doing anything to support webpack and just build a simple bundler from scratch.

jorgebucaran commented 6 years ago

@corysimmons Webpack is buggy... It seems almost all "JS fatigue" revolves around that project...

That's not very nice man. JS fatigue is a myth and @TheLarkInn is just offering help. I am not a webpack user myself, but I can think of many users who want to bundle their hyperapps with webpack.

@TheLarkInn There are lots of great examples out there already but we are here to support ya'll!!!!

Can you show me an example of this? πŸ˜„

jorgebucaran commented 6 years ago

Webpack... bundles are huge

They can get bigger than rollup if you are bundling a ton of modules, but that's because of how webpack works.

[webpack] work by wrapping each module in a function, putting them in a bundle with a browser-friendly implementation of require, and evaluating them one-by-one. That’s great if you need things like on-demand loading, but otherwise it’s a bit of a waste, and it gets worse if you have lots of modules.

and

If you need code-splitting, or you have lots of static assets, or you’re building something with lots of CommonJS dependencies, Webpack is a better choice. If your codebase is ES2015 modules and you’re making something to be used by other people, you probably want Rollup.

Source

Also:

[webpack] ...at runtime, each of those module functions is evaluated in turn to populate the module cache. This architecture has lots of advantages β€” it makes it possible to implement advanced features like code-splitting and on-demand loading, and hot module replacement (HMR).

Source

selfup commented 6 years ago

Webpack is fine ❀️ . I use it and the API is straightforward.

@corysimmons Let's try to be a bit more civil πŸ˜›

Also scope hoisting has helped a ton! My boilerplate counter is only 2kb gzipped using webpack, So bundles being very large might not apply so much anymore.

Let's not blame JS fatigue on a single library πŸ™


Otherwise, I wonder if this should be a Mixin (official Mixin) or in core πŸ€”

Moving lazy loading talk

Separate issue: https://github.com/hyperapp/hyperapp/issues/379

corysimmons commented 6 years ago

Yeah I'm toxic. Bye guys.

jorgebucaran commented 6 years ago

@corysimmons Whoa, I just said: "that's not very nice man" because you went on a little off-topic rant blasting webpack.

And now you left the organization too? I don't get it, were you expecting anyone to support you on this or pretend you didn't say anything?

okwolf commented 6 years ago
  • [ ] Optimize patch?

@JorgeBucaran is this referring to what #378 would do to help fix #373?

jorgebucaran commented 6 years ago

@okwolf Nope, #373 came up just recently. Optimize patch involves rewriting the patch function.

The objective is to rewrite it in less code and make it faster at the same time. πŸ‡πŸ’₯

okwolf commented 6 years ago

The objective is to rewrite it in less code and make it faster at the same time. πŸ‡πŸ’₯

@JorgeBucaran I understand how to measure code size, but what metric are we using to determine performance in this instance?

jorgebucaran commented 6 years ago

We use js-framework-benchmark.

vladshcherbin commented 6 years ago

An interesting project to put on a test, will there be SSR support in 1.0 or this feature is not on a roadmap?

jorgebucaran commented 6 years ago

@VladShcherbin Thanks! Hyperapp now provides automatic SSR hydration out of the box since 0.14.0.

vladshcherbin commented 6 years ago

@JorgeBucaran yeah, I've seen hydration in the docs.

I mean, when a user requests a page, how do you generate html for this page on server (using node for example), is there any demo/repo of this?