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

Deprecation warning on CommonChunksPlugin. Add SplitChunksPlugin page #1863

Closed
wants to merge 24 commits into from

Conversation

jeremenichelli
Copy link
Member

@jeremenichelli jeremenichelli commented Feb 27, 2018

Adding Tobias as a reviewer since I used his gist as a base for the SplitChunksPlugin page. I've also added a deprecation warning on CommonChunksPlugin one (not deleting it for now since developers and teams who can immediately migrate might need it).

MagicDuck and others added 21 commits February 6, 2018 23:19
This moves some of the content from `compiler.md` and brings it into the
main node api documentation in order to allow `compiler.md` to become
`compiler-hooks.md` which fits better in the context of plugins.
…le.md`

This moves some of the `Tapable` discussion to the lead-in `plugins.md` to
prevent doc duplication. Instead of redocumenting the `tapable` package, we
should focus on improving the README and simply link to there throughout
our docs. As I've mentioned before, we can also create a "Utilities" section
for things other than "Loaders" and "Plugins" that we want to dynamically
pull in.
These guides were full of todos and probably lead to more confusion
than clarity. We can discuss more and add them back in once there's
a clear flow for how to incorporate and document them.
This page now focuses specifically on the `hooks` as all the non-plugin related
content was moved to `node.md`. I updated the hooks to the new syntax, added
all undocumented hooks, reformatted each hook as a section to allow more
breathing room, and clarified exactly which `tapable` hook is used for each
section. Still need to get more info on some of the new hooks before we can
ship this...
This page now uses the same section setup as `compiler-hooks.md` and
is up to date with the latest hooks available in the webpack 4 alpha release.
Improve lead-in to give a little more context on what the parser does. Add
the latest hooks and use the same layout as the other pages in the section.
@montogeek
Copy link
Member

Great initial work!

@jeremenichelli
Copy link
Member Author

@skipjack I want to bother you as less as possible, but tagging you here since it's a whole new page that would love to have a look from you.

@jeremenichelli jeremenichelli changed the base branch from next to master February 28, 2018 19:38
@jeremenichelli jeremenichelli changed the base branch from master to next February 28, 2018 20:07
Copy link
Collaborator

@skipjack skipjack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, don't worry about pinging me. Happy to come back and do reviews here and there.

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 cache for later use. This results in pagespeed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.
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.

W> CommonsChunkPlugin has been deprecated in webpack v4 legato. If you want to know how chunks are treated in the newest version checkout [SplitChunksPlugin](/plugins/split-chunks-plugin/).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rephrase this slightly:

The CommonsChunkPlugin has been deprecated in webpack v4 legato.. To learn how chunks are treated in the latest version, check out the SplitChunksPlugin.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/legato../legato.


Originally in webpack, chunks (and modules import inside them) were connected by a parent-child relationship in the internal webpack graph.

This connection didn't allow to further optimizations and reluted into more coded downloaded.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/reluted/resulted

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/more coded downloaded/more downloaded code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/allow to/allow for/

cacheGroups: {
default: {
minChunks: 2,
priority: -20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comma is missing

splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a slash-comma: test: /[\\/]node_modules[\\/]/,


Out of the box `SplitChunksPlugin` should work great for most users.

By default the plugin only affect on-demand chunks, because changing initial chunks would affect the script tags that the HTML file should include to run the project.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

affect should be affects

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blowery I don't agree, affect is correct grammar

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@audiolion, are you sure? I think if "plugin" were plural, then I agree "affect" should be used (ie "the plugins only affect on-demand chunks"), however given it's singular, "affects" seems more correct to me.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha, I was reading the wrong "affect", initial chunks would affect(s) the script tags...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, same happened to me. Thanks.


For these people that like to have more control over this functionality, webpack provides a set of options to better fit your needs.

W> If you are manually changing the split configuration, measure the impact of the changes to see and make sure there's a real benefit. The defaults are choosen to fit best practices of web performance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/choosen/chosen
(change below my opinion, not related to grammar):
s/fit best practices of web performance/fit web performance best practices


### Configuring cache groups

The defaults assigns all modules from `node_modules` to a cache group called `vendors` and all modules duplicated in at least 2 chunks to a change group `default`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/change group/cache group

@benthemonkey
Copy link
Contributor

benthemonkey commented Mar 6, 2018

I notice these docs don't include any information about the enforce cache group setting. I've been playing around with that option and was hoping to learn more about it from these docs. It seems like it is useful for overriding the base settings for only one cache group. E.g.:

splitChunks: {
	chunks: "async",
	minSize: 30000,
	minChunks: 1,
	maxAsyncRequests: 5,
	maxInitialRequests: 3,
	name: true,
	cacheGroups: {
		default: {
			minChunks: 2,
			priority: -20
			reuseExistingChunk: true,
		},
		vendors: {
			test: /[\\/]node_modules[\\/]/,
			priority: -10
		},
		special: {
			test: myTestFunc,
			enforce: true
		}
	}
}

Please correct me if I am mistaken: The enforce allows the special cache group to ignore the minSize, minChunks, maxAsyncRequests and maxInitialRequests set in the overall splitChunks config and purely use test to decide what goes into the chunk. What I'm unclear on is how that fits in when used with reuseExistingChunk.


## `optimization.runtimeChunk`

Setting `optimization.runtimeChunk` to `true` adds an additonal chunk to each entrypoint containing only the runtime.
Copy link
Contributor

@benthemonkey benthemonkey Mar 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include the different things that you can pass to runtimeChunk. It can be a boolean, 'single', 'multiple' or an object that has property name whose value can be either a string or a function of signature (entrypoint: Chunk) => string

e.g.

{
	name: entrypoint => `runtime~${entrypoint.name}`
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @sokra can you fill in some technical gap here? Should we add enforce details in this piece, I would need your help with it 😓

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is its default value? In this blog post it says it's true, but from trying it out it's not.

* Maximum number of parallel request when loading chunks on demand would be lower or equal to 5
* Maximum number of parallel request at initial page load would be lower or equal to 3

When trying to fullfill the last two conditions, bigger chunks are preferred.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fullfill -> fulfill

webpack will automatically split chunks based on these conditions:

* New chunk can be shared OR modules are from the `node_modules` folder
* New chunk would be bigger than 30kb (before min+gz)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kb -> KiB (here and elsewhere)


W> When assigning equal names to different split chunks they are merged together. This can be used to put all vendor modules into a single shared chunk, but it's not recommend since it can result in more code downloaded.

The magic value `true` automatically chooses a name based on chunks and cache group key. Elsewise a string or function can be passed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Elsewise/Otherwise

Elsewise usage in english

@jeremenichelli
Copy link
Member Author

Thanks everyone for all your feedback. Working on updates and getting changes pushed soon.


W> CommonsChunkPlugin has been deprecated in webpack v4 legato. If you want to know how chunks are treated in the newest version checkout [SplitChunksPlugin](/plugins/split-chunks-plugin/).

By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in cache for later use. This results in pagespeed optimizations as the browser can quickly serve the shared code from cache, rather than being forced to load a larger bundle whenever a new page is visited.

```javascript
new webpack.optimize.CommonsChunkPlugin(options)
Copy link

