bigskysoftware / intercooler-js

Making AJAX as easy as anchor tags
http://intercoolerjs.org
MIT License
4.78k stars 235 forks source link

Remove jquery dependency? #157

Closed pwFoo closed 7 years ago

pwFoo commented 7 years ago

Hi,

I love intercooler. It's easy to use and works great! intercoolerJS itself isn't too big, but it's bloated by jQuery dependency.

How much jQuery code is used? Is it possible to move IntercoolerJS to JavaScript or a smaller library (MinifiedJS, UmbrellaJS? Any plans to remove the jQuery dependency?

Regards

OvermindDL1 commented 7 years ago

jQuery is not really necessary for most of it except for selectors used via headers, so if those could be re-done...

1cg commented 7 years ago

There are a few areas that are tricky around selectors (e.g. pseudo-selectors) and so on. ic-action relies on jQuery semantics too.

If I redo it in vanilla JS, it will be a major version bump because keeping all the small semantics the same would be impossible.

I'd like to do it, it will just take me some time. If anyone is interested in working with me on it, that would help motivate me. :)

Cheers, Carson

On January 23, 2017 at 7:45:17 AM, OvermindDL1 (notifications@github.com) wrote:

jQuery is not really necessary for most of it except for selectors used via headers, so if those could be re-done...

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/LeadDyno/intercooler-js/issues/157#issuecomment-274523374, or mute the thread https://github.com/notifications/unsubscribe-auth/AAcov1JSizAViF_UFOUbX5gZTlO2MYYiks5rVMsLgaJpZM4Lq2kV .

pwFoo commented 7 years ago

jQuery independent would be awesome. I haven't much experience with JavaScript, but I would try to help with it if possible.

If it would be complicated to do it without selectors maybe a smaller library would be possible? jQuery alternatives.

Zepto should be jQuery compatible and is a lot of smaller and played with MinifiedJS one year ago.

IntercoolerJS should keep size in mind without or with just a small library dependency :)

OvermindDL1 commented 7 years ago

Honestly I'd say start with a PR that removes as much jQuery as possible without changing semantics. That will make it significantly easier to identify the areas it is required for total replacing. :-)

1cg commented 7 years ago

Mockjax would be a tricky bit to replace.

Looking at the jQuery ajax function is... a bit terrifying.

OvermindDL1 commented 7 years ago

Looking at the jQuery ajax function is... a bit terrifying.

It was useful back in the day because browser ajax implementations were.. not similar.

However raw javascript ajax is dead simple if you do not mind ignoring <IE9. ^.^

1cg commented 7 years ago

There is an internal hackathon on February 9th & 10th at one of my companies.

I will do some proof of concept work then.

WillRubin commented 7 years ago

>> Looking at the jQuery ajax function is... a bit terrifying.

I know you can look at the source, but here's a nice reference for a bunch of the conversions. You Might Not Need jQuery

Edit: You can probably leave Mockjax as it's only a dev/demo thing. Unless there's a better mocking library anyway.

keybits commented 7 years ago

Not sure how relevant this is, but browser support for Fetch (https://fetch.spec.whatwg.org/) is now pretty good, having just landed in Safari 10.1 (http://caniuse.com/#feat=fetch).

pwFoo commented 7 years ago

Found a small ajax solution. Minified 1.66 KB. https://github.com/fdaciuk/ajax

Also play with a super-tiny jQuery like selector / event helper. https://github.com/dciccale/ki.js

pwFoo commented 7 years ago

Fetch was new to me, so I first found the polyfill and not the new native feature ;) There is a fetch polyfill (minified 7.18 KB) to improve browser support, but could be a problem with mobile browsers.

Fetch sounds great, but polyfill shouldn't be loaded for each client. Just if it's needed...

Looked at simple XMLHttpRequest based ajax scripts like

During search a small solution to replace jQuery I found the ki.js core (490B), ki.js extensions (just as examples how to extend ki.js core) and a nice and small ajax script (1.59 KB).

I replaced the simple querySelectorAll call with a improved query function and converted (should be improved I think...) the ajax script to a ki.js plugin. Both together have a minified file size of ~2KB with

