From 5e3014d508534454db11607150c2068ca2956f66 Mon Sep 17 00:00:00 2001 From: Guillaume Briday Date: Wed, 12 Jun 2019 14:06:51 +0200 Subject: [PATCH 1/5] Add a preload_pack_asset helper --- docs/webpack.md | 16 +++++++++++++++- lib/webpacker/helper.rb | 15 +++++++++++++-- test/helper_test.rb | 6 ++++++ test/test_app/public/packs/manifest.json | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/webpack.md b/docs/webpack.md index 63a74e66a..82cc3909d 100644 --- a/docs/webpack.md +++ b/docs/webpack.md @@ -277,7 +277,7 @@ environment.splitChunks() environment.splitChunks((config) => Object.assign({}, config, { optimization: { splitChunks: false }})) ``` -Then use, `javascript_packs_with_chunks_tag` helper to include all the transpiled +Then use the `javascript_packs_with_chunks_tag` and `stylesheet_packs_with_chunks_tag` helpers to include all the transpiled packs with the chunks in your view, which creates html tags for all the chunks. ```erb @@ -304,6 +304,20 @@ get duplicated chunks on the page. For the old configuration with the CommonsChunkPlugin see below. **Note** that this functionality is deprecated in Webpack V4. +#### Preloading + +Before preload or prefetch your assets, please read [https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content). + +Webpack also provide it's own methods for preload or prefetch [https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c](https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c). + +You can preload your assets with the `preload_pack_asset` helper. + +```erb +<%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> +``` + +**Warning:** You don't want to preload the css, you want to preload the fonts and images inside the css so that fonts, css, and images can all be downloaded in parallel instead of waiting for the browser to parse the css. + ### Add common chunks (deprecated in Webpack V4) The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in the cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from the cache, rather than being forced to load a larger bundle whenever a new page is visited. diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index 792892353..fb90abab9 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -78,12 +78,23 @@ def javascript_pack_tag(*names, **options) # DO: # <%= javascript_packs_with_chunks_tag 'calendar', 'map' %> # DON'T: - # <%= javascript_packs_with_chunks_tag 'calendar' %> + # <%= javascript_packs_with_chunks_tag 'calendar' %> # <%= javascript_packs_with_chunks_tag 'map' %> def javascript_packs_with_chunks_tag(*names, **options) javascript_include_tag(*sources_from_manifest_entrypoints(names, type: :javascript), **options) end + # Creates a link tag, for preloading, that references a given Webpacker asset + # In production mode, the digested reference is automatically looked up. + # See: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content + # Example: + # + # <%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> # => + # + def preload_pack_asset(name, **options) + preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) + end + # Creates a link tag that references the named pack file, as compiled by webpack per the entries list # in config/webpack/shared.js. By default, this list is auto-generated to match everything in # app/javascript/packs/*.js. In production mode, the digested reference is automatically looked up. @@ -120,7 +131,7 @@ def stylesheet_pack_tag(*names, **options) # DO: # <%= stylesheet_packs_with_chunks_tag 'calendar', 'map' %> # DON'T: - # <%= stylesheet_packs_with_chunks_tag 'calendar' %> + # <%= stylesheet_packs_with_chunks_tag 'calendar' %> # <%= stylesheet_packs_with_chunks_tag 'map' %> def stylesheet_packs_with_chunks_tag(*names, **options) if current_webpacker_instance.config.extract_css? diff --git a/test/helper_test.rb b/test/helper_test.rb index d326228a2..0d6692e28 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -79,6 +79,12 @@ def test_javascript_pack_tag_split_chunks javascript_packs_with_chunks_tag("application") end + def test_preload_pack_asset + assert_equal \ + %(), + preload_pack_asset("fonts/fa-regular-400.woff2") + end + def test_stylesheet_pack_tag_split_chunks assert_equal \ %(\n) + diff --git a/test/test_app/public/packs/manifest.json b/test/test_app/public/packs/manifest.json index 5a49f60fb..783214316 100644 --- a/test/test_app/public/packs/manifest.json +++ b/test/test_app/public/packs/manifest.json @@ -4,6 +4,7 @@ "bootstrap.js": "/packs/bootstrap-300631c4f0e0f9c865bc.js", "application.js": "/packs/application-k344a6d59eef8632c9d1.js", "application.png": "/packs/application-k344a6d59eef8632c9d1.png", + "fonts/fa-regular-400.woff2": "/packs/fonts/fa-regular-400-944fb546bd7018b07190a32244f67dc9.woff2", "media/images/image.jpg": "/packs/media/images/image-c38deda30895059837cf.jpg", "media/images/nested/image.jpg": "/packs/media/images/nested/image-c38deda30895059837cf.jpg", "entrypoints": { From bb168e44a64a515f3ff2a87cbb75456fa6874bd6 Mon Sep 17 00:00:00 2001 From: Guillaume Briday Date: Mon, 22 Jul 2019 00:01:02 +0200 Subject: [PATCH 2/5] Check Rails version for preload_pack_asset method --- docs/webpack.md | 2 +- lib/webpacker/helper.rb | 4 +++- test/helper_test.rb | 8 +++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/webpack.md b/docs/webpack.md index 82cc3909d..f2e5d5326 100644 --- a/docs/webpack.md +++ b/docs/webpack.md @@ -310,7 +310,7 @@ Before preload or prefetch your assets, please read [https://developer.mozilla.o Webpack also provide it's own methods for preload or prefetch [https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c](https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c). -You can preload your assets with the `preload_pack_asset` helper. +You can preload your assets with the `preload_pack_asset` helper if you have Rails >= 5.2.x. ```erb <%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index fb90abab9..020f12a8e 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -92,7 +92,9 @@ def javascript_packs_with_chunks_tag(*names, **options) # <%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> # => # def preload_pack_asset(name, **options) - preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) + if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2) + preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) + end end # Creates a link tag that references the named pack file, as compiled by webpack per the entries list diff --git a/test/helper_test.rb b/test/helper_test.rb index 0d6692e28..6d6d6c83e 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -80,9 +80,11 @@ def test_javascript_pack_tag_split_chunks end def test_preload_pack_asset - assert_equal \ - %(), - preload_pack_asset("fonts/fa-regular-400.woff2") + if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2) + assert_equal \ + %(), + preload_pack_asset("fonts/fa-regular-400.woff2") + end end def test_stylesheet_pack_tag_split_chunks From 2d2f4bfa73365493537f61967360dc2cd4d44096 Mon Sep 17 00:00:00 2001 From: Guillaume Briday Date: Fri, 2 Aug 2019 20:34:05 +0200 Subject: [PATCH 3/5] Using native preload_link_tag or custom link tag --- lib/webpacker/helper.rb | 25 ++++++++++++++++++++++++- test/helper_test.rb | 8 +++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index 020f12a8e..047273411 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -92,8 +92,31 @@ def javascript_packs_with_chunks_tag(*names, **options) # <%= preload_pack_asset 'fonts/fa-regular-400.woff2' %> # => # def preload_pack_asset(name, **options) - if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2) + if self.class.method_defined?(:preload_link_tag) preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) + else + href = current_webpacker_instance.manifest.lookup!(name) + extname = File.extname(href).downcase.delete(".") + mime_type = options.delete(:type) || Mime::Type.lookup_by_extension(extname).try(:to_s) + as_type = options.delete(:as) || resolve_link_as(extname, mime_type) + crossorigin = options.delete(:crossorigin) + crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font") + nopush = options.delete(:nopush) || false + + early_hints_link = "<#{href}>; rel=preload; as=#{as_type}" + early_hints_link += "; type=#{mime_type}" if mime_type + early_hints_link += "; crossorigin=#{crossorigin}" if crossorigin + early_hints_link += "; nopush" if nopush + + request.send_early_hints("Link" => early_hints_link) if respond_to?(:request) && request + + tag.link({ + rel: "preload", + href: href, + as: as_type, + type: mime_type, + crossorigin: crossorigin + }.merge!(options.symbolize_keys)) end end diff --git a/test/helper_test.rb b/test/helper_test.rb index 6d6d6c83e..0d6692e28 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -80,11 +80,9 @@ def test_javascript_pack_tag_split_chunks end def test_preload_pack_asset - if Rails::VERSION::MAJOR > 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2) - assert_equal \ - %(), - preload_pack_asset("fonts/fa-regular-400.woff2") - end + assert_equal \ + %(), + preload_pack_asset("fonts/fa-regular-400.woff2") end def test_stylesheet_pack_tag_split_chunks From da3f5fd742ae5ef4623226ccb540cdcc4aa6436a Mon Sep 17 00:00:00 2001 From: Guillaume Briday Date: Sat, 3 Aug 2019 13:16:19 +0200 Subject: [PATCH 4/5] Removing support for Rails < 5.2 in preload_pack_asset method --- lib/webpacker/helper.rb | 23 ----------------------- test/helper_test.rb | 8 +++++--- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index 047273411..faca70924 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -94,29 +94,6 @@ def javascript_packs_with_chunks_tag(*names, **options) def preload_pack_asset(name, **options) if self.class.method_defined?(:preload_link_tag) preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) - else - href = current_webpacker_instance.manifest.lookup!(name) - extname = File.extname(href).downcase.delete(".") - mime_type = options.delete(:type) || Mime::Type.lookup_by_extension(extname).try(:to_s) - as_type = options.delete(:as) || resolve_link_as(extname, mime_type) - crossorigin = options.delete(:crossorigin) - crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font") - nopush = options.delete(:nopush) || false - - early_hints_link = "<#{href}>; rel=preload; as=#{as_type}" - early_hints_link += "; type=#{mime_type}" if mime_type - early_hints_link += "; crossorigin=#{crossorigin}" if crossorigin - early_hints_link += "; nopush" if nopush - - request.send_early_hints("Link" => early_hints_link) if respond_to?(:request) && request - - tag.link({ - rel: "preload", - href: href, - as: as_type, - type: mime_type, - crossorigin: crossorigin - }.merge!(options.symbolize_keys)) end end diff --git a/test/helper_test.rb b/test/helper_test.rb index 0d6692e28..906b843c0 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -80,9 +80,11 @@ def test_javascript_pack_tag_split_chunks end def test_preload_pack_asset - assert_equal \ - %(), - preload_pack_asset("fonts/fa-regular-400.woff2") + if self.class.method_defined?(:preload_link_tag) + assert_equal \ + %(), + preload_pack_asset("fonts/fa-regular-400.woff2") + end end def test_stylesheet_pack_tag_split_chunks From 6cbd48015d9e8d77ba8fe5f0158bc20515730fb5 Mon Sep 17 00:00:00 2001 From: Guillaume Briday Date: Mon, 12 Aug 2019 21:39:19 +0200 Subject: [PATCH 5/5] Raise exception for Rails < 5.2 in preload_pack_asset method --- lib/webpacker/helper.rb | 2 ++ test/helper_test.rb | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/webpacker/helper.rb b/lib/webpacker/helper.rb index faca70924..884f0d3f6 100644 --- a/lib/webpacker/helper.rb +++ b/lib/webpacker/helper.rb @@ -94,6 +94,8 @@ def javascript_packs_with_chunks_tag(*names, **options) def preload_pack_asset(name, **options) if self.class.method_defined?(:preload_link_tag) preload_link_tag(current_webpacker_instance.manifest.lookup!(name), options) + else + raise "You need Rails >= 5.2 to use this tag." end end diff --git a/test/helper_test.rb b/test/helper_test.rb index 906b843c0..509afd3d0 100644 --- a/test/helper_test.rb +++ b/test/helper_test.rb @@ -84,6 +84,14 @@ def test_preload_pack_asset assert_equal \ %(), preload_pack_asset("fonts/fa-regular-400.woff2") + else + error = assert_raises do + preload_pack_asset("fonts/fa-regular-400.woff2") + end + + assert_equal \ + "You need Rails >= 5.2 to use this tag.", + error.message end end