These are chat archives for ractivejs/ractive

22nd
Jan 2018
Juan C. Andreu
@andreujuanc
Jan 22 2018 08:57
Migrate is not so hard.
I'm doing it with one of my projects.
js files can get checked as TS, and that'd tell you to some degree how much work it might be. Then slowly change files to .ts
But, thats just a port.
sometimes its better just to use these changes as a redo, and refactor things around
Paul Maly
@PaulMaly_twitter
Jan 22 2018 09:07
Yea, valid js file is also valid TS file. But seems, refactoring need to include also the better code-splitting to decrease code size. For me Ractive is almost ideal framework. I think we've only two major issues: big size and low speed.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 09:25
I mean, Ractive's main competitors are React (~150kb) and Vue (~80kb). Both seems more performant.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 10:13
@evs-chris Proposal about {{#await}} block: could we replace Promise value by real value in case if promise resolved with success? Seems, it could be useful.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 12:23
@evs-chris also please check my comments on #3182
Joseph
@fskreuz
Jan 22 2018 13:33
That's one of the reasons for TS as opposed to another language entirely. You can simply change the file to .ts and slowly move everything over.
I also happen to work on an TS project that started with a less strict config (you're practically writing JS). Currently moving it to a stricter setup (forced types, no nulls/explicit null types, etc.).
Joseph
@fskreuz
Jan 22 2018 13:38
Anyways, random question of the day: Is it safe to assume that, if you have a build setup (development, pre-processing, or both), you can write in ES? or better yet, can we force you to write in ES?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 13:41
I don't use TS, in my projects, but I think TS is very good tool for big enterprice projects or software used by many people. Both groupa need to be stable as possible. So, I guess Ractive in the second group.
About your question: nope, I won't write my code using ES features before it will be available in latest NodeJS
because, my isomorphic code should runs on server without any building/packaging
Joseph
@fskreuz
Jan 22 2018 13:45
You could transpile both tho
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:45
but most of ES features already are available
Joseph
@fskreuz
Jan 22 2018 13:45
I think 4 had around 90% of them. But 6 and 8, both LTS, should have everything except the module system (iirc, it's experimental in 9).
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:46
@fskreuz that's too annoying and also the reasons I don't use TS for all node projects
Joseph
@fskreuz
Jan 22 2018 13:46
re: the random question of the day, for a bit of context, implemented loader-rollup last night using the new APIs on that PR. What the APIs do is simply wrap the component script into ES/CJS/AMD, append a few things, and poof! Component file as a JS module. But It came to my attention that the generated code isn't really pretty, particularly the ES one since it comes with a polyfill to translate require calls in the script body to the imports (since the component file script is basically CJS-like). So...
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:46
but yes, except for imports, the support is very good now
Joseph
@fskreuz
Jan 22 2018 13:49
...is it reasonable to say "Hey, if you have a build step, please write your component's <script>in ES modules instead of component.exports so we can mangle and export your code better."
Paul Maly
@PaulMaly_twitter
Jan 22 2018 13:50
Yep, most of ES, but not all. Thats why I use CommonJS instead imports
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:53
note sure, I remember I run into some problems last time I tried using ES modules there but I don't remember the details
Paul Maly
@PaulMaly_twitter
Jan 22 2018 13:53
@fskreuz yep, I could transpile it, but I won't
Joseph
@fskreuz
Jan 22 2018 13:55
It's for component files only tho (i'm practically asking for a version 2 of how to write component files).
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:58
indeed, I'm running component JS unmodified on server side, but I guess transpiling it wouldn't be a problem in my case
Joseph
@fskreuz
Jan 22 2018 13:59
Aha. Hmm...
Martin Kolárik
@MartinKolarik
Jan 22 2018 13:59
but back to your question... if the polyfill was included only when needed (when there are require calls in the code), would it solve the problem?
Juan C. Andreu
@andreujuanc
Jan 22 2018 14:04
I do only Es lately. Or TS.
I find it easier and clearer code
Specially on bit enterprise code
Big*
If you use requirejs or webpack require calls are handled for you
Chris Reeves
@evs-chris
Jan 22 2018 14:08
I haven't done a whole lot of traditional ssr, but so far my approach is to use es, especially modules, and use a bundle with node too
I find that node modules and the frontend bundle don't really overlap in any significant way
the way I've used it thus far, the only point of change is passing in the data vs fetching the data from the client app
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:23
It's your way, but I don't see any reason to use bundled code in nodejs instead of just use source code and nodejs native modular system.
Besides, I don't like very much ES6 import/export, because I want to be able to require modules in-place, not only on top of the file.

the way I've used it thus far, the only point of change is passing in the data vs fetching the data from the client app

In my code this point is also isomorphic ))

Chris Reeves
@evs-chris
Jan 22 2018 14:27
thinking about hydration a bit, would it make sense to have ractive check an attribute on the target node e.g. data-ractive-enhance to turn it on, or do most people using progressive enhancement just leave it on in the root/rendered instance all of the time?
Martin Kolárik
@MartinKolarik
Jan 22 2018 14:28
leave it on in the root/rendered instance all of the time
Chris Reeves
@evs-chris
Jan 22 2018 14:29
that's fair 😁
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:29
maybe we could just make enhance=true as default value?
any cons ?
Chris Reeves
@evs-chris
Jan 22 2018 14:30
re isomorphism: I have shared modules that run in both places, but I kinda have up on 100% isomorphism a while back because the shims started to pile up and get awkward e.g. making a request to a service
it could be made essentially free if used with an empty target
but I'm not certain that it doesn't have a bit of overhead as it stands
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:33
I don't get it, could you please explain little bit more? if I leave target is empty, markup will be enhanced automatically?

re:

@evs-chris Proposal about {{#await}} block: could we replace Promise value by real value in case if promise resolved with success? Seems, it could be useful.
@evs-chris also please check my comments on #3182

Chris Reeves
@evs-chris
Jan 22 2018 14:35
no, if target is empty, then turning on enhancement could be made to have no overhead - as it is right now, I think there's a perf hit turning on enhance even if there's no dom to try to take over
for the await block, the template is not really supposed to write data unless it's coming from an event
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:37
and?
I could do this:
ractive.set('foo', 1);

{{#await foo}}
{{then val}}
{{val}}
{{/await}}
so it works
Chris Reeves
@evs-chris
Jan 22 2018 14:39
yes, but the block didn't change foo
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:41
yep, but could or it's not possible? something like: promise.then(setRegularValue).then(renderThenBlock)
Chris Reeves
@evs-chris
Jan 22 2018 14:41
would also probably cause some weirdness with more than one await block looking at the same promise
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:43

how about this code:

{{#await foo}}
{{then val}}
{{val}}
{{/await}}

ractive.set('foo', fetch()); // very long request
ractive.set('foo', 1);

that is not the same? seems, doesn't break anything

Chris Reeves
@evs-chris
Jan 22 2018 14:51
what about a flag? {{#await foo set}}
at this point I think it would be premature to say that await should always modify the data, so if it's going to, it should be opt-in
Paul Maly
@PaulMaly_twitter
Jan 22 2018 14:54
Looks weird, actually I also don't have good solution. Maybe we need just leave it of the rest for a while.
Plugins interesting me much more, could you please give your comments about it?
Joseph
@fskreuz
Jan 22 2018 15:03

could we replace Promise value by real value in case if promise resolved with success?

Promise adaptor :wink:

Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:07
:clap:
About plugins.. my suggestions (copy in chat):
1) prevent applying a plugin multiple times
2) use more consistent args, eg, function (Ractive, target) {} instead of function (opts) {}
Chris Reeves
@evs-chris
Jan 22 2018 15:19
I'd rather not require my plugins to register in the global defaults
I usually have a handful of component-specific decorators, child components, and transitions for my more complicated components
and throwing them in the global namespace is asking for conflicts
that's where target and register come in, though it's probably possible to find better names
target is always where you want to install methods and properties so either the instance or the prototype for current and future instances
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:22
Me too, but I don't think we should restrict this opportunity
I've a few plugins which I need to assign things to Ractive's constructor
Chris Reeves
@evs-chris
Jan 22 2018 15:23
register is always where you want to install any decorators, transitions, components, etc, so the instance or the component def
and with an opts object, we can throw in Ractive as well pretty easily
also function MyPlugin({ Ractive }) { ... } :grinning:
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:24
I don't think at all that we should make the assumptions of how developers will use plugins
yep, but how about consistency ?
we don't use this approach in other plugins, just a regular args list
Chris Reeves
@evs-chris
Jan 22 2018 15:25
positional args are unpleasant for future expansion
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:26
but maybe we should made this change in future versions eg. 2.0 and made it for everything?
Chris Reeves
@evs-chris
Jan 22 2018 15:26
what would a plugin do beyond modify prototypes and register plugin things?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:26
many things)
on, observe for instances
set/get data / shared data
we shouldn't make the assumptions
how exactly developers will use it
Chris Reeves
@evs-chris
Jan 22 2018 15:28
all of those are available on target if it's an instance
if it's not, well you couldn't do that anyway
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:30
in one of my plugins, I use this code to setup data variable related on context:
(this.set || this.sharedSet)();
Ractive.use() vs instance.use()
Paul Maly
@PaulMaly_twitter
Jan 22 2018 15:49
Real case: my plugin need to setup some value to target and also observe it changes.
And it should work per instance and in global
Paul Maly
@PaulMaly_twitter
Jan 22 2018 16:06
module.exports = (keypath) => (Ractive, target) => {

      (target.set || target.sharedSet)(keypath, 'initialState');
      (Ractive.isInstance(target) ? target : new Ractive()).observe(keypath, function() { /* do something */ });
};
Ractive.use(require('myPlugin')('myKeypath')); && instance.get('@shared.myKeypath');
// OR
instance.use(require('myPlugin')('myKeypath')); && instance.get('myKeypath');
user have a choice
Chris Reeves
@evs-chris
Jan 22 2018 16:22
do you have many decorator, transitions, etc plugins?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 16:26
decorators yes, transitions not so, but I have a few custom plugins I use with my own use() method
These plugins implements things which doesn't relate to decorators or other built-in plugins
actually, for me use() is not just the way to setup built-in plugins, but write a custom plugins
that's why I don't think we should make the assumptions about them
To write anything I really need only two things: Ractive' constructor and context of caller
Paul Maly
@PaulMaly_twitter
Jan 22 2018 16:32
Re: deduping, as you can see above in this case I need to control that plugin would be installed only once per callee
*caller
Chris Reeves
@evs-chris
Jan 22 2018 16:33
out of curiosity, what other APIs would you change in future versions if we went with a destructure-what-you-need style use?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 16:36
Hm, adaptors maybe
Chris Reeves
@evs-chris
Jan 22 2018 16:53
I responded to your comments on the issue, but I'll ask here too - why do you want to ensure that a plugin is only added to an instance once? is that a thing that crops up regularly?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:03
See above
Re: deduping, as you can see above in this case I need to control that plugin would be installed only once per callee
*caller
Chris Reeves
@evs-chris
Jan 22 2018 17:03
ah! missed it in the other comments
the issue with that is that function identity changes if you have options to generate a new function
and there's a similar issue even if ractive manages the opts
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:06
Could you please provide a code example of this issue?
Chris Reeves
@evs-chris
Jan 22 2018 17:08
function plugin(opts) {
  return function() {}; // dummy
}

console.log(plugin() !== plugin());
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:08
In general case I think custom plugins should the same thing as any regular plugins, for example for your browser. I don't think so I would be happy if your Chrome wouldn't control it's plugins deduping)))
Also eg. Vue plugins is only purpose in deduping
Chris Reeves
@evs-chris
Jan 22 2018 17:10
there's legit cases where you want the same plugin multiple times though, e.g. Ractive.use(fade(), fade({ duration: 1000, name: 'slowFade' }))
we could allow the plugin to return an id string if it needs deduping and use that
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:13
I don't think there's the last case. For me a plugin is more complex thing. Also plugins can and will extend global things, so they must be under control
Chris Reeves
@evs-chris
Jan 22 2018 17:15
then function identity definitely won't work for ensuring a plugin only executes once, though I'm still a little unclear about why they'd get called multiple times to begin with, if not explicitly by the user
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:16
For example, Vue router
it shouln't be called twice
I prefer plugin system control it for me
Maybe we could use chaining instead of function identity?
Ractive.use(plugin1, arg1).use(plugin2, arg2)
Chris Reeves
@evs-chris
Jan 22 2018 17:39
that still doesn't handle the cases where the plugin can be legitimately used multiple times with different configs
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:45
Think about it like about browser plugins. Do you need to have them in this way?
One more example:
Paul Maly
@PaulMaly_twitter
Jan 22 2018 17:51
In future, we could split methods like add/push/splice/etc to some module like ractive-extras
Chris Reeves
@evs-chris
Jan 22 2018 18:27
I think the most common use would be allowing components to be registered with a custom name, possibly more than once if you need easy event bubble handling
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:33
Hm, I don't know that case. Could you explain that in code?
Re: ractive-extras
Module 1: ``Ractive.use(require('ractive-extras'));
Module2: ``Ractive.use(require('ractive-extras'));
Chris Reeves
@evs-chris
Jan 22 2018 18:35
const cmp = Ractive.extend(); // some common useful component here
new Ractive({
  template: `<thing1 /> <thing2 />`,
  components: { thing1: cmp, thing2: cmp },
  on: {
    'thing1.something'() { ... },
    'thing2.something'() { ... }
  }
});
that's an oddly composed example for brevity
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:37
And where is the problem we could solve by use()?
I always do that
Chris Reeves
@evs-chris
Jan 22 2018 18:37
if cmp was a plugin available for use with use, it would be something like
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:39
oh, I see, it's looks like mixin more than plugin
Chris Reeves
@evs-chris
Jan 22 2018 18:39
const cmpConfig = {};
function plugin(config) {
  return ({ Ractive, instance }) => instance.components[config.name || 'cmp'] = Ractive.extend(cmpConfig);
}
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:40
Omg, no
There is no problem here
You can always do this with simple function))
Plugins are noy about setup other plugins/components, but about complex custom/domain-specific behaviars.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:46
My point of view:
Chris Reeves
@evs-chris
Jan 22 2018 18:46
but that's one of the major benefits of use, you no longer have to figure out how to get Ractive or the parent component/instance/whatever around to the plugins in whichever module system the end user happens to be using
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:47
Yep, but regarding component we can solve it much simple)))
For example, let components be just an options map and handle it inside of Ractive constructor))
Chris Reeves
@evs-chris
Jan 22 2018 18:49
it is handled that way, but if the component is not part of your codebase, then where does Ractive come from for the component code to call Ractive.extend or Ractive.extendWith?
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:50
const MyComponent = {
       template: ``,
       data: () => {}
};
new Ractive({
       el: '#app',
       components: {
                 comp: MyComponent
        }
})
then where does Ractive come from for the component code to call Ractive.extend or Ractive.extendWith?
ease,
if component is POJO (just a options map), so always use Ractive.extend
If component author want to use Ractive.extendWith, so, he will use it
Chris Reeves
@evs-chris
Jan 22 2018 18:52
class MyComponent; const component = Ractive.extendWith(MyComponent, opts); export default component;
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:52
yep
Chris Reeves
@evs-chris
Jan 22 2018 18:52
that's the only way to control the component constructor name at this point
that's also quite a breaking change
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:53
// component1.js
export default Ractive.extend({});

