3 namespace Drupal\http2_server_push\Asset;
5 use Drupal\Core\Asset\AssetCollectionRendererInterface;
6 use Symfony\Component\HttpFoundation\RequestStack;
9 * Decorates the JS collection renderer service, adds Server Push.
11 * @see \Drupal\Core\Asset\JsCollectionRenderer
12 * @see \Drupal\http2_server_push\Render\HtmlResponseAttachmentsProcessor
14 class JsCollectionRenderer implements AssetCollectionRendererInterface {
16 use AssetHtmlTagRenderElementTrait;
19 * The decorated JS collection renderer.
21 * @var \Drupal\Core\Asset\AssetCollectionRendererInterface
23 protected $jsCollectionRenderer;
28 * @var \Symfony\Component\HttpFoundation\RequestStack
30 protected $requestStack;
33 * Constructs a JsCollectionRenderer.
35 * @param \Drupal\Core\Asset\AssetCollectionRendererInterface $js_collection_renderer
36 * The decorated JS collection renderer.
37 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
40 public function __construct(AssetCollectionRendererInterface $js_collection_renderer, RequestStack $request_stack) {
41 $this->jsCollectionRenderer = $js_collection_renderer;
42 $this->requestStack = $request_stack;
48 public function render(array $js_assets) {
49 $elements = $this->jsCollectionRenderer->render($js_assets);
51 $request = $this->requestStack->getCurrentRequest();
52 $link_headers = $request->attributes->get('http2_server_push_link_headers', []);
53 foreach ($elements as &$element) {
54 if (!static::isScript($element)) {
58 // Locally served JS files that are sent to all browsers can be pushed.
59 if (isset($element['#attributes']['src']) && static::hasRootRelativeUrl($element, 'src') && static::isUnconditional($element)) {
60 $link_header_value = '<' . $element['#attributes']['src'] . '>; rel=preload; as=script';
61 $link_headers[] = $link_header_value;
63 // @todo When this is moved into Drupal core, consider allowing bubbling
64 // of bubbleable metadata from the return value of
65 // \Drupal\Core\Render\HtmlResponseAttachmentsProcessor::processAssetLibraries
66 // so this line of code can work, which would mean we would no longer
67 // need to use request attributes. (The problem is that a key assumption
68 // is that rendering set of asset libraries to HTML that loads CSS/JS,
69 // no further attachment bubbling happens. That's a fine assumption, but
70 // this module is the first and sole exception.)
71 //$element['#attached']['http_header'][] = ['Link', $link_header_value];
74 $request->attributes->set('http2_server_push_link_headers', $link_headers);