Skip to content

Commit

Permalink
Add new javascript_packs_with_chunks_tag helper
Browse files Browse the repository at this point in the history
  • Loading branch information
gauravtiwari committed Jan 17, 2019
1 parent c73dd7a commit 250de51
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 44 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
**Please note that Webpacker 3.1.0 and 3.1.1 have some serious bugs so please consider using either 3.0.2 or 3.2.0**

## [4.0.0] - Unreleased

### Fixed
- Issue with javascript_pack_tag asset duplication [#1898](https://github.com/rails/webpacker/pull/1898)


### Added
- `javascript_packs_with_chunks_tag` helper, which creates html tags
for a pack and all the dependent chunks, when using splitchunks.

```erb
<%= javascript_packs_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %>
<script src="/packs/vendor-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
```

**Important:** Pass all your pack names when using `javascript_packs_with_chunks_tag`
helper otherwise you will get duplicated chunks on the page.

```erb
<%# DO %>
<%= javascript_packs_with_chunks_tag 'calendar', 'map' %>
<%# DON'T %>
<%= javascript_packs_with_chunks_tag 'calendar' %>
<%= javascript_packs_with_chunks_tag 'map' %>
```

## [4.0.0.rc.2] - 2018-12-15

### Fixed
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,31 @@ can use the `asset_pack_path` helper:
<img src="<%= asset_pack_path 'images/logo.svg' %>" />
```

If you are using new webpack 4 split chunks API, then consider using `javascript_packs_with_chunks_tag` helper, which creates html
tags for a pack and all the dependent chunks.

```erb
<%= javascript_packs_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %>
<script src="/packs/vendor-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
```

**Important:** Pass all your pack names when using `javascript_packs_with_chunks_tag`
helper otherwise you will get duplicated chunks on the page.

```erb
<%# DO %>
<%= javascript_packs_with_chunks_tag 'calendar', 'map' %>
<%# DON'T %>
<%= javascript_packs_with_chunks_tag 'calendar' %>
<%= javascript_packs_with_chunks_tag 'map' %>
```

**Note:** In order for your styles or static assets files to be available in your view,
you would need to link them in your "pack" or entry file.

Expand Down
48 changes: 26 additions & 22 deletions docs/webpack.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,32 +267,36 @@ For the full configuration options of SplitChunks, see the [Webpack documentatio
// config/webpack/environment.js
const WebpackAssetsManifest = require('webpack-assets-manifest');

const splitChunks = {
optimization: {
splitChunks: {
chunks: 'all'
},
},
};

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
})
)
// Enable the default config
environment.splitChunks()

// or using custom config
environment.splitChunks((config) => Object.assign({}, config, { optimization: { splitChunks: false }}))
```

To use the `javascript_pack_tag` or the `stylesheet_pack_tag` with `SplitChunks` or `RuntimeChunks` you can refer to the packs as usual.
Then use, `javascript_packs_with_chunks_tag` helper to include all the transpiled
packs with the chunks in your view, which creates html tags for all the chunks.

```erb
javascript_pack_tag "your-entrypoint-javascript-file"
stylesheet_pack_tag "your-entrypoint-stylesheet-file"
<%= javascript_packs_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %>
<script src="/packs/vendor-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
<script src="/packs/map-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
```

**Important:** Pass all your pack names when using this helper otherwise you will
get duplicated chunks on the page.

```erb
<%# DO %>
<%= javascript_packs_with_chunks_tag 'calendar', 'map' %>
<%# DON'T %>
<%= javascript_packs_with_chunks_tag 'calendar' %>
<%= javascript_packs_with_chunks_tag 'map' %>
```

For the old configuration with the CommonsChunkPlugin see below. **Note** that this functionality is deprecated in Webpack V4.
Expand Down
32 changes: 29 additions & 3 deletions lib/webpacker/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,29 @@ def image_pack_tag(name, **options)
# <%= javascript_pack_tag 'calendar', 'data-turbolinks-track': 'reload' %> # =>
# <script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
def javascript_pack_tag(*names, **options)
javascript_include_tag(*sources_from_pack_manifest(names, type: :javascript), **options)
javascript_include_tag(*sources_from_manifest_entries(names, type: :javascript), **options)
end

# Creates script tags that references the chunks from entrypoints when using split chunks API,
# 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 and all the dependent chunks. In production mode, the digested reference is automatically looked up.
# See: https://webpack.js.org/plugins/split-chunks-plugin/
# Example:
#
# <%= javascript_packs_with_chunks_tag 'calendar', 'map', 'data-turbolinks-track': 'reload' %> # =>
# <script src="/packs/vendor-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
# <script src="/packs/calendar~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
# <script src="/packs/calendar-1016838bab065ae1e314.js" data-turbolinks-track="reload"></script>
# <script src="/packs/map~runtime-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
# <script src="/packs/map-16838bab065ae1e314.js" data-turbolinks-track="reload"></script>
# DO:
# <%= javascript_packs_with_chunks_tag 'calendar', 'map' %>
# DON'T:
# <%= 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 that references the named pack file, as compiled by webpack per the entries list
Expand All @@ -80,7 +102,7 @@ def javascript_pack_tag(*names, **options)
# <link rel="stylesheet" media="screen" href="/packs/calendar-1016838bab065ae1e122.css" data-turbolinks-track="reload" />
def stylesheet_pack_tag(*names, **options)
if current_webpacker_instance.config.extract_css?
stylesheet_link_tag(*sources_from_pack_manifest(names, type: :stylesheet), **options)
stylesheet_link_tag(*sources_from_manifest_entries(names, type: :stylesheet), **options)
end
end

Expand All @@ -89,7 +111,11 @@ def stylesheet?(name)
File.extname(name) == ".css"
end

def sources_from_pack_manifest(names, type:)
def sources_from_manifest_entries(names, type:)
names.map { |name| current_webpacker_instance.manifest.lookup!(name, type: type) }.flatten
end

def sources_from_manifest_entrypoints(names, type:)
names.map { |name| current_webpacker_instance.manifest.lookup_pack_with_chunks!(name, type: type) }.flatten.uniq
end
end
31 changes: 15 additions & 16 deletions lib/webpacker/manifest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ def refresh
@data = load
end

def lookup_pack_with_chunks(name, pack_type = {})
compile if compiling?

manifest_pack_type = manifest_type(pack_type[:type])
manifest_pack_name = manifest_name(name, manifest_pack_type)
find("entrypoints")[manifest_pack_name][manifest_pack_type]
rescue NoMethodError
nil
end

def lookup_pack_with_chunks!(name, pack_type = {})
lookup_pack_with_chunks(name, pack_type) || handle_missing_entry(name)
end

# Computes the relative path for a given Webpacker asset using manifest.json.
# If no asset is found, returns nil.
#
Expand All @@ -27,22 +41,7 @@ def refresh
def lookup(name, pack_type = {})
compile if compiling?

# When using SplitChunks or RuntimeChunks the manifest hash will contain
# an extra object called "entrypoints". When the entrypoints key is not
# present in the manifest, or the name is not found in the entrypoints hash,
# it will raise a NoMethodError. If this happens, we should try to lookup
# a single instance of the pack based on the given name.
begin
manifest_pack_type = manifest_type(pack_type[:type])
manifest_pack_name = manifest_name(name, manifest_pack_type)

# Lookup the pack in the entrypoints of the manifest
find("entrypoints")[manifest_pack_name][manifest_pack_type]
rescue NoMethodError

# Lookup a single instance of the pack
find(full_pack_name(name, pack_type[:type]))
end
find(full_pack_name(name, pack_type[:type]))
end

# Like lookup, except that if no asset is found, raises a Webpacker::Manifest::MissingEntryError.
Expand Down
1 change: 0 additions & 1 deletion package/environments/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ module.exports = class extends Base {

if (devServer.hmr) {
this.plugins.append('HotModuleReplacement', new webpack.HotModuleReplacementPlugin())
this.plugins.append('NamedModules', new webpack.NamedModulesPlugin())
this.config.output.filename = '[name]-[hash].js'
}

Expand Down
2 changes: 1 addition & 1 deletion test/helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_javascript_pack_tag_split_chunks
%(<script src="/packs/vendors~application~bootstrap-c20632e7baf2c81200d3.chunk.js"></script>\n) +
%(<script src="/packs/vendors~application-e55f2aae30c07fb6d82a.chunk.js"></script>\n) +
%(<script src="/packs/application-k344a6d59eef8632c9d1.js"></script>),
javascript_pack_tag("application")
javascript_packs_with_chunks_tag("application")
end

def test_stylesheet_pack_tag
Expand Down
6 changes: 5 additions & 1 deletion test/manifest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def test_lookup_nil
assert_nil Webpacker.manifest.lookup("foo.js")
end

def test_lookup_chunks_nil
assert_nil Webpacker.manifest.lookup_pack_with_chunks("foo.js")
end

def test_lookup_success
assert_equal Webpacker.manifest.lookup("bootstrap.js"), "/packs/bootstrap-300631c4f0e0f9c865bc.js"
end
Expand All @@ -33,6 +37,6 @@ def test_lookup_entrypoint
"/packs/application-k344a6d59eef8632c9d1.js"
]

assert_equal Webpacker.manifest.lookup!("application", type: :javascript), application_entrypoints
assert_equal Webpacker.manifest.lookup_pack_with_chunks!("application", type: :javascript), application_entrypoints
end
end

0 comments on commit 250de51

Please sign in to comment.