-
-
Notifications
You must be signed in to change notification settings - Fork 184
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
Fixing extra and invalid paths in Webpack 5 #249
Fixing extra and invalid paths in Webpack 5 #249
Conversation
I would absolutely love to accept this PR, but without tests to guard against regressions I can't. (I do see that you state that tests are
The use of |
1afd6fd
to
329988e
Compare
329988e
to
9021a8c
Compare
Codecov Report
@@ Coverage Diff @@
## master #249 +/- ##
==========================================
- Coverage 98.19% 89.23% -8.97%
==========================================
Files 3 3
Lines 111 130 +19
==========================================
+ Hits 109 116 +7
- Misses 2 14 +12
Continue to review full report at Codecov.
|
lib/helpers.js
Outdated
const reduceAssets = (files, asset, moduleAssets) => { | ||
const name = moduleAssets[asset.name] ? moduleAssets[asset.name] : asset.info.sourceFilename; | ||
const reduceAssets = (files, asset, moduleAssets, assetTypeModuleAssets) => { | ||
console.log(assetTypeModuleAssets, asset.info.sourceFilename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This little guy snuck into the party
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yea :) I'm actively debugging a last Windows issue that I can only replicate on this CI. So i'm abusing the Windows CI (I don't have access to any other Windows machine).
I'll let you know when things are ready to look at - I thought I had it so I must be missing a tiny last detail :)
00685c9
to
fd755f5
Compare
}; | ||
}); | ||
|
||
return Array.from(chunk.files).reduce((prev, path) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you view this section without whitespace - https://github.com/shellscape/webpack-manifest-plugin/pull/249/files?w=1 - you'll see that the existing logic remains the same. The chunk.auxiliaryFiles
were removed from the "normal" logic and moved into the above loop to track those custom.
isInitial: false, | ||
isChunk: false, | ||
isAsset: true, | ||
isModuleAsset: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe these are all correct: these are not chunks, they are assets. And I believe they are "module assets" because they are auxiliary assets to a chunk, but I'm not positive if that is the intention. These will most notably include sourcemap files.
lib/hooks.js
Outdated
moduleAssets, | ||
assetTypeModuleAssets, | ||
options | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few of these cs changes are being made automatically by the linter - I tried to keep the diff as clean as possible :)
@@ -22,12 +22,12 @@ test('output to the correct location', async (t) => { | |||
filename: '[name].js', | |||
path: outputPath | |||
}, | |||
plugins: [new WebpackManifestPlugin({ fileName: 'webpack.manifest.js' })] | |||
plugins: [new WebpackManifestPlugin({ fileName: 'webpack.manifest.json' })] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you end the file in .js
, the TerserPlugin tries to parse these files and explodes. I'm not sure why this is different between v4 and v5 (it's only a problem on v5), but it makes sense: the manifest contents are not actually a valid JavaScript file ({ "foo": "bar" }
is not valid JavaScript - you'd need to have a const =
in front or something equal).
And so, I think this is valid to change. Users are able to control the filename (the point of the test), but in Webpack 5, they cannot name it .js
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that something we should document in the README?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I would say, let's wait to see if we have any questions about it. The only reason I'm hesitating is that the JSON was never a valid JavaScript file... so I'm trying to think of what the use-case ever would have been (and so, is anyone out there actually doing that?).
@@ -75,15 +74,15 @@ test('works with source maps', async (t) => { | |||
one: '../fixtures/file.js' | |||
}, | |||
output: { | |||
filename: '[name].js', | |||
filename: 'build/[name].js', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making the test more interesting.
// Note: I believe this to be another bug in webpack v5 and cannot find a good workaround atm | ||
if (webpack.version.startsWith('5')) { | ||
expected['main.txt'] = 'file.txt'; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out, these are now fixed! They are #237
lib/helpers.js
Outdated
const reduceAssets = (files, asset, moduleAssets) => { | ||
const name = moduleAssets[asset.name] ? moduleAssets[asset.name] : asset.info.sourceFilename; | ||
const reduceAssets = (files, asset, moduleAssets, assetTypeModuleAssets) => { | ||
console.log(assetTypeModuleAssets, asset.info.sourceFilename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yea :) I'm actively debugging a last Windows issue that I can only replicate on this CI. So i'm abusing the Windows CI (I don't have access to any other Windows machine).
I'll let you know when things are ready to look at - I thought I had it so I must be missing a tiny last detail :)
d41041c
to
e3dce2a
Compare
I'm stuck on one last detail for now: for some reason, in Windows only, What's stranger is that on our CI - we use AppVeyor - it is not missing, and everything works fine. I have no idea why that would be the case :/. |
Are there any other environment differences on AppVeyor versus our Actions? Node versions, other installed windows weird things? |
Hmm, i've actually just added the same Windows matrix to our PR, and it's working fine - https://github.com/symfony/webpack-encore/pull/921/checks#step:6:11 - that test relies on the same thing that is mysteriously missing here. We're executing Webpack in exactly the same way... 🤔 |
I've asked for help here: webpack/webpack#12637 I absolutely had this issue cornered from all angles... until I hit the Windows bug in this CI only (which I can't repeat anywhere else, not even on my own CI). In general, what this plugin tries to do is simple: get a list of all files that were emitted and make a map from the Anyways, I'm hoping there is a simpler way. When If you have any ideas, I would love to hear them :). Thanks! |
94b3587
to
2ebfba9
Compare
2ebfba9
to
185954d
Compare
if (moduleAssets[asset.name]) { | ||
name = moduleAssets[asset.name]; | ||
} else if (asset.info.sourceFilename) { | ||
name = join(dirname(asset.name), basename(asset.info.sourceFilename)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically the same thing that's already being done at the bottom of hooks.js
for the file-loader
/ NormalModule situation -
webpack-manifest-plugin/lib/hooks.js
Line 122 in 9f408f6
Object.assign(moduleAssets, { [file]: join(dirname(file), basename(module.userRequest)) }); |
* (because npm 6 does not do that but npm 7 does) is not enough. For some | ||
* reason why must, by hand, update the package.json file first and then | ||
* run a normal "npm install". | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is insanity, but THIS turned out to be the reason that asset.info.sourceFilename
was missing on Windows (and why I could repeat it). I know from the Webpack folks - webpack/webpack#12637 (comment) - that relying on asset.info.sourceFilename
IS the correct way to do things.
Basically, for reasons that aren't clear, on Windows only, if you installed Webpack 5 via npm install webpack -D
it would not work. Somewhere, internally, some dependencies must have gotten "crossed". But if you manually change the peerDependencies
and devDependencies
for Webpack and then run npm install
, things work fine. This... almost killed me. But it turns out that this was an edge-case npm + Windows bug of some sort... or possibly some edge case since the package.json
file is mixed with libraries that have Webpack 4 vs Webpack 5 as their peer dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fascinating. What we need to know before we merge is why this was an issue only now. We've been testing webpack v4 and webpack v5 separately with the windows workflows without issue up to this point. So what's the missing bit of nuance as to why it's an issue now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weaverryan ping on this comment
t.truthy(manifest); | ||
t.deepEqual(Object.keys(expected), ['main.js', 'images/manifest.svg']); | ||
t.deepEqual(manifest['main.js'], 'main.js'); | ||
t.regex(manifest['images/manifest.svg'], /images\/manifest\.[a-z|\d]{4}\.svg/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this so I could do a fuzzy check on the hash. The [fullhash]
thing does not work for assetModuleFilename
, so I needed to use a real hash.
This is now ready!!!!!! I have updated the PR description. In short, a crazy npm+Windows bug caused an "invalid" problem, which the test suite now works around. I was also able to simplify the PR a bit after getting guidance from the Webpack folds. Please let me know if you need anything else - I'm hoping (now that this is finally complete... and it almost killed me 😉 ) that we could release this soon (and then I can avoid releasing my "copy" of the plugin inside symfony/webpack-encore). Thanks! |
…fest-plugin fix) (weaverryan) This PR was squashed before being merged into the main branch. Discussion ---------- Fixing manifest paths (by temporarily embedding webpack-manifest-plugin fix) This temporarily embeds shellscape/webpack-manifest-plugin#249, which fixes #907 and also a comment on #914 (comment) To test this: ``` $ yarn remove @symfony/webpack-encore $ yarn add git://github.com/weaverryan/webpack-encore.git#try-manifest-fix ``` Please let me know if this does or doesn't fix your `manifest.json` file. I'm also interested in hearing from Windows users, as the fix requires some "path" manipulation. Thanks! Commits ------- b81428d Fixing manifest paths (by temporarily embedding webpack-manifest-plugin fix)
@weaverryan as we were having some issues with Webpack 5, webpack-manifest-plugin and copy-webpack-plugin (seemingly related to #237 and #238), I tried out your branch. It seems to fix some of the issues, but still handles one case incorrectly. We have something in our Webpack config that looks like
Under Webpack 4 (with webpack-manifest-plugin 2.2.0) this resulted in the following manifest entries. I assume these to be correct.
Under Webpack 5 (with webpack-manifest-plugin 3.0.0, without your fix) this resulted in the following entries:
Now with your fix we only get a single manifest entry for the favicons:
It seems like the logic to combine the dirname from one path with the basename of another from weaverryan/webpack-encore@d83e6db#diff-8a4026eedbd67006d86faab015b15c08372284c5c957cfd5a49e0faf8dd85396R34 does not work nicely when files copied using copy-webpack-plugin get a different name than they had originally, especially if the original names collide. Would there be a way to change your fix to handle this situation correctly? I looked at a possible solution, but I have to admit I'm too unfamiliar with Webpack internals and asset modules to grasp what exactly is going on. Maybe it's necessary to distinguish the asset module case from the copied asset case using |
@aboks I'm going to merge this one now so folks get the benefit of the changes. We can iterate to solve that last case later on. |
This PR contains:
Are tests included?
Breaking Changes?
If yes, then include "BREAKING CHANGES:" in the first commit message body, followed by a description of what is breaking.
List any relevant issue numbers: Fixes #238 and fixes #237 (also fixes symfony/webpack-encore#907)
Description
Hi!
I maintain @symfony/webpack-encore, and we recently upgraded to Webpack 5 and have hit issues with the
manifest.json
file. So, I dug into it :).This is complex, and I hope someone may have some ideas on how to make this nicer. Here is the situation:
A) As far as I (and the test suite) can tell,
chunk.auxiliaryFiles
is only needed to get sourcemap files. All other files are available in other ways. Since allchunk.auxiliaryFiles
were used before, it caused #237 because when we loop over these files, we re-use the samechunk.name
over and over again (and then just add the correct extension like.svg
). So, we need to use some of these, but not all of them. To do that, we collect all the "auxiliary files", then check which have not been added to the manifest at the end. Those that are missing (sourcemaps) are added.B) The second issue - and the one that fixes #238 - is more complex. Basically, if you're using the new "asset modules" system in Webpack 5, then the
emitFile()
method - which we rely on in thenormalModuleLoaderHook
is never called. In fact, as far as I can tell, this method was only ever called by thefile-loader
- https://github.com/webpack-contrib/file-loader/blob/467e6b782bb8bb9fcb54dcb981b5df1a2aeae818/src/index.js#L81 (this
is theloaderContext
) - it's never called by Webpack directly.When you use "asset modules", there is no
file-loader
and so this is never called. According to the Webpack people - webpack/webpack#12637 (comment) - we should rely onasset.info.sourceFilename
as the "source of truth". We were already using that, but sort of "incorrectly" - theasset.info.sourceFilename
will be equal to something like'../../assets/logo.png'
or'node_modules/something/fonts/lato-normal.abc123.woff2'
. So, what we need is thebasename
of this prefixed by thedirname
ofasset.name
(which will be something likefonts/lato-normal.abc123.woff2
).To test in your project
If you're having this issue, I would love if this fix could be validated:
Thanks!