Maybe ki.js + ajax (plugin) could be improved and used as base? Or just the ajax script because it's small and support all needed methods (get, post, delete, ...)?

So should it go the "traditional" XMLHttpRequest way or fetch?

1cg commented 7 years ago

Right now I'm thinking we should create a minimum jQuery-compatible layer that includes just the implementation needed, like Angular does.

Full jQuery is 84k minified, 28k gziped, so I'd like to target a minified version of under 10k minified.

pwFoo commented 7 years ago

A fast walk through intercooler source to find some of the jQuery methods.

show / hide
prepend / append
remove
empty

addClass / removeClass
attr

trigger
closest
each

find
children
filter
is

scrollTop
height
offset
animate

ki.extend.js have some of the needed methods.

addClass
removeClass
toggleClass
hasClass
show
hide
css
attr
removeAttr
hasAttr
first
last
get
before
after
text
html
append
prepend
remove
parent
trigger
is

Most of the plugins are copied from You Might Not Need jQuery. But features should be compared with plainjs.com (example show / hide) because some need more than that be work as expected.

I would love I minimal ki.js core with extensions added as needed. The minimum jQuery-compatible layer should be a separate project and included / additionally loaded with intercooler.

pwFoo commented 7 years ago

At the moment I review the plugins and reduce code (remove old browser support <IE9).

1cg commented 7 years ago

Are you actively working on a minimal jQuery? :)

pwFoo commented 7 years ago

Yeah... just for fun at the moment... Yes g

I'm new with JavaScript, but maybe you could review and improve my code later? And maybe use it as jQuery replacement for intercooler? ;)

1cg commented 7 years ago

Excellent! I'm going to put some time into this next week during a hackathon, please share whatever results you have along the way.

pwFoo commented 7 years ago

I'll share it later today.

pwFoo commented 7 years ago

I like the ki.js based library I'm working on, but maybe consider usage of jqLite. It's ~20kb minified and some parts are working.

Missing method:

Uncaught TypeError: $.map is not a function

But an own and even smaller replacement would be nice to have ;)

UPDATE Custom library needs a attr() which should be easy to do. I'll test it out later.

pwFoo commented 7 years ago

This two lines look strange to me in intercooler.js?

var USE_DATA = $('meta[name="intercoolerjs:use-data-prefix"]').attr("content") == "true";
var USE_ACTUAL_HTTP_METHOD = $('meta[name="intercoolerjs:use-actual-http-method"]').attr("content") == "true";

attr() executed on a non existing object because there isn't a selector matching element ? Disabled both lines and fail at the $.map method same as jqLite.

OvermindDL1 commented 7 years ago

$() selectors in jquery return a list of matches (with functions on the list for ease of use), calling attr on that list if no results will return undefined or "" or something (I forget), so comparing that to "true" (why is it == instead of ===?!) will be false, so it works. :-)

pwFoo commented 7 years ago

Ok, but clean way would be to check it instead of get it at this point?

The simple attr() method could be extended to handle this.

Fixed it with an simple workaround.

$.prototype.attr = function(a, b) {
    if (this.length === 0) return false;
    return this.each(function(c) {
      c.setAttribute(a, b);
    });
/*
    return b === []._ ? this[0].getAttribute(a) : this.each(function(c) {
      c.setAttribute(a, b);
  });*/
};
pwFoo commented 7 years ago

Fixed map() with the custom library, next could me bigger problem to solve g

Uncaught TypeError: $.ajaxTransport is not a function

I don't know anything about $.ajaxTransport. The ajax() method included as plugin is documented here: https://github.com/fdaciuk/ajax

I share the code soon...

pwFoo commented 7 years ago

I haven't experience how to fork / manage a git repo... So it's done quick and dirty. :)

Renamed the modified / extended ki.js fork jqSlim. All plugins (ajax too) are included in the plugins directory. I also forked the ajax module and updated the dev branch. jqSlim-ajax.

My first steps with JavaScript... Feedback to the code is welcome ;)

@carsongross @OvermindDL1

pwFoo commented 7 years ago

minified / gzipped jqSlim core + all plugins by refresh-sf.com

Input: 13.98 KB Output: 4.19 KB Gzip: 1.58 KB Delta: -12.40 KB (-88.68%)

jqSlim-all.min.js.gz

pwFoo commented 7 years ago

The following plugins are not updated / included at the moment:

but should be available at https://github.com/james2doyle/ki.extend.js/tree/master/build/parts. Just copy&paste with some optimizations.

The file sizes above including fadeIn / fadeOut:

Input: 1.54 KB Output: 563 bytes Gzip: 268 bytes

So library size could be reduced if needed...

Animations aren't included. Maybe there are a small modules to convert as plugin like animateplus or TinyAnimate. But I haven't looked into animations or animation modules yet.

pwFoo commented 7 years ago

Added functions (c&p, renamed variables):

So $.ajaxTransport() is still missing.

pwFoo commented 7 years ago

@carsongross Would it possible to move from $.ajaxTransport() to $.ajax() method? Maybe that would be compatible to zepto.js (~10kb) and jqSlim / ki.js (~5kb at the moment) too. jqLite haven't a ajax module included with a minified size of ~20kb :(

1cg commented 7 years ago

Can you create a gist with your code?

I think we can just grab the ajax module directly from jQuery. IIRC it wasn't very big.

1cg commented 7 years ago

I'm going to be working on intercooler today, so if you'd like to jump on https://gitter.im/intercooler-js/Lobby and chat, I'll be there

pwFoo commented 7 years ago

The jqSlim minimal approach isn't that easy and have some problems. So Zepto with zepto.mockjax should be easier to do at the moment.

Found another minimal library You could test for compatibility...

jBone. JavaScript Library for Events and DOM manipulation. Replaces jQuery for Backbone. http://jbone.js.org/

1cg commented 7 years ago

We now offer zepto compatiblity:

https://github.com/LeadDyno/intercooler-js/commit/9bd1162ecebe5472f200d06bff34e81ac5d3023c

I'm declaring that good enough, with a total gzipped javascript infrastructure of 18kB for zepto + intercooler.

pwFoo commented 7 years ago

Tested with my existing intercooler setup. zepto + intercooler zepto-compat (minimal tested at the moment) and it works fine 👍 Thanks!

Playing with my own library (local only build) just for fun g 1,04kb gzipped without ajax at the moment ;)

jboynyc commented 7 years ago

I've been test driving IntercoolerJS with Zepto and ran into an as-of-yet undocumented limitation. Just thought I'd share in case it helps developing this branch.

<html lang="en">
  <head>
    <title>IntercoolerJS + Zepto Experiment</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.js">
    <script src="https://rawgit.com/madrobby/zepto/master/src/data.js">
    <script src="https://rawgit.com/LeadDyno/intercooler-js/ic-zepto-compat/src/intercooler.js">
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="two-thirds column">
          <input name="qry" ic-post-to="/" ic-trigger-on="keyup changed" ic-trigger-delay="1s" ic-target="#sidebar" type="text">
        </div>
        <div class="one-third column" id="sidebar">
        </div>
      </div>
    </div>
  </body>
</html>

POST data that is sent when typing something into the input field:

ic-request=true

ic-element-name=qry
ic-id=1
ic-target-id=sidebar
ic-trigger-name=qry
ic-current-url=/
_method=POST

As you can see, the crucial bit -- the contents of the input field -- is not transmitted in the POST request.


Here's what is sent over the wire when I replace Zepto with Jquery:

ic-request=true
qry=This+is+how+we+do+it
ic-element-name=qry
ic-id=1
ic-target-id=sidebar
ic-trigger-name=qry
ic-current-url=/
_method=POST
1cg commented 7 years ago

Thanks, I will handle this case in the next release.

Cheers, Carson

On February 21, 2017 at 5:01:37 AM, John Boy (notifications@github.com) wrote:

I've been test driving IntercoolerJS with Zepto and ran into an as-of-yet undocumented limitation. Just thought I'd share in case it helps developing this branch.

IntercoolerJS + Zepto Experiment Githubissues.
  • Githubissues is a development platform for aggregating issues.