Skip to content

Upgrade to Webpack 4 #250

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

Closed
thekonz opened this issue Jan 25, 2018 · 41 comments
Closed

Upgrade to Webpack 4 #250

thekonz opened this issue Jan 25, 2018 · 41 comments

Comments

@thekonz
Copy link

thekonz commented Jan 25, 2018

As you might have already seen: Webpack 4 beta is out

This beta release is pretty much stable and will be released as such in a month.

As promised, we will wait a month from today before releasing webpack 4 stable

The new release offers a lot simpler configuration and better compression. This should reduce the amount of code in encore and yield better results in production.

@Lyrkan
Copy link
Collaborator

Lyrkan commented Jan 25, 2018

This should reduce the amount of code in encore

That would be the case if we drop Webpack 2 and 3 compatibility... which is probably ok for new projects but would prevent existing projects from updating Encore easily.

Making it work with both Webpack 2, 3 and 4 may not be easy though based on some of the changes listed on this page: webpack/webpack#6357

@seyfer
Copy link

seyfer commented Feb 26, 2018

It is released today
https://medium.com/webpack/webpack-4-released-today-6cdb994702d4
waiting for the update 🎆

@weaverryan
Copy link
Member

Yep! We just need someone to create a PR :). Also, some libs we depend on may not yet be compat with 4, but we’ll find out with a PR. Volunteers? It’ll get done faster that way ;)

@enguerranws
Copy link

@weaverryan What do you need in that PR? I started upgrading Webpack version and resolving module dependencies errors, ran yarn test (no errors in the output), but what can I do more to help on this?

Really looking forward to use Encore with Webpack 4 👍

@andrewtch
Copy link

andrewtch commented Mar 25, 2018

Same question here @weaverryan - what do you expect in the PR? As I've tested only extract-text-plugin breaks 4.0 support.

@enguerranws
Copy link

@andrewtch For the moment, I fixed extract-text-plugin breaking by fixing its version to "extract-text-webpack-plugin": "4.0.0-beta.0".

@Lyrkan
Copy link
Collaborator

Lyrkan commented Mar 26, 2018

Hi @enguerranws,

I'd say that if you have something that works with Webpack 4 you can already create a PR for it.
That'll help to see if something more is needed :)

I'm really interested to see how you handled some of the other things that changed in this version (such as the new mode option and the removal of CommonsChunkPlugin and UglifyJsPlugin).

Does your version still works with Webpack 3 by the way ? (even though I'm not sure we should keep supporting it, WDYT @weaverryan ?)

@stof
Copy link
Member

stof commented Apr 5, 2018

Well, the new mode option maps directly to our concept of Encore.isProduction(), so this is probably the easiest part of the migration.

@stof
Copy link
Member

stof commented Apr 5, 2018

I would be totally fine with requiring webpack 4 for a new version of Encore, assuming it is a semver major (which would be the case anyway as we are pre-1.0). Maintaining both support for version 3 and 4 in parallel would probably be a nightmare, especially given that the npm ecosystem does not resolve a common versions of deps (so we might end up having webpack 4 installed as a dependency of Encore and webpack 3 installed as a dependency of something else, or the opposite...). It might create more issues than what it solves. People needing to stay on Webpack 3 would have to do some special things anyway to force their whole no_modules to stay on v3 once Encore supports v4. It might be much simpler to tell them to stay on the previous version of Encore, and to upgrade when their other plugins are compatible with webpack 4.

@stof
Copy link
Member

stof commented Apr 5, 2018

for the CSS, we should migrate to https://github.com/webpack-contrib/mini-css-extract-plugin for Webpack 4

@Lyrkan
Copy link
Collaborator

Lyrkan commented Apr 5, 2018

Well, the new mode option maps directly to our concept of Encore.isProduction()

@stof From my understanding it is used to enable some loaders/plugins presets (source maps, minification, etc...). It could make some things from the Encore API a bit awkward since we also have methods that directly control these kind of things (especially enableSourceMaps).

That's why I was wondering if it wouldn't be better to use mode: "none" and keep handling everything ourselves.

@weaverryan
Copy link
Member

Initially, I think Stof has a good point about creating a new version of Encore that only supports Webpack 4. Most users don’t care about the underlying version anyways.

At this point, we just need to create a PR and start hacking on it. It’s been on my list (probably you to @Lyrkan), just haven’t gotten to it yet.

But I would love to do this soon and be progressive :).

@stof
Copy link
Member

stof commented Apr 11, 2018

Well, the goal of Encore is to make webpack easier to use. If webpack 4 gives us sensible defaults for the dev and prod modes, we may want to deprecate our own APIs enabling the sourcemaps for instance, and relying on the webpack decision (that even means less code to maintain for us).
Webpack 4 introduced modes to make their configuration easier, which is also what we want to achieve in Encore. It totally makes sense to have some of our APIs becoming obsolete thanks to the underlying work.

@enguerranws
Copy link

enguerranws commented Apr 12, 2018

Initially, I think Stof has a good point about creating a new version of Encore that only supports Webpack 4. Most users don’t care about the underlying version anyways.

I totally agree on that. Since @Lyrkan pointed that up, I'm thinking of cases and projects that would need a Webpack 4 "Webpack 3 compatible". Didn't find it out.

@Lyrkan
Copy link
Collaborator

Lyrkan commented Apr 12, 2018

I was thinking of cases and projects that would need a Webpack 4 "Webpack 3 compatible". Didn't find it out.

It could be needed if someone wants to use Encore with a Webpack plugin (for instance by using Encore.addPlugin()) that doesn't support Webpack 3 yet.

@stof
Copy link
Member

stof commented Apr 12, 2018

@Lyrkan for such case, they could use an older release of Encore. It would be much more easier than fighting with npm or yarn to make them use older versions of the Encore deps.

@stof
Copy link
Member

stof commented Apr 12, 2018

and yes, such resolution is much harder to achieve in the JS world than with composer, because of the fact that composer resolves a single version of each package (so you can influence them from the root), while npm/yarn are able to use different versions of the same package in different places in the tree (thanks to the fact that nothing is global in JS modules, unlike in PHP where class definitions are global)

@enguerranws
Copy link

enguerranws commented May 15, 2018

Any update on that issue? Really looking forward to use Encore again (I temporary switched to a pure - not Encore - Webpack 4 build).

@stof
Copy link
Member

stof commented May 16, 2018

Note that while starting to use webpack in my project (still a WIP for now), I actually decided to use Webpack 4 instead of using Encore. And I found it quite easy to use (their new mode handles most things automatically for me). The most complex part of my config is related to a need that Encore not solve for me anyway.

@weaverryan
Copy link
Member

@stof I'm curious - did you dod anything special in your setup related to having a "common chunk" (the plugin is gone of course, which is why I'm asking). That's one of the big changes that I haven't looked into yet.

No work has been done on this yet - need to find some time :)

@enguerranws
Copy link

@stof same here, using a pure Webpack 4 build is quite easy, the only thing I'm missing is the Webpack HRM that I'm not able to enable.

@stof
Copy link
Member

stof commented May 16, 2018

@weaverryan Webpack 4 defines splitting cache groups (the new system used by the SplitChunksPlugin replacing CommonsChunkPlugin) automatically for node_modules. By default, it does it only for dynamic chunks (places where you use import() for code splitting), as webpack controls this code to be able to import multiple chunks. This is the code needed to use the builtin splitting also for the main entry points (for which you have to take care of loading the JS files in your HTML):

module.exports = {
  entry: {
    'js/app': './assets/js/app.js'
  },
  output: {
    filename: '[name].js',
    path: 'public/build/',
    publicPath: '/build/'
  },
  plugins: [
    // TODO add a ManifestPlugin
  ],
  optimization: {
    runtimeChunk: 'single', // Extract the runtime to its own chunk
    splitChunks: {
      chunks: 'all' // Split all chunks, not only dynamic ones
    }
  }
}

This will create the following files in public/js:

  • runtime.js: equivalent of Encore's manifest.js file
  • app.js: your own code
  • vendors~app.js: vendor files for the app entry point, if there are enough (webpack has a min size condition to extract it). Note that the ~ delimiter is configurable if you prefer something else.

@stof
Copy link
Member

stof commented May 16, 2018

this is of course missing the loaders rules in case you want to customize them

@stof
Copy link
Member

stof commented May 16, 2018

Actually, runtimeChunk should be manifest if you want to match the name used in Encore. When using single, it will create a file named runtime.js, not manifest.js (which is a better name btw, as this is not about a manifest but about the webpack runtime)

@weaverryan
Copy link
Member

Thanks for the details! What I’m trying to determine is the best strategy going forward. Currently, we allow people to create their single commons entry and put whatever they choose into it explicitly. But, that seems contrary to the Webpack 4 way, where it uses sensible rules to figure things out.

Part of the problem is that if we want to split all chunks, then the user will need some extra tool on the server side to know what script tags are needed dynamically. Or, we could only do async out of the box. Or we could use the new system to re-create our old setup (where you explicitly choose one shared/commons entry). As usual, backend devs have a slightly different use case (multi entry apps commonly, inability to use the HtmlWebpackPlugin), so the best path isn’t clear.

@weaverryan weaverryan mentioned this issue May 16, 2018
17 tasks
@weaverryan
Copy link
Member

In progress - #324 :)

@stof
Copy link
Member

stof commented May 16, 2018

@weaverryan What we could have is a plugin dumping a JSON file mapping an entrypoint to the list of chunks it includes (i.e. storing the info that Webpack has about whether the vendors chunk was created). This would allow to have a small Symfony bundle getting this list.

Note that building the old behavior is also possible by configuring some cacheGroups for the splitChunks plugin (and probably disabling the builtin ones).

@eman1986
Copy link

eman1986 commented Jun 1, 2018

I'm excited to see webpack 4 being supported. I really like the idea around encore and hope to see it supporting webpack 4 really soon. 😁

@iwyg
Copy link

iwyg commented Jun 5, 2018

@stof this sounds great. BTW this is exactly what I did recently using the webpack-manifest-plugin generate hook (not in a symfony project though).

@stof
Copy link
Member

stof commented Jun 5, 2018

@iwyg is your code public ?

@iwyg
Copy link

iwyg commented Jun 5, 2018

@stof sadly no, but I could provide the generator hook if you're interested. This will produce a manifest.json like

{
  "app.js": {
    "path": "/app/dist/app.0bd544445e6ba035f61d.js",
    "dependencies": [
      {
        "name": "runtime~app",
        "files": {
          "js": [
            "/app/dist/runtime~app.d41d8cd98f00b204e980.js"
          ]
        }
      },
      {
        "name": "vendors~app",
        "files": {
          "js": [
            "/app/dist/vendors~app.32c57c5163ee99487c3d.js"
          ]
        }
      },
      {
        "name": "app",
        "files": {
          "js": [
            "/app/dist/app.0bd544445e6ba035f61d.js"
          ],
          "css": [
            "/app/dist/app.0bd544445e6ba035f61d.css"
          ]
        }
      }
    ]
  }
}

@weaverryan
Copy link
Member

You can check the linked PR. Currently, I’m dumping a new entrypoints.json file. It’s a bit simpler, so I’d appreciate it if you see any shortcoming.

@pinoniq
Copy link
Contributor

pinoniq commented Jul 2, 2018

I couldn't see it in the comments here, but we should look into the issues in webpack 4 with uglify-es. It has a couple of big issues, and seems to unsupported. One of my colleagues pointed me on the fact that the way uglify-es works:

When using React, for example, it create a new Component class at each render which will force React to unmount and remount your component.

@seyfer
Copy link

seyfer commented Aug 19, 2018

Since linked PR merged - this one could be closed?

@quentin-st
Copy link

When will this be tagged/released? @seyfer : I guess they'll close this issue when it'll be done

@MrMitch
Copy link

MrMitch commented Oct 10, 2018

Hi @weaverryan, thank you for all the work on this. I see #324 has been merged and the only thing preventing this from being released is the doc which needs to be updated

Document use of browserslist + update Encore recipe

How can we help on that ?

@roland4432
Copy link

Any updates?

@Lyrkan
Copy link
Collaborator

Lyrkan commented Nov 5, 2018

Version 0.21.0 has been released :)

@Lyrkan Lyrkan closed this as completed Nov 5, 2018
@MrMitch
Copy link

MrMitch commented Nov 5, 2018

Nice, thank you for that, we're all eager to try it out.
Since the changelog mentions a few [BC BREAK], shouldn't the major version have changed (i.e. 1.0.0) ?

@Lyrkan
Copy link
Collaborator

Lyrkan commented Nov 5, 2018

@MrMitch This shouldn't be an issue for now (= before 1.0.0 is tagged) since, for instance, having ^0.20.0 in your package.json file won't allow 0.21.0 to be installed. This behavior is explained on this page:

Caret Ranges ^1.2.3 ^0.2.5 ^0.0.4
Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple.

@antishov
Copy link

@Lyrkan great news, thanks a lot!

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

No branches or pull requests