Bug Tracker

Modify

Ticket #5742 (closed feature: duplicate)

Opened 4 years ago

Last modified 2 years ago

Consider RunJS for jQuery code loading

Reported by: jrburke Owned by:
Priority: major Milestone: 1.4
Component: core Version: 1.3.2
Keywords: Cc:
Blocking: Blocked by:

Description

This is an alternative proposal to a $.require() function.

Code loading in the browser is a cross-library concern, and I believe it is best served by something that can be a stand-alone script, something that can be used to load even jQuery itself.

I propose RunJS as the code loader for jQuery. It is a standalone project and recently relicensed to be a tri-license like Sizzle:  http://github.com/jrburke/runjs

Here are the requirements RunJS is trying to meet:  http://github.com/jrburke/runjs/blob/master/docs/requirements.md

Here are specific instructions that detail how it can be used with jQuery now (links to a downloadable sample at the end):  http://github.com/jrburke/runjs/blob/master/docs/jquery.md

Here is a patch to jQuery that integrates RunJS, in a similar fashion as Sizzle:  http://github.com/jrburke/jquery/commit/8678f98a3a514f0a5f14a51edad970c616d46a6f

That is the bare-bones patch. I believe starting jQuery off using a stand-alone loader instead of something that is only accessible inside of jQuery (like via a $.require) will make it harder in the long term to have jquery code interoperate with other modules in the future.

Given the "no global modules" approach that is supported by RunJS, it would be possible to construct jQuery so that it would not need to create a global jQuery object. This makes it nice if multiple versions of jQuery needed to be loaded in the page with their own dependencies.

The build tools with RunJS could allow each piece of jQuery to be used on its own -- each component JS file can specify its dependencies and the RunJS build will make it easy to create custom versions of jQuery.

I am happy to make changes to RunJS if there is something that would help make it easier to integrate jQuery.

I am working with Dojo to get RunJS integrated in any future efforts for that toolkit. I can already convert the Dojo 1.4.0 code to use it, but the i18n bundles for layers is are not fully optimized yet. RunJS is capable enough to handle larger Dojo projects with many nested dependencies. I also plan on approaching other toolkits to try to get it as the baseline code loader that works well in the browser. However, with this ticket, jQuery would be the first one to integrate RunJS, if jQuery chooses to do so.

With the baseline build of RunJS integrated with today's jQuery master, the file sizes break out like so:

minified:

  • no RunJS: 68,459 bytes
  • w/ RunJS: 74,224 bytes

gzipped:

  • no RunJS: 23,100 bytes
  • w/ RunJS: 25,214 bytes

These numbers were generated by typing in "make" and looking in the dist directory.

Change History

comment:1 Changed 4 years ago by jrburke

I have changed RunJS to RequireJS now:  http://github.com/jrburke/requirejs

It implements the Transport/C proposal for CommonJS:  http://wiki.commonjs.org/wiki/Modules/Transport/C

RequireJS has better support for CommonJS modules by providing a conversion script that converts CommonJS modules to RequireJS format, but still provides an easy way to ease into modular code loading:  http://github.com/jrburke/requirejs/blob/master/docs/jquery.md

My fork of jQuery has the changes:  http://github.com/jrburke/jquery

comment:2 Changed 4 years ago by dmethvin

  • Component changed from unfiled to core

comment:3 Changed 4 years ago by jrburke

I submitted a pull request that demonstrates how a simple integration might work without having to build require() functionality into jQuery itself:  http://github.com/jrburke/jquery/commit/0178972afb7c125b36c690d483be84cbff0fcc61

Some notes from the pull request:

This is a possible way to tie in a require function for jQuery without having to build it in directly to jQuery. The require function is provided by  RequireJS. This has the following advantages:

  • Allows jQuery to be required, meaning a page can have a small bootstrap via RequireJS and load jQuery after page load.
  • The require.def in RequireJS allows multiple versions of jQuery to exist on the page in a more flexible way than jQuery.noConflict().
  • Only jQuery users who care about modular script loading have to take the require() cost.

Ideally these sorts of changes would not be needed in the jQuery source, but I do not see another way to do them, particularly since jQuery could be inlined with some other scripts that may register ready callbacks. It is not very robust to try to monkey patch jQuery after it loads. The monkey patch would also be very ugly.

The changes in src/core.js:

  • Make sure jQuery ready callbacks are not fired until any scripts require is tracking finish loading. Since require uses dynamically created, async script tag loading, the scripts can finish after DOMContentLoaded.
  • Allow ready callbacks to be registered and fired after DOMContentLoaded. This is needed since require() can be called after DOMContentLoaded (for instance, loading more modules when a button is clicked), and the user may want to keep with the normal idiom of registering jQuery ready callbacks.
  • Register jQuery as a module, which allows the multiple versions of jQuery in a page to work, and for other script modules to get a direct reference to jQuery.

I completely understand if you feel this does not fit in with jQuery's goals for script loading. I am just giving an option particularly since there are many choices with how a require function could be designed. This approach tries to allow the minimum set of changes to allow more real world experimentation with a working and deployed require() approach. If you have another approach you would like me to try, I am happy to help.

I believe RequireJS  meets the requirements I have heard for a require() in jQuery,  as of RequireJS 0.11, with some notable features:

  • RequireJS tracks CommonJS, but is optimized for the browser. It is possible to reuse modules written in CommonJS via RequireJS, allowing jQuery users the ability to leverage more code.
  • RequireJS can run in multiple environments: Rhino, Node, Jetpack and inside Web Workers.
  • Only uses dynamically created script tags for loading scripts in the browser: works across domains (for loading from CDNs) and is the most robust, browser-friendly, debug-friendly loading approach.
  • It encourages very modular, scoped code that works well with JSLint.
  • The optimization tool in RequireJS gives a server-agnostic way to optimize code for best delivery.

comment:4 Changed 4 years ago by snover

  • Status changed from new to closed
  • Resolution set to duplicate

Superseded by #7102. Closing as per jrburke.

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.