Parcel: JavaScript file hash doesn't change when dependency filename changed

Created on 2 Jun 2018  ยท  24Comments  ยท  Source: parcel-bundler/parcel

๐Ÿ› bug report

I noticed that a new JavaScript file was generated with the same name as the old one, even though its contents had changed.

๐ŸŽ› Configuration (.babelrc, package.json, cli command)

I created a sample project in this repository:

https://github.com/dobesv/parcel-import-bug

๐Ÿค” Expected Behavior

If the contents of a generated JavaScript file change in any significant way, so should the hash in its filename.

๐Ÿ˜ฏ Current Behavior

As you can see in the below transcript, the contents of the generated JavaScript file are modified, but its hash doesn't change.

$ echo a>template5.html
$ parcel build index.html -d dist-a
โœจ  Built in 1.24s.

dist-a/parcel-import-bug.a9b3581e.js      299.6 KB    19.34s
dist-a/controller.1cfadc83.js             87.37 KB     220ms
dist-a/controller.343f9052.js              1.23 KB     173ms
dist-a/index.html                            245 B       5ms
dist-a/parcel-import-bug.bfb7fe78.urls        31 B     102ms
dist-a/test.ae9c52ee.css                      20 B      12ms
dist-a/template5.7deadfab.html                 2 B     193ms
dist-a/parcel-import-bug.bfb7fe78.json         0 B     103ms
dist-a/controller.343f9052.map                 0 B     209ms
dist-a/parcel-import-bug.e3817f33.map          0 B    19.26s
dist-a/controller.1cfadc83.map                 0 B     255ms
$ echo b>template5.html
$ parcel build index.html -d dist-b
โœจ  Built in 1.30s.

dist-b/parcel-import-bug.a9b3581e.js      299.6 KB    20.44s
dist-b/controller.1cfadc83.js             87.37 KB     227ms
dist-b/controller.343f9052.js              1.23 KB     182ms
dist-b/index.html                            245 B       3ms
dist-b/parcel-import-bug.bfb7fe78.urls        31 B     102ms
dist-b/test.ae9c52ee.css                      20 B      15ms
dist-b/template5.fc4c8ece.html                 2 B     190ms
dist-b/parcel-import-bug.bfb7fe78.json         0 B     101ms
dist-b/controller.343f9052.map                 0 B     217ms
dist-b/parcel-import-bug.e3817f33.map          0 B    20.34s
dist-b/controller.1cfadc83.map                 0 B     260ms
(env) 13:40:40 ~/parcel-import-bug 
$ diff dist-a/parcel-import-bug.a9b3581e.js dist-b/parcel-import-bug.a9b3581e.js
474,475c474,475
< module.exports={html:"/template5.7deadfab.html"};
< },{"./template5.html":[["template5.7deadfab.html",198],198]}],202:[function(require,module,exports) {
---
> module.exports={html:"/template5.fc4c8ece.html"};
> },{"./template5.html":[["template5.fc4c8ece.html",198],198]}],202:[function(require,module,exports) {

๐Ÿ’ Possible Solution

Not clear yet why this is the case. Maybe the hash in the filename isn't calculated from the file contents, but something else?

๐Ÿ”ฆ Context

When deploying a new version of the app, I assume that the filenames will change when their contents do, and set long cache expiry times on those files. If this assumption is broken, our app fails to load or various other weird problems can occur.

๐Ÿ’ป Code Sample

https://github.com/dobesv/parcel-import-bug

๐ŸŒ Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.8.1
| Node | 9.11.1
| npm/Yarn | 1.6.0
| Operating System | Ubuntu Xenial (Linux Mint)

Bug

Most helpful comment

I have submitted a fix but it has not been accepted or rejected. Not sure what else to do here. I do wonder why so few people are complaining about this issue, though. Maybe it's not as bad as it seems and there's just something we few are doing wrong.

All 24 comments

I tried setting NODE_ENV=production during the build, and this resulted in more differences between the files but they still had the same hashed filename.

I think maybe the filename for a package with a bunch of js files bundled together isn't including files that aren't actually bundled into the file as part of its hash, even if it depends on those files.

As I've dug into this a bit more, it seems like the hash of a JS bundle will update if a CSS file it depends on is changed, because a CSS file generates an empty js string. But if you have an html dependency, it doesn't generate any js at all (not even an empty string) which means that changes to the html won't cause the hash of the bundle to change.

I guess importing HTML files isn't officially supported by Parcel yet, so perhaps this is something I'll have to workaround in my plugin.

However, I'm having trouble figuring out a way to get around this in the plugin. Any help from someone who knows the workings and plans for parcel would be much appreciated.

So to try and summarize a bit:

  • The hash in a bundle filename only depends on the assets included in that bundle, assets that emit a js output (this does include JavaScript and CSS files)
  • The file contents used to determine the bundle hash are calculated prior to calculating file hashes of the dependencies
  • My plugin emits a js file but its hash is calculated only based on the names of files it includes, not their contents
  • Asset contents and hashes are generated prior to bundling
  • But the hash of the "urls" module I am generating depends on the filenames of the bundles.

A bit of a puzzle here ...

Well, I'm implementing a workaround in my plugin to just run a sort of "sub build" to calculate the hashes of its dependencies and insert a hash of those hashes into its own output. It seems like the structure of Parcel doesn't accomodate the idea of a file depending on the names of other files.

My workaround isn't working properly any more - it seems to stall out the build. But this issue remains. I have also recreated this as an automated test in the parcel test suite:

https://github.com/dobesv/parcel/pull/new/indirect-import-hash-issue

I created a plugin for this as a temporary workaround for anyone affected by this issue. https://github.com/dobesv/parcel-plugin-bundle-deep-hash

https://github.com/ChALkeR/parcel-cache-fail -- here is my description of the problem.

this is a huge issue ; it makes caching with code splitting impossible.

I have submitted a fix but it has not been accepted or rejected. Not sure what else to do here. I do wonder why so few people are complaining about this issue, though. Maybe it's not as bad as it seems and there's just something we few are doing wrong.

@dobesv Is there a PR? Would like to see it if possible :) I couldn't find it by your name. Thx btw!

@dobesv nice solution! thank you. Btw this is a huge bug indeed.

@wxsms Do you have a reproduction repo for the latest version of parcel?

@dobesv nope. But it's easy to reproduce, just make some lazy load scripts and change the deepest script's content, it results in the entry script's hash not changed.

@wxsms I'm just thinking that if they have a reproduction repo using the latest version of parcel they will be more likely to fix it than if they have to reproduce it themselves.

I just tested with Parcel 2, are you sure this is still occurring?

@mischnic Sry I'm not using Parcel2, the latest version on NPM is 1.12.4, that's my version.

Have not notice yet there is v2 since this. It's kind of invisible to normal users ๐Ÿ˜ข

@mischnic I am using Parcel 1 and facing same issue. Will the fix be rolled out to Parcel 1 too?

My suggestion, to be frank, is to not use Parcel. I have this one project that uses parcel and I regret using it. I've been using Webpack in other projects and it's better in every way except initial setup effort.

@dobesv Sadly, I do not have choice here, my project is such that have to look for both webpack and parcel bundler support.

Closing. Please use parcel 2.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tarepan picture tarepan  ยท  46Comments

jpergler picture jpergler  ยท  59Comments

jpsc picture jpsc  ยท  81Comments

shiloa picture shiloa  ยท  39Comments

mjrjoh picture mjrjoh  ยท  40Comments