Skip to content

Conversation

@rkostrzewski
Copy link
Collaborator

Currently all compilation chunks are changing when new chunk is added to bundle (possibly removed too). This can break long term caching for often changing apps.

This change introducing consistent hashes via HashedModuleIdsPlugin (kinda described here).

Example:
Default generated app with following in index.js

import './style';

import { h } from 'preact';
import { Router } from 'preact-router';

import Header from './components/header';
import Home from './routes/home';
import Profile from './routes/profile';

// import NewRoute from './routes/new-route'

export default () => (
	<div id="app">
		<Header />
		<Router>
			<Home path="/" />
			<Profile path="/profile/" user="me" />
			<Profile path="/profile/:user" />
			{/* <NewRoute path="/new" /> */}
		</Router>
	</div>
);

After running npm run build build dir looks like this:

136B assets
 18K bundle.js
 15K favicon.ico
784B index.html
426B manifest.json
3.8K polyfills.chunk.906967bd865a58e79868.js
333B push-manifest.json
777B route-home.chunk.cb9a97a68a24844cb988.js
1.4K route-profile.chunk.912babe0ee7dbb610e0b.js
1.1K style.css
 86B style.css.map
3.9K sw.js

After adding new route:

136B assets
 18K bundle.js
 15K favicon.ico
784B index.html
426B manifest.json
3.8K polyfills.chunk.f9e3f954aa46b2631857.js
508B push-manifest.json
777B route-home.chunk.6a92827b1cd9460beb95.js
725B route-new-route.chunk.4f17c863583cb00f2870.js
1.4K route-profile.chunk.d01c8307b02769a19281.js
1.1K style.css
 86B style.css.map
3.9K sw.js

route-home.chunk had hash cb9a97a68a24844cb988 now it has 6a92827b1cd9460beb95. Same goes for other chunks.

After the changes hashes are correctly preserved.
Before:

136B assets
 18K bundle.js
 15K favicon.ico
784B index.html
426B manifest.json
3.8K polyfills.chunk.5156d40ad82df36bfb93.js
333B push-manifest.json
790B route-home.chunk.fe6f6d1271eb23067f8f.js
1.4K route-profile.chunk.94c8dcc7d504a8b9950f.js
1.1K style.css
 86B style.css.map
3.9K sw.js

After:

136B assets
 18K bundle.js
 15K favicon.ico
784B index.html
426B manifest.json
3.8K polyfills.chunk.5156d40ad82df36bfb93.js
508B push-manifest.json
790B route-home.chunk.fe6f6d1271eb23067f8f.js
732B route-new-route.chunk.ec70894bbedfe0afb3d3.js
1.4K route-profile.chunk.94c8dcc7d504a8b9950f.js
1.1K style.css
 86B style.css.map
3.9K sw.js

Chunks that were not changed have same hashes ✨

@rkostrzewski rkostrzewski changed the title Webpack hashes change for not changed chunks when new ones are added. fix: Webpack hashes change for not changed chunks when new ones are added. May 21, 2017
Copy link
Member

@lukeed lukeed left a comment

Choose a reason for hiding this comment

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

Nice! Totally forgot that NamedModulesPlugin had a production counterpart.

@developit
Copy link
Member

This is beautiful.

Think it would be worth using shorter hashes for chunk filenames?

@rkostrzewski
Copy link
Collaborator Author

Idk, what's the benefit tough?
HtmlWebpackPlugin already deals with injecting them so that doesn't matter for end user IMHO.
The shorter the chunkhash the more possible hash collision becomes (probably doesn't matter too, unless we'd go for extremely short sizes 😜 ).

@developit
Copy link
Member

developit commented May 25, 2017

I just figured it'd be nicer to look at haha. It does slightly trim down the HTML payload size, though I agree it's pretty minimal. Only raised the question because I've most often seen webpack hashes used truncated to 5 characters. Also I think there's a way to have the hash pass through base64? That means it'll contain more than just numbers, which would trim it down a bit in the first place.

@rkostrzewski
Copy link
Collaborator Author

rkostrzewski commented May 26, 2017

@developit I've looked into it and the docs don't mention base64 or smaller chunkhashes anywhere. I've also tried using stuff like [name].chunk.[chunkhash:base64].js or [name].chunk.[chunkhash:5].js and as a result I've got files like: route-home.chunk.[chunkhash:5].js (i.e. no hash at all). Also base64 encoded number is longer than original (20 vs 28).

I guess I could write a custom plugin which would trim down the length, don't know if it's worth the trouble. Your call though.

@lukeed
Copy link
Member

lukeed commented May 26, 2017

Hmmm... I'll check for a recent project of mine that uses [chunkhash:5] --- I'm pretty certain that still works!

I will have to update you in the morning, though. Currently in bed & past my bedtime =)

@developit
Copy link
Member

Definitely not worth a custom plugin, just figured if there was a builtin we could use it.

@lukeed
Copy link
Member

lukeed commented May 26, 2017

@rkostrzewski @developit

I went thru a few trials & the only combinations that work are [chunkhash:5] and [hash:5]. It looks like the base64 addition is loader-specific? I have it in some places, but it definitely doesn't work on output config names.

@rkostrzewski
Copy link
Collaborator Author

@lukeed you are right! Must have messed up something previously.

Anyway, I've set chunkhashes to 5 characters 🎉

Copy link
Member

@developit developit left a comment

Choose a reason for hiding this comment

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

LGTM!

@developit developit merged commit 984476f into preactjs:master May 29, 2017
@rkostrzewski rkostrzewski deleted the fix/webpack-hashing branch June 23, 2017 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants