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

WIP: upgrade to Webpack 5 #34

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

justinfagnani
Copy link

@justinfagnani justinfagnani commented Jan 31, 2021

Addresses #33

I took a crack at upgrading, but I really don't know Webpack well, so I got stuck in a few places. Opening this PR in case a few of the things I got right make for a useful starting point.

Two things that are tricky:

  1. There is no type webpack.Stats.ToJsonOutput. webpack.Stats is a class with a toJson() method, but I don't see any types for it's output. There are JSON schema files, so maybe it's expected to consume one of those? I tried to use the JS interface with stats.compilation, but I'm not sure if that's working yet.
  2. I can't get the Vue loader to work. I get:
    [VueLoaderPlugin Error] No matching use for vue-loader is found.
    Make sure the rule matching .vue files include vue-loader in its use.
    
  3. MemoryFS doesn't implement the OutputFilesystem interface correctly. I casted to any for now.

@sokra
Copy link

sokra commented Feb 2, 2021

3. MemoryFS doesn't implement the OutputFilesystem interface correctly. I casted to any for now.

This is deprecated in favor of memfs, which is a more complete memory filesystem.

@sokra
Copy link

sokra commented Feb 2, 2021

  1. There is no type webpack.Stats.ToJsonOutput. webpack.Stats is a class with a toJson() method, but I don't see any types for it's output. There are JSON schema files, so maybe it's expected to consume one of those? I tried to use the JS interface with stats.compilation, but I'm not sure if that's working yet.

The typings are a bit incomplete here, but the JSON data is mostly the same except for a few minor changes.

@43081j
Copy link

43081j commented Feb 2, 2021

hey justin 👋

the vue stuff is broken because the svelte rule is matched by the vue plugin, which breaks the loop and never reaches the vue rule.

see here:
https://github.com/vuejs/vue-loader/blob/a2b89d3c44011e9c8c4af523a8d7039d9b27705c/lib/plugin-webpack5.js#L58-L66

the plugin iterates through all the rules. for each rule, it tests it against foo.vue and, if that fails, it tries foo.vue.html. in our case, foo.vue.html matches the svelte rule before the iteration has reached the vue rule.

switching them around might fix it but feels a bit delicate, easy to break again if someone isn't aware of this behaviour

i suppose really its a bug in vue-loader in that it shouldn't break the loop until it finds a vue-loader rule, if ever.


return new Promise<CompilePackageReturn>(resolve => {
compiler.run((err, stats) => {
const error = (err as unknown) as WebpackError // Webpack types incorrect
// stats object can be empty if there are build errors
resolve({ stats, error, memoryFileSystem })
resolve({ stats: stats!, error, memoryFileSystem })
Copy link

Choose a reason for hiding this comment

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

stats can be empty if there was an error FYI

@43081j
Copy link

43081j commented Feb 2, 2021

also the test fails for some unrelated error right now:

Error: Conflict: Multiple chunks emit assets to the same filename bundle.js (chunks main and runtime)

Which also reveals that we have a problem here:

let jsonStats = stats.toJson({
assets: true,
children: false,
chunks: false,
chunkGroups: false,
chunkModules: false,
chunkOrigins: false,
modules: true,
errorDetails: false,
entrypoints: false,
reasons: false,
maxModules: 500,
performance: false,
source: true,
depth: true,
providedExports: true,
warnings: false,
modulesSort: 'depth',
})
if (!jsonStats) {
throw new UnexpectedBuildError(
'Expected webpack json stats to be non-null, but was null'
)
}
if (error && !stats) {
throw new BuildError(error)

you can see at the bottom we check if (error && !stats), but if stats was falsy then the toJson call further up would throw and be uncaught. we should probably shuffle that around a bit so we're accounting for the fact stats can be empty, rather than always calling toJson regardless

Copy link

@sokra sokra left a comment

Choose a reason for hiding this comment

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

Error: Conflict: Multiple chunks emit assets to the same filename bundle.js (chunks main and runtime)

This is caused by output.filename: 'bundle.js'. Better use the default output.filename: "[name].js" otherwise the main entry and runtime runtimeChunk, will lead to the same filename bundle.js.

// comments: false,
// },
// },
// }),
Copy link

Choose a reason for hiding this comment

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

You can reference the default (terser) with "..." in webpack 5.

@sokra
Copy link

sokra commented Mar 2, 2021

  1. There is no type webpack.Stats.ToJsonOutput

webpack.StatsCompilation will do that.

@sokra
Copy link

sokra commented Mar 2, 2021

3. MemoryFS doesn't implement the OutputFilesystem interface correctly. I casted to any for now.

That's fixed now

@43081j
Copy link

43081j commented Mar 28, 2021

i can try pick this up if you don't have time @justinfagnani

@sokra webpack5 has its own types now i see, but it doesn't export quite a few of the interfaces it uses. for example, the changes justin has here need StatsAsset which isn't an exported interface. ideally all types exposed on exported functions/classes/etc should also be exported i think

@justinfagnani
Copy link
Author

I definitely don't have time right now, so that'd be great @43081j !

I guess it'd be nice to file issues/PRs on Webpack to export the type interfaces needed here.

@43081j
Copy link

43081j commented Mar 29, 2021

No worries, I'll have a go at finishing it off.

Also have opened a PR at definitelytyped to update the mini-css plugin so you don't have to cast it as any. Will see if I can get that done first

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