Going through my starred repos here on GitHub, I stumbled on an old idea someone had from years ago about a JavaScript Library Manager. https://github.com/jlleblanc/JavaScript-Libraries
Joomla core is massively lacking a concept like this to better track what has been loaded and what are the dependencies of each asset.
Would there be interest in a group forming to expand on this concept and potentially introduce API into 4.0 to address some of these shortcomings?
Labels |
Added:
?
|
I can't say I remember anything about that PR and I haven't looked at any
of my comments on it but looking at it today I can't say I'm a fan at all
of the JSON based asset definitions used. This stuff should be a
relatively simple PHP API. WordPress' enqueue functions somewhat cover
that for a lack of other good examples off the top of my head, but that
requires having a central registry of everything (which the JSON
definitions help with, but I don't know if that's necessarily good or how
to deal with things like needing core media known to that registry always).
On Wednesday, October 12, 2016, andrepereiradasilva <
notifications@github.com> wrote:
Maybe is possible to do something like that even in 3.x without major
refactor.Something like this:
$doc = JFactory::getDocument();$doc->addScript('jui/jquery.js', array('assetId' => 'jquery', 'version' => 'auto', 'relative' => true));$doc->addScript('jui/jquery.js', array('assetId' => 'jquery-noconflict', 'version' => 'auto', 'relative' => true));$doc->addScript('jui/jquery.js', array('assetId' => 'jquery-ui-core', 'version' => 'auto', 'relative' => true));$doc->addScript('system/modal-fields.js', array( 'relative' => true, 'requires' => array('jquery','jquery-ui','jquery.ui.core'), ));
The same could be done for addStyleSheet
Also didn't @Fedik https://github.com/Fedik also make a proposal for
this?
See #8913 #8913—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#12402 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAWfoVXovYHke-rf5rX5tScKlaB8Qrurks5qzVj6gaJpZM4KVHr7
.
@andrepereiradasilva @mbabker I've done some work here, creating an array from the building block of grunt (what is used to manage the assets in j4):
<?php
defined('_JEXEC') or die;
array(
'jquery' => array('version' => '2.1.4','dependencies' => '"codemirror"'),
'jquery-migrate' => array('version' => '1.4.1','dependencies' => '"codemirror"'),
'bootstrap' => array('version' => '~4.0.0-alpha.4','dependencies' => '"codemirror"'),
'tether' => array('version' => '1.3.7','dependencies' => '"codemirror"'),
'font-awesome' => array('version' => '4.6.3','dependencies' => '"codemirror"'),
'chosenjs' => array('version' => '1.4.3','dependencies' => '"codemirror"'),
'jquery-minicolors' => array('version' => '2.1.10','dependencies' => '"codemirror"'),
'jquery-sortable' => array('version' => '0.9.13','dependencies' => '"codemirror"'),
'jquery-ui' => array('version' => '1.12.1','dependencies' => '"codemirror"'),
'mediaelement' => array('version' => '2.22.0','dependencies' => '"codemirror"'),
'punycode' => array('version' => '1.4.1','dependencies' => '"codemirror"'),
'tinymce' => array('version' => '4.4.3','dependencies' => '"codemirror"'),
'codemirror' => array('version' => '5.19.0','dependencies' => '"codemirror"'),
);
This file then can be included and with @andrepereiradasilva code you get a nice asset manager!
i would prefer a simple PHP API too.
If we go to for a brand new Asset Management Library should deal with at least:
Maybe more that i don't remember now
Optional (depends on existence of JDocumentRendererHtmlFooter and all templates updated):
Process inline js/css declarations and do not merge them in one which IMHO, does not make sense because the js/css executing order is important.
J4 will not support IE 8 out of the box, so we can scrap this (I guess)
Process inline js/css declarations and do not merge them in one which IMHO, does not make sense because the js/css executing order is important.
I agree, but I would like to see Joomla 4 WITHOUT any line of inline script!
J4 will not support IE 8 out of the box, so we can scrap this (I guess)
Don't forget IE9 ...
See https://polyfill.io/v2/docs/features/
I agree, but I would like to see Joomla 4 WITHOUT any line of inline script!
?
Understand, but users can still have the possibility to add inline scripts/css.
I agree, but I would like to see Joomla 4 WITHOUT any line of inline script!
As long as we have things like color and font parameters in the template styles, good luck with that. Unless you're going to add overhead to that save process by recompiling CSS or whatnot (and I really wish we'd take a step back and find another way to do it without a PHP API; can't speak for SCSS based options but the LESS one is fatally broken).
Very simple to use (my vote goes to a simple PHP API) - instead of multiple methods with different behaviours (JHtml::script, addScript, addScriptVersion, addScriptDeclaration, etc)
Yes. There should be One Right Way™ to load assets. Depending on intent I count at least 3 public facing API methods and the ability to directly manipulate the asset arrays in JDocument
because they're public properties.
Add js/css "libraries" (don't render them is not needed)
This is in essence the registry I had in mind (at a minimum there is a registry containing the core library assets, think stuff in the jui
and system
directories; the language switcher module's stuff isn't part of this registry by default). I don't think we can decide what's unused; just like today if someone loads a script into the JDocument
asset arrays it should be output, but the "what's loaded for output" and "what is available" data stores will most definitely be two different things.
Add js/css files ...
For all of this stuff, I'm honestly reaching the point where we should consider having data objects representing each loaded asset versus dealing purely with unstructured associative arrays. On the one hand, the arrays make it dead easy to add arguments or attributes to the loaders, but on the other hand it gets into a black hole of needing to know what's allowed and where. Data objects are mostly cheap and still easily extendable if you want to add functionality (unfortunately that requires adding other logic too like overloading the head document renderer).
Allow to select the HTML render position (head/footer) where a script should be rendered
This gets tricky because it has to be on a by-script basis and the internals have to be smart enough to not let something be moved from the head to the end of the body if something declares it needs to be loaded in the head (think inline scripts, as much as some in this thread hate them), and that obviously will also need to drag the dependencies up too.
This is in essence the registry I had in mind (at a minimum there is a registry containing the core library assets, think stuff in the jui and system directories; the language switcher module's stuff isn't part of this registry by default). I don't think we can decide what's unused; just like today if someone loads a script into the JDocument asset arrays it should be output, but the "what's loaded for output" and "what is available" data stores will most definitely be two different things.
It's unused when on render no rendered script depends on it.
We can't also not decide what asset libraries (besides core ones) can be used. It should be flexible to add new asset libraries to the asset library "registry".
Absolutely. By default though when the request boots up the registry should be populated with the core library data so it doesn't have to be manually discovered. After that, most everything except removing a "known" library from the registry should be an option (to include changing attributes of a loaded asset like its source URL (if you wanted it to load from a CDN versus local), version query strings, attributes for the generated HTML element, etc.). What's going to be debatable is if we allow the version number to be edited (i.e. core ships jQuery 3.2.1 which has a breaking bug for some major library in it, should a developer be able to set that back to 3.1.0 as an example?).
What's going to be debatable is if we allow the version number to be edited (i.e. core ships jQuery 3.2.1 which has a breaking bug for some major library in it, should a developer be able to set that back to 3.1.0 as an example?).
humm for one side, for instance, that change can break the core js since the core scripts could not work in the old/new versions of the that jquery library. for other side, that would be great flexibily for users.
updated: For jquery, we can solve the first part by moving all core js to vanilla js ;) but we still would use other libraries
@mbabker @andrepereiradasilva so for the core shipped libraries we can have something generated automatically whenever there is an update to any of the 3rd party libs:
<?php
defined('_JEXEC') or die;
abstract class ExternalAssets{
public static function getCoreAssets() {
return array(
'jquery' => array('version' => '2.1.4','dependencies' => ''),
'jquery-migrate' => array('version' => '1.4.1','dependencies' => 'jquery'),
'bootstrap' => array('version' => '~4.0.0-alpha.4','dependencies' => 'jquery, tether'),
'tether' => array('version' => '1.3.7','dependencies' => 'jquery, tether'),
'font-awesome' => array('version' => '4.6.3','dependencies' => ''),
'chosenjs' => array('version' => '1.4.3','dependencies' => 'jquery, tether'),
'jquery-minicolors' => array('version' => '2.1.10','dependencies' => 'jquery'),
'jquery-sortable' => array('version' => '0.9.13','dependencies' => 'jquery'),
'jquery-ui' => array('version' => '1.12.1','dependencies' => 'jquery'),
'mediaelement' => array('version' => '2.22.0','dependencies' => 'jquery'),
'punycode' => array('version' => '1.4.1','dependencies' => ''),
'tinymce' => array('version' => '4.4.3','dependencies' => ''),
'codemirror' => array('version' => '5.19.0','dependencies' => ''),
);
}
}
Similar thing must be implemented for 3rd PD so whenever a new asset is installed this goes to a json and with some similar function we end up with another similar array object
What do you think?
As long as we have things like color and font parameters in the template styles
There is a custom.css for all these...
think inline scripts, as much as some in this thread hate them
I have some working code for that, BUT the default position for the scripts needs to be the end of the document not the head...
There is a custom.css for all these...
Is the expectation that the user be able to write the CSS themselves (which is what these parameters are basically doing, but inline)? If so then you can dump every style related parameter we have and let the user do that.
I don't think we should be hooking template style editing up to a CSS compiler in any manner (even if it's just us building a CSS snippet and writing it to a file). Honestly it seems like it's too error prone (how do you handle a user making changes to the generated CSS file then saving the parameters again as an example).
the default position for the scripts needs to be the end of the document not the head...
Maybe. If you can safely build the output in a way to support it that way and have the awareness it needs to move stuff to the head then sure, we can do that. As structured today though, that is an impossible goal without having something like Sourcerer in core and giving all users access to the PHP API from the WYSIWYG editor. If you default everything to the end of the body but have no way for a user to create inline scripts dependent on jQuery then you've created a massive barrier to use.
How about, for 4.0, have a new Assets class (and AssetsHelper class if needed)?
This class would have a list of all assets js/css and public methods to add/remove/get asset libraries, to add/remove/get assets and to render assets. All the rest would not be accessible.
Asset would be all js external/inline js/css.
Then, on document html render, JDocument would call the Assets::Render() method.
if ok with this, one question remains: should this class be in joomla libraries folder or in the joomla framework itself?
CMS libraries (libraries/src
directory and namespaced). The closest thing the Framework has to a rendering platform is the bridge package that lets you use other rendering engines, no point in adding an asset manager when all that stuff should be done through the bridged package.
ok so it seems that would be the general idea.
@mbabker can you add @andrepereiradasilva to the template branch, so he can see the work on the assets (maintenance) already done. Maybe we can extract some stuff from there...
I try to get parts of my brain together and write some thought also
And explain some stuff behind #8913
For good asset manager need:
Registry of available Assets and know their dependencies.
Without knowing what asset are available in the system we end up to add all possible Assets in each layout, that is actually the same that we have now:
JHtml::_('stylesheet', 'extension/style1.css', false, true);
JHtml::_('script', 'extension/script1.js', false, true);
JHtml::_('script', 'extension/script2.js', false, true);
With the registry, things become a looooot easier.
We just add layout specific Asset and it will pick up all dependencies (if there any) from Registry.
JHtml::_('asset.load', 'layoutAsset');
// or inline code
JHtml::_('asset.styleDeclaration', $content, array('blablaAsset'));
Developer even do not need to remember which dependencies should be there.
Important note.
JAssetFactory
do not tries to resolve dependencies and do not attach any asset to the Document
until the final head rendering, so it performance safe on some point of view.
On start I had idea use Bower, and its json but in the end I found it totally unflexible and useless for B/C Asset manager.
So I made joomla.asset.json
where define all assets and its dependencies per extension/template.
Well, it not required to be JSON, it can be anything, XML, PHP as @dgt41 wrote, anything.
I stopped on JSON because it is more easy to parse/use, and I suppose that the frondender are less afraid of JSON than PHP or XML
Suggested version support fancy stuff like language:
"css": [
"template.css",
"language/[LANGUAGE_TAG]/[LANGUAGE_TAG].css",
"custom.css"
]
And if we allow to use custom JAssetItem
per Asset Item (look JAssetFactory::prepareAssetInstance) then we can do even more fancy stuff (but question whether we need it)
It is "Tales from the Crypt". To be honest I not very understand the panic around this.
Most important is to be able use defer
, then do not need all this trash at the footer
However in asset definition we can add an option, something like "allowFooter".
So Asset with allowFooter:true
and without dependency can be placed at the footer, but if Asset has dependency on the script that cannot be in the footer, then it will be in the head.
Status | New | ⇒ | Discussion |
Category | ⇒ | Libraries |
Before start doing something useful we need to make decision about the Asset Registry.
But keep in mind, the Asset it is NOT a Single file, it is a Files collection.
Example Bootstrap contain js and couple css files.
The Registry should provide 2 important thing:
After some tests I think an auto generated asset ( @dgt41 example from previous comment) will not work as we expect.
For example look at /vendor/bootstrap
, there js bootstrap.min.js
and css bootstrap.min.css
, bootstrap-grid.min.css
, bootstrap-reboot.min.css
, or jQuery, there a loot more js files.
Then what loadAsset()
should load when we call loadAsset(bootstrap)
?
Possible way is to split asset to sub-asset, or multiple asset like:
// main asset
'bootstrap' : {
dependency: ['bootstrap.css', 'bootstrap.js']
}
// sub assets
'bootstrap.js' : {
js:['bootstrap.min.js']
}
'bootstrap.css' : {
css:['bootstrap.min.css']
}
So in the code if need just css we call loadAsset(bootstrap.css)
, and if later need to load ALL then we (or 3d extension) can call loadAsset(bootstrap)
.
But I think it is rare case, most Assets not require "sub-asset". Like chosen:
chosen: {
css: ['chose.css'],
js: ['chose.js'],
dependency: ['jquery']
}
And I think we do not need to make asset for all in /media, but would be good to make it for /system
and /vendor
for start.
It can be PHP, JSON, XML anything, but should be clear and easy to create for non "programmers".
Thoughts?
@Fedik you picked the worse example, bootstrap :(
Anyways let me write my thoughts here, starting with what is more likely to become the norm in the next years (for me it's more important the project makes a decision not upon current best practices but based on the upcoming technologies that will flourish the next years).
Javascript: ES6 and particularly modules are almost here: https://t.co/4x3bR2XnoJ
Also the current state of the platform: http://caniuse.com/#feat=es6-module (yes most browsers are supporting this with a flag, but that could change the comping months)
What this means is that the web is going towards a more modularised approach, instead of the current trend (use web pack to create a file with all the scripts a view/page needs). let me give an example here: let's say a page needs multiselect.js
and multiselect.js
has a dependency in core.js
in reality the first line of multiselect.js
will be:
import {Joomla} from './core.js';
The tricky part is ES5 browsers (the article above showcases a solution) and the paths
CSS: here things are a bit more easy, most of the times one file per resource needed.
Now on the Asset approach: the decision here fundamentally needs to answer how granular this functionality needs to be. Eg if you need to give dev's the ability to fine tune things (also means they need to read the docs and figure out what assets their page needs) then probably we need to give support for e.g. bootstrap.modal.js
which will translate to: load the common js and then load the modal.js...
PS All I wanted to highlight here is that the platform itself already solved the dependency control problem, so instead us trying to figure out a different solution, let's embrace the platform and use it as it's the common ground!
@dgt41 ES6 is a good target, but I guess for Joomla 5+
Currently I am hardly imagine how ES6 module can live in CMS (not only Joomla). Maybe it is cool for "self made" project, but for CMS, it can be hard.
And problem not only ES5 browsers.
Your example in real life will be:
import {Joomla} from './media/system/js/core.min.js';
I guess you already see the problem
This is not allow to use our override system, and all paths are fixed in the file.
ES6 modules do not have "advanced path resolving".
For stand alone project you can use "webpack", and combine all modules to single file, but it will be problem for CMS.
Possible solution could be generate init.js
for each page, with something like:
import * from './media/system/js/core.min.js';
import * from './media/vendor/foo/js/scrip1.min.js';
...
...
import * from './media/vendor/fooXX/js/scripXX.min.js';
But in same way we can just include all files in the document.
Alternative to ES6 modules (for now) is use requirejs
, wich allow to define the path to each module in the config (http://requirejs.org/docs/api.html#config). And Joomla! just need to generate this config.
But, for both solutions, we still need to know (at PHP side) which scripts/styles are available, and their dependencies. And for this we need to have the Assets repository.
Also I do not think we can handle dependencies only by use ES6 modules or requirejs
, for CMS need to be something in "backend".
btw, nor ES6 nor requirejs do not handle styles dependencies, so you still need to add them manually
@Fedik yeah the override bit that joomla got it's kinda hard to be reproduced in native ES6 modules unless we override the default browser implementation (ok, that's going a bit too far...)
I guess requirejs
+ some Assets management (PHP side) is the only viable way here.
Although, few months ago I did that thingy with the PHP array, I'm in favour of a descriptor file JSON format, as you suggested the other day. Let's not over engineer this, simple solutions are always the best ones (but not oversimplified)
Labels |
Added:
J4 Issue
|
Unfortunately this is going nowhere.
Status | Discussion | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2018-07-23 19:03:03 |
Closed_By | ⇒ | mbabker |
Maybe is possible to do something like that even in 3.x without major refactor.
Something like this (just an example):
The same could be done for addStyleSheet
Also didn't @Fedik also make a proposal for this?
See #8913