The configuration docs at https://github.com/rails/webpacker/blob/master/docs/webpack.md currently refer to CommonsChunkPlugin as the way to deduplicate your js packs.
Since Webpack 4 "the CommonsChunkPlugin was removed in favor of optimization.splitChunks": https://webpack.js.org/plugins/split-chunks-plugin/
The documentation link above should be updated to reflect that change as webpacker now supports webpack 4.
This will involve changes to the javascript_pack_tag as it doesn't seem to support entrypoints entries in the manifest.
The may not be the most 'railsy' way but here is how I got it working:
// config/webpack/split_chunks.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
// config/webpack/environment.js
const splitChunks = require('./split_chunks')
const WebpackAssetsManifest = require('webpack-assets-manifest')
environment.config.merge(splitChunks)
// Should override the existing manifest plugin
environment.plugins.insert(
'Manifest',
new WebpackAssetsManifest({
entrypoints: true, // default in rails is false
writeToDisk: true, // rails defaults copied from webpacker
publicPath: true // rails defaults copied from webpacker
})
)
# app/helpers/application_helper.rb
module ApplicationHelper
def javascript_entrypoint_pack_tag(*names, **options)
javascript_include_tag(*sources_from_pack_manifest_entrypoints(names, type: :javascript), **options)
end
private
def sources_from_pack_manifest_entrypoints(names, type:)
names.map do |name|
Webpacker.manifest.lookup!('entrypoints')[name][manifest_type(type)]
end.flatten
end
def manifest_type(type)
case type
when :javascript then 'js'
when :stylesheet then 'css'
else type.to_s
end
end
end
# view file
= javascript_entrypoint_pack_tag 'pack_name'
I also found the need to define:
def stylesheet_entrypoint_pack_tag(*names, **options)
unless Webpacker.dev_server.running? && Webpacker.dev_server.hot_module_replacing?
stylesheet_link_tag(*sources_from_pack_manifest_entrypoints(names, type: :stylesheet), **options)
end
end
Thanks for this documentation, it works perfectly.
@tinderfields maybe you could open a PR and update the docs, because it would be super helpful if this information was available there too! Maybe @gauravtiwari has some ideas about the best approach for this?
I wrote this helper for generating preload tags:
def javascript_entrypoint_pack_preload_tag(*names, **options)
logical_paths = sources_from_pack_manifest_entrypoints(names, type: :javascript)
# rubocop:disable Rails/OutputSafety
logical_paths.uniq.map do |logical_path|
href = path_to_javascript(logical_path, skip_pipeline: true)
tag_options = {
rel: "preload",
href: href,
as: "script",
}.reverse_merge(options)
tag(
:link,
tag_options,
)
end.join("\n").html_safe
# rubocop:enable Rails/OutputSafety
end
sources_from_pack_manifest_entrypoints is from https://github.com/rails/webpacker/issues/1622#issuecomment-407389401
Should be similar for CSS files
(but preloading CSS is slower on chromium-based browsers)
Please use the latest RC, and feel free to open a new issue with more details if this is still an issue.
@gauravtiwari just noticed that this works now if you don't include an extension, however if you do javascript_pack_tag("something.js") it will fail. I traced the code a bit and it seems to leave a trailing . on the file name after stripping the extension which causes it to fail to find the entrypoint.
Oddly enough it also doesn't throw any errors.
Just a heads up you should now be using these instructions: https://github.com/rails/webpacker/blob/master/docs/webpack.md#add-splitchunks-webpack-v4
@tinderfields I used your solution but have problem in including files in my view. I have these files to include:
CSS:
https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css
'application',
media: 'all',
'data-turbolinks-track': 'reload'
JS:
https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.2.0/zxcvbn.js
'application'
How can I import them?
Most helpful comment
I also found the need to define: