Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new javascript_packs_with_chunks_tag tag helper #1898

Merged
merged 1 commit into from
Jan 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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