//component2.js
export default Ractive. extendWith(MyComponent, opts);

//component3.js
export default opts; // besome Ractive.extend(opts);
Chris Reeves
@evs-chris
Jan 22 2018 18:53
and doesn't address other uses of Ractive for things other than components
Paul Maly
@PaulMaly_twitter
Jan 22 2018 18:55
ok, lets say like this:
export default [MyComponent, opts];
components: {
     component1: Ractive.extend({}),
     component2: Ractive.extendWith(MyComponent, {}),
     component3: {},
     component4: [MyComponent, {}]
}
My main idea - because we already have special components property in Ractive, we could have right context for it
like decorators, already doesn't need to have Ractive inside of it module definition file
we can just export function and Ractive pass right context to it
also we can do with adaptors, components, transtions and other built-in things, because it's built-in types
use() is about completely custom things
Chris Reeves
@evs-chris
Jan 22 2018 19:00
but it can, and arguably should, cover both
no assumptions about what you're trying to do with a plugin, right?
I want to use plugins to avoid module system headaches for my component libraries
Paul Maly
@PaulMaly_twitter
Jan 22 2018 19:01
I don't think so, for me maybe it looks like:
new Ractive({
     decorators: {},
     components: {},
     transitions: {},
     use: {} // custom plugins
})
Chris Reeves
@evs-chris
Jan 22 2018 19:02
and be able to split stuff into core modules that other plugins can detect when initing
if the plugin gets a handle to the target prototype, instance, and Ractive, it can do just about anything
Paul Maly
@PaulMaly_twitter
Jan 22 2018 19:15
yes, but only once per caller
also without dedupling feature use() doesn't make sense, because of:
// use.js
export default function use(config) {
  return ({ Ractive, instance }) => instance.components[config.name || 'cmp'] = Ractive.extend(cmpConfig);
}

import use from 'use.js';

use(Ractive, instance);
we don't need to have special method for that
Joseph
@fskreuz
Jan 22 2018 19:22
I feel like this discussion will become lost in chat. I'm in favor of enumerating all the possible permutations of how use is used in the relevant Github issue before proceeding with implementation.
It took me a day to realize on-the-fly instance augmentation wasn't possible using init options (without some hacktacular deep-merging of config). But if use cases were enumerated in the original post (code samples), that would have been helpful early in the discussion instead of 10 or so comments later.
(This is also the reason I have the monorepo PR before suggesting major changes to Ractive, just to prove out a few things first. Actual code can explain better).
Joseph
@fskreuz
Jan 22 2018 19:29
And by the way, long discussions on Github isn't really bad. You should see other frameworks hash out features. They're like 100 scrolls long (and hundreds of emojis) at best. :grin:
Juan C. Andreu
@andreujuanc
Jan 22 2018 19:33
+1
Specially in gitter, sometimes need to F5 to bring hidden chat out of the void...
Joseph
@fskreuz
Jan 22 2018 19:36
I remember replying once, and I was like 5 messages behind already. Took a refresh to notice. :D
Paul Maly
@PaulMaly_twitter
Jan 22 2018 19:41
I think we should read this article about Vue plugins: https://vuejs.org/v2/guide/plugins.html
Paul Maly
@PaulMaly_twitter
Jan 22 2018 20:31
re: plugins . I like approach which was described by @fskreuz in #3178
Paul Maly
@PaulMaly_twitter
Jan 22 2018 20:38
But somehow, we need to be able control deduping for which things, it's important. Maybe just inside of plugin itself like:
export default function(Ractive) {
      ! Ractive.prototype.wait && 
        Ractive.prototype.wait = (promis, key) => {};
      ! Ractive.prototype.ready && 
        Ractive.prototype.ready = (callback) => {};
};
Juan C. Andreu
@andreujuanc
Jan 22 2018 20:38
i really dont get the benefit of use vs whatever = myplugin
I mean, its nice. But can't see the urge.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 20:41
In my first proposal, plugin is just an external function which executed in context of Ractive's constructor like this Ractive.use(func) or Ractive's instance like this component.use(func)
This is just similar like this but more convenient:
Ractive.use(func);

func.call(Ractive);
And second major feature in my first proposal was about deduping control:
Ractive.use(plugin); // apply a plugin

....
Ractive.use(plugin);  // do nothing
All of this is just like Vue does, except that my idea to implement it also on instance level
Paul Maly
@PaulMaly_twitter
Jan 22 2018 20:48
But in the long term, our Ractive constructor could be just {} ))
Like namespace
const Ractive = require('ractive');

Ractive.use(
    require('ractive-decorators'),
    require('ractive-transitions'),
    require('ractive-extras'),
    ....
);
Only things you really need
Paul Maly
@PaulMaly_twitter
Jan 22 2018 21:01
Perhaps, we should move out of core all the things like Plugins (decorators, adaptors, transitions, etc.), most of instance and static methods (eg. array methods, toggle(), add(), findConponent() and others), SSR tools, Anchors etc. to keep the core is small and clean.
Juan C. Andreu
@andreujuanc
Jan 22 2018 21:34
maybe
i see now
its more of a "lets clean the house" sort of thing.
Paul Maly
@PaulMaly_twitter
Jan 22 2018 21:46
yep
@evs-chris Is it a bug ? playground