@audiolion audiolion Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be removed? or replaced with:

optimization: {
  splitChunks: {
    name: 'all',
  },
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the old CommonsChunkPlugin page. We are keeping the old documentaiton for teams that are already using it and haven't migrated to v4. We are adding a warning on top talking about the deprecation of it from now on.


`cacheGroups` is an object where keys are the cache group names. All options from the ones listed above are possible: `chunks`, `minSize`, `minChunks`, `maxAsyncRequests`, `maxInitialRequests`, `name`.

You can set `optimization.splitChunks.cacheGroups.default` to `false` to disable the default cache group.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for optimization.splitChunks.cacheGroups.vendors.


Here are some examples and their effect:

### Example 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add another example:

Enable the default optimizations for all chunks instead of only async chunks. This is the recommended configuration.

splitChunks: {
  chunks: "all"
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a specific section for chunks: "all" so we highlight this configuration set as recommended, pushing in a bit.

}
}
}
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default this configuration will only create a commons chunk when the minimum size and maximum number of requests are valid. Adding enforce: true, will disable any not configured condition and enforce creating the chunk.


You can set `optimization.splitChunks.cacheGroups.default` to `false` to disable the default cache group.

The priority of the default groups are negative to allow any custom cache group to take higher priority (the default value is `0`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The priority controls the order in which cache groups are executed. Higher priorities will execute before lower priorities.

url: https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
---

Originally in webpack, chunks (and modules import inside them) were connected by a parent-child relationship in the internal webpack graph.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/modules import/modules imported/


Originally in webpack, chunks (and modules import inside them) were connected by a parent-child relationship in the internal webpack graph.

This connection didn't allow to further optimizations and reluted into more coded downloaded.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/allow to/allow for/


This connection didn't allow to further optimizations and reluted into more coded downloaded.

webpack v4 removes the `CommonsChunkPlugin` in favor of `optimization.splitChunks` and `optimization.runtimeChunk` options. Here is how the new flow works.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/favor of/favor of the/


Out of the box `SplitChunksPlugin` should work great for most users.

By default the plugin only affect on-demand chunks, because changing initial chunks would affect the script tags that the HTML file should include to run the project.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@audiolion, are you sure? I think if "plugin" were plural, then I agree "affect" should be used (ie "the plugins only affect on-demand chunks"), however given it's singular, "affects" seems more correct to me.

* New chunk can be shared OR modules are from the `node_modules` folder
* New chunk would be bigger than 30kb (before min+gz)
* Maximum number of parallel request when loading chunks on demand would be lower or equal to 5
* Maximum number of parallel request at initial page load would be lower or equal to 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/parallel request/parallel requests/ (x2)


## Configuration

For these people that like to have more control over this functionality, webpack provides a set of options to better fit your needs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/For these people/For people/


### Select modules

The `test` option controls which modules are selected by this cache group. Omitting it selects all modules. It can be a RegExp, string or function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if this section went more into details about the function version of this option, e.g. what the args to the function are, how to use them, and what the function should return.

Copy link
Contributor

@lencioni lencioni Mar 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, it looks like test fn is called with 2 args. module and chunks.

https://github.com/webpack/webpack/blob/66ff412f7e2409ee535c2dc79abf4068015b2e22/lib/optimize/SplitChunksPlugin.js#L188

I think module is an object that describes the chunk being considered for placement, and chunks seems to be an array of objects with metadata about each chunk. I'm not sure where these are documented or defined in code yet.

It seems that test functions should return a boolean.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each chunk object seems to have these keys:

id
ids
debugId
name
entryModule
_modules
_groups
files
rendered
hash
renderedHash
chunkReason
extraAsync

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I imagine that boolean decides if the current module goes to a chunk or not.


By default cache groups inherit options from `splitChunks.*`, but `test`, `priority` and `reuseExistingChunk` can only be configured on cache group level.

`cacheGroups` is an object where keys are the cache group names. All options from the ones listed above are possible: `chunks`, `minSize`, `minChunks`, `maxAsyncRequests`, `maxInitialRequests`, `name`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like cacheGroups can also be a function? Should this be documented here? https://github.com/webpack/webpack/blob/66ff412f7e2409ee535c2dc79abf4068015b2e22/lib/optimize/SplitChunksPlugin.js#L132


Putting the content of `helpers` into each chunk will result into its code being downloaded twice. By using a separate chunk this will only happen once. We pay the cost of an additional request, which could be considered a tradeoff. That's why there is a minimum size of 30kb.

T> With the new `optimizations.splitChunks.chunks: "all"` option the same would happend for initial chunks. Chunks can even be shared between entrypoints and on-demand loading.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/optimizations/optimization/

@jeremenichelli jeremenichelli changed the base branch from next to master March 25, 2018 23:59
@jeremenichelli
Copy link
Member Author

Thanks everyone for the comments, I'm creating a new pull request since the next branch has been merged and rebase is completely broken from here in files that haven't been touched and I don't want to cause regression on content.

@sokra I will create an issue with some stuff that needs to be revisited or cover in the split chunks article. Thanks for the comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.