Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
asset library system
Priority:
Critical
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
26 Nov 2014 at 13:36 UTC
Updated:
15 Jan 2015 at 01:00 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
wim leersComment #2
wim leersComment #3
wim leers#2378095: Convert all remaining attached individual CSS/JS assets to attached asset libraries landed.
Comment #4
wim leersWith #2382557: Change JS settings into a separate asset type being very close to RTBC, I've already begun working on this patch.
Comment #5
wim leersAbout this patch, besides the obvious changes:
AttachedAssetsTest, which is a hugely cleaned up version ofCascadingStylesheetsTestandJavaScriptTest(which still contained things like#attached_library, tests that\Drupal\system\Tests\Asset\CssGrouperUnitTestalready did… but more comprehensively and as a unit testMergeAttachmentsTestwas deleted.The smaller patch is the actual one, but for now it needs to include #2382557: Change JS settings into a separate asset type.
Comment #7
wim leersHow this manages to cause 2 failures (1 locally) in
\Drupal\comment\Tests\CommentTokenReplaceTestis beyond me.I'll just wait for #2382557 to land before debugging this further.
Comment #8
catchAgreed on removing inline js. When I've done site audits a very common problem is a poorly written contrib or custom module sticking inline js on the page instead of using Drupal.settings. Then that inline js because it is added in amongst all the other js on the page results in two aggregates (one before the inline js, one after) where there originally would have been one. So supporting that as a regular asset type makes it very easy to mess up the front end performance of a site.
I wonder a little bit about inline CSS - some rendering strategies try to group layout CSS inline so that it gets downloaded very, very quickly as part of the initial HTML request. I guess that's something that would happen in the css aggregation/rendering stages anyway though and no way a module can do this in #attached anyway.
Comment #9
wim leersExactly!
It'd have to be an alternative implementation of the CSS asset renderer service (
AssetCollectionRendererInterface), which is totally possible in D8 :)Comment #10
mikeytown2 commentedI agree that inline css/js messes up aggregates, but this can be fixed; in advagg there is a setting that forces all inline code to be at the bottom, there is another setting that forces all external code to be at the top, and a 3rd setting that will group all browser conditionals together; these are all things that can mess up aggregates. Having a standard way to add in inline code is nice as it allows one an easy way to modify it; be it minification or delayed execution or modification of the code if it was added by a module.
Comment #11
wim leers#2382557: Change JS settings into a separate asset type was committed! Now this is unblocked.
Comment #12
wim leersStraight reroll of
assets_only_libraries-2382533-5-do-not-test.patchin #5.Comment #13
berdirThis is not correct, this has to be triggered by javascript.
The point of doing it in javascript is that it also works when delivering pages from page page/varnish.
Comment #15
wim leers#13: good point. I had totally forgotten about that.
Comment #16
wim leersComment #18
wim leersI'm an idiot. I addressed #13 but then failed to revert the test changes…
Comment #20
wim leers#2347999: DrupalUnitTestBase is deprecated, replace with KernelTestBase broke this. Straight reroll.
Comment #21
wim leersSelf-review time. Plus patch to fix it.
This looks weird.
{@inheritdoc}This is obsolete, a
KernelTestBase's config changes don't persist to the actual site.Missing trailing period.
and CSS
Too much whitespace.
s/preproccess/preprocess/
s/the same library/libraries with the same name/
Formatting problems.
Whitespace problem.
Comment #22
nod_In common.inc there is still
What's the plan for that clean-up?
in _drupal_add_library:
Seems to me that $data will always be numeric and $options will always be an array because we declare everything through libraries and in the YML, js and css are always objects, not a mix of
[filename, filename]and{filename: options, filename: options}:Tried it and looks like the following is enough:
in JsCollectionRenderer
I so want those gone, but looks like we still "need" it for drupalSettings. Out of scope though.
In History module
$build['#attached']['drupalSettings']['history']['nodesToMarkAsRead'][$node->id()] = TRUE;can we have
$build['#attached']['drupalSettings']['history']['nodesToMarkAsRead'][] = $node->id();Instead? It's the ajaxPageState situation again, are we really worried about duplicates here?
Looks good to me otherwise :)
Comment #23
wim leersGood question. Back then, I thought this issue would be a great place to finally remove
_drupal_add_(css|js)(). Turns out this isn't a great place: the patch is already >110 KB because of the essential test coverage updates/fixes.Now #2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests seems like the best place to do that. So updated the todo to link to that issue instead.
Great catch! :) I didn't bother fully simplifying here (I copied it *verbatim*), because the big simplification will happen in #2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests, where
_drupal_add_(css|js|library)()will go away. But if we can do this now already, that'll make the next patch simpler to review, so +1, made that change.+1, and indeed out of scope.
Yes, we are worried about duplicates and hence other
drupalSettingsoverwriting these. It's up to us to provide unique keys so that some other attacheddrupalSettingsdon't overwrite ours.Comment #25
wim leersOops.
Comment #27
wim leersTurns out that this statement:
Seems to me that $data will always be numeric and $options will always be an array because we declare everything through libraries and in the YMLwas not entirely true. Quick Edit module has a
hook_library_alter()for which this is not true. Hence the test failures in #25. Since it's the only violation in core, it's easy enough to make it comply as well.Comment #28
dawehnerThis patch looks really great. It reduces a lot the amount of different ways how to do things: 'css' vs 'library', 'library' vs. 'inline' ...
Just curious, is this example still valid?
Comment #29
wim leersYep, that was the goal: declarativeness, simplicity, consistency.
Good question. The answer is: yes and no.
_drupal_add_js()has been prefixed with an underscore since January 8, 2014 and been marked deprecated since June 29, 2013. We always kept the docs intact, because technically, all of this still works, but instead of being a public API, it's now a private API that can change without notice. The next step is to remove_drupal_add_(css|js|library)(), which will happen in #2368797: Optimize ajaxPageState to keep Drupal 8 sites fast on high-latency networks, prevent CSS/JS aggregation from taking down sites and use HTTP GET for AJAX requests.Comment #30
nod_Better tests, better DX, everything still working. No more complains.
Basically the patch changes history module to not use inline JS, do the API removal change and do lots of test improvments.
Comment #31
wim leersUpdated IS, added beta evaluation.
Comment #32
catchOnly had nitpicks, fixed on commit:
associative
Not introduced by the patch, just moved around, but 'the the'.
Everything else looks great. Simplifies the system itself and makes things more consistent for themes and modules. Also unblocks both the AJAX pagestate optimization and doing asset generation in separate http requests.
Committed/pushed to 8.0.x, thanks!
Comment #34
Jeff Burnz commentedHow do I add a dynamically generated stylesheet that could have any name?
Comment #35
wim leersJeff: Define "dynamically generated"?
hook_library_info_alter()to alter the library you care about and add your randomly named CSS file.hook_library_alter()to alter the library you care about and add your randomly named CSS. Examples includelocale_library_alter()andquickedit_library_alter().Once #2378737: Consider not executing hook_library_(info)_alter() *per* library, but once for all lands, they'll have the exact same signature, they'll just be executed at different times and with different frequencies.
Comment #36
Jeff Burnz commentedOne of my modules and a theme can build stylesheets - there is no library. I can never know the name of these files in advance, it depends on the user input.
User saves a form, file is generated and saved to the file system. I save the path/name of file etc and load it at the appropriate time.
How can I load these files?
Comment #37
andypostJeff, you will need to manage libraries for each file
Comment #38
catchIf there's no library for the file to go in, then a completely new library could be added dynamically once #2358981: Provide a mechanism for dynamic library declarations is in.
Comment #39
wim leersOr, for now, you could have a library with a dummy file that is altered away.
Comment #40
Jeff Burnz commentedJust be aware of this #2050269: hook_library_info_alter() is not called for themes
I'm going to have a crack at solving my issue with hook_css_alter(), since that is probably the only real option I have for now.
What we really need is #2358981: Provide a mechanism for dynamic library declarations
Comment #41
arla commentedI think this change record will have to be updated: drupal_add_css(), drupal_add_js() and drupal_add_library() removed in favor of #attached
Perhaps others as well.
Comment #42
andypostcomment does not depends on history. is this fine?
Comment #43
hass commentedFrom case intro this issue may the the root cause of #2391025: Add support for inline JS/CSS with #attached
I read Remove support for inline CSS and JS assets (see #5.3 + #8 for details). what is a clear failure!
Comment #44
Jeff Burnz commentedHeres one of my cases that is, as I see it, very difficult to work around since this change.
I used inline JS for live reload, Typekit fonts and other things, this change forced me to use the asynchronous Typekit method which always gives a FOUT and is pretty dam hard to avoid even using their state classes. Inlining the JS is very fast method for Typekit, same goes for Google fonts, if you inline the link its super fast, but I cannot do that now (users select their font in settings), and I have to use their asynchronous JS method which gives a FOUT most of the time and there are no state classes at all.
I'm looking for ways around these issues, I understand the concerns in the issue and there maybe ways to get around the FOUT's etc, but this has made things much more difficult for front enders.
Comment #45
nod_See the 'file-inline' type that we could use to fix this. Need to open an issue about it.
Comment #46
hass commentedWhat is 'file-inline' ? I need full inline code without files. The inline code I'm adding may dynamic per user, too.
Comment #47
nod_Sorry was on my phone couldn't find the issue. What I mean is the "inline js" part of this comment #2298551-9: Documentation updates adding/adjusting inline/external JS in themes.
I'm replying in the other issue. I don't see a reason to go back on the principle of this issue. Inline scripts are not considered assets anymore, it's just random HTML bits, that can be added by
#markupin the body of the page or with#attached => html_head.Comment #48
bzrudi71 commentedI read a lot regarding the latest changes to js/css libraries here, and in all the related issues. I still can't find a solution for my problem. Consider this - I use a field formatter/widget for displaying/editing a map (Google/OSM). This map is displayed on every node. All the js required for the map itself is defined in my module.libraries.yml (igwmap.formatter.js), easy and clear. For the map layers, for example an GPX track overlay, all the required js is stored in a file during node save, so each single nid has a separate js file to load. For now I did this (in FieldFormatter):
where $item->static_js is the full path to the js file for the current node to load, so something like this files/tracks/js/node_1234.js. I do not see how to work around this by the provided examples, so this seems like a regression to me. Also non of the hooks_library_something() seem to do the job. I see why we need these changes and they all make sense to me, but leave me with a problem I have no idea how to get around. Any suggestions welcome :-)
Comment #49
wim leersInstead of saving the data to a JS file and loading that file, save the data to a file or the DB and load it as JS settings. Or, store it as JSON, then let your JS load that JSON. Or, since you're using
#markupalready, include that JSON in the markup.Plenty of options :)
Comment #50
bzrudi71 commentedThanks @Wim! I did it some other way, but you pointed me to the right direction :-)
Comment #52
yesct commentedmaking tag the more common one so we can delete the lesser used one so it does not show in the autocomplete