Webpacker: Provide SplitChunksPlugin documentation

Created on 24 Jul 2018  路  9Comments  路  Source: rails/webpacker

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.

Most helpful comment

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

All 9 comments

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?

Was this page helpful?
0 / 5 - 0 ratings