-
-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
const { dirname, join, basename } = require('path'); | ||
|
||
const generateManifest = (compilation, files, { generate, seed = {} }) => { | ||
let result; | ||
if (generate) { | ||
|
@@ -25,7 +27,13 @@ const getFileType = (fileName, { transformExtensions }) => { | |
}; | ||
|
||
const reduceAssets = (files, asset, moduleAssets) => { | ||
const name = moduleAssets[asset.name] ? moduleAssets[asset.name] : asset.info.sourceFilename; | ||
let name; | ||
if (moduleAssets[asset.name]) { | ||
name = moduleAssets[asset.name]; | ||
} else if (asset.info.sourceFilename) { | ||
name = join(dirname(asset.name), basename(asset.info.sourceFilename)); | ||
} | ||
|
||
if (name) { | ||
return files.concat({ | ||
path: asset.name, | ||
|
@@ -52,29 +60,43 @@ const reduceAssets = (files, asset, moduleAssets) => { | |
}); | ||
}; | ||
|
||
const reduceChunk = (files, chunk, options) => | ||
Array.of(...Array.from(chunk.files), ...Array.from(chunk.auxiliaryFiles || [])).reduce( | ||
(prev, path) => { | ||
let name = chunk.name ? chunk.name : null; | ||
// chunk name, or for nameless chunks, just map the files directly. | ||
name = name | ||
? options.useEntryKeys && !path.endsWith('.map') | ||
? name | ||
: `${name}.${getFileType(path, options)}` | ||
: path; | ||
const reduceChunk = (files, chunk, options, auxiliaryFiles) => { | ||
// auxiliary files contain things like images, fonts AND, most | ||
// importantly, other files like .map sourcemap files | ||
// we modify the auxiliaryFiles so that we can add any of these | ||
// to the manifest that was not added by another method | ||
// (sourcemaps files are not added via any other method) | ||
Array.from(chunk.auxiliaryFiles || []).forEach((auxiliaryFile) => { | ||
auxiliaryFiles[auxiliaryFile] = { | ||
path: auxiliaryFile, | ||
name: basename(auxiliaryFile), | ||
isInitial: false, | ||
isChunk: false, | ||
isAsset: true, | ||
isModuleAsset: true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
}; | ||
}); | ||
|
||
return Array.from(chunk.files).reduce((prev, path) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
let name = chunk.name ? chunk.name : null; | ||
// chunk name, or for nameless chunks, just map the files directly. | ||
name = name | ||
? options.useEntryKeys && !path.endsWith('.map') | ||
? name | ||
: `${name}.${getFileType(path, options)}` | ||
: path; | ||
|
||
return prev.concat({ | ||
path, | ||
chunk, | ||
name, | ||
isInitial: chunk.isOnlyInitial(), | ||
isChunk: true, | ||
isAsset: false, | ||
isModuleAsset: false | ||
}); | ||
}, | ||
files | ||
); | ||
return prev.concat({ | ||
path, | ||
chunk, | ||
name, | ||
isInitial: chunk.isOnlyInitial(), | ||
isChunk: true, | ||
isAsset: false, | ||
isModuleAsset: false | ||
}); | ||
}, files); | ||
}; | ||
|
||
const standardizeFilePaths = (file) => { | ||
const result = Object.assign({}, file); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* This file sets Webpack version - both devDependencies and peerDependencies. | ||
* | ||
* This is, for some reason, needed with Windows and maybe npm 6. Running | ||
* "npm install webpack -D" AND manually updating the peerDependencies | ||
* (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 commentThe reason will be displayed to describe this comment to others. Learn more. This is insanity, but THIS turned out to be the reason that Basically, for reasons that aren't clear, on Windows only, if you installed Webpack 5 via There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. @weaverryan ping on this comment |
||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const version = process.argv[2]; | ||
if (!version) { | ||
console.log('Please pass the webpack version - "^4" or "^5" - as an argument.'); | ||
|
||
process.exit(1); | ||
} | ||
|
||
const packageData = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'))); | ||
packageData.peerDependencies.webpack = version; | ||
|
||
packageData.devDependencies.webpack = version; | ||
|
||
fs.writeFileSync(path.join(__dirname, 'package.json'), JSON.stringify(packageData, null, 2)); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import '../../assets/manifest.svg'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. If you end the file in 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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?). |
||
}; | ||
|
||
await compile(config, {}, t); | ||
|
||
const manifestPath = join(outputPath, 'webpack.manifest.js'); | ||
const manifestPath = join(outputPath, 'webpack.manifest.json'); | ||
const result = readJson(manifestPath); | ||
|
||
t.deepEqual(result, { 'main.js': 'main.js' }); | ||
|
@@ -41,11 +41,11 @@ test('output using absolute path', async (t) => { | |
filename: '[name].js', | ||
path: absOutputPath | ||
}, | ||
plugins: [new WebpackManifestPlugin({ fileName: join(absOutputPath, 'webpack.manifest.js') })] | ||
plugins: [new WebpackManifestPlugin({ fileName: join(absOutputPath, 'webpack.manifest.json') })] | ||
}; | ||
await compile(config, {}, t); | ||
|
||
const manifestPath = join(absOutputPath, 'webpack.manifest.js'); | ||
const manifestPath = join(absOutputPath, 'webpack.manifest.json'); | ||
const result = readJson(manifestPath); | ||
|
||
t.deepEqual(result, { 'main.js': 'main.js' }); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,15 +75,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 commentThe reason will be displayed to describe this comment to others. Learn more. Just making the test more interesting. |
||
path: join(outputPath, 'source-maps') | ||
} | ||
}; | ||
const { manifest } = await compile(config, t); | ||
|
||
t.deepEqual(manifest, { | ||
'one.js': 'one.js', | ||
'one.js.map': 'one.js.map' | ||
'one.js': 'build/one.js', | ||
'one.js.map': 'build/one.js.map' | ||
}); | ||
}); | ||
|
||
|
@@ -158,11 +158,6 @@ test('outputs a manifest of no-js file', async (t) => { | |
'file.txt': 'file.txt' | ||
}; | ||
|
||
// 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 commentThe reason will be displayed to describe this comment to others. Learn more. It turns out, these are now fixed! They are #237 |
||
|
||
t.truthy(manifest); | ||
t.deepEqual(manifest, expected); | ||
}); | ||
|
@@ -188,3 +183,37 @@ test('make manifest available to other webpack plugins', async (t) => { | |
t.pass(); | ||
} | ||
}); | ||
|
||
if (!webpack.version.startsWith('4')) { | ||
test('works with asset modules', async (t) => { | ||
const config = { | ||
context: __dirname, | ||
entry: '../fixtures/import_image.js', | ||
output: { | ||
path: join(outputPath, 'auxiliary-assets'), | ||
assetModuleFilename: `images/[name].[hash:4][ext]` | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.(svg)/, | ||
type: 'asset/resource' | ||
} | ||
] | ||
} | ||
}; | ||
|
||
const { manifest } = await compile(config, t); | ||
const expected = { | ||
'main.js': 'main.js', | ||
'images/manifest.svg': `images/manifest.14ca.svg` | ||
}; | ||
|
||
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 commentThe 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 |
||
}); | ||
} else { | ||
test.skip('works with asset modules', () => {}); | ||
} |
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 thefile-loader
/ NormalModule situation -webpack-manifest-plugin/lib/hooks.js
Line 122 in 9f408f6