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

chore: update to webpack v5 #27438

Merged
merged 37 commits into from
Aug 9, 2023
Merged

Conversation

AtofStryker
Copy link
Contributor

@AtofStryker AtofStryker commented Aug 1, 2023

What is in this PR

This PR updates the cypress monorepo to use webpack@5 from webpack@4 doing the bare minimum updating to get webpack 5 working. This handles the Test webpack 5 compatibility and Upgrade webpack to 5 steps in the migration guide

The main goal of updating to webpack 5 is to get with the recent dependency updates, as well as unblock the electron v25 upgrade. Since newer versions of Electron run on Node 18, it causes issues with --openssl-legacy-provider, which is fixed by this upgrade (see code removed in b973ca5 ). See

Most the changes needed are well documented inside the code as to why we need them. This includes

  • 2 dependency patches, one to whatwg-url and another to enhanced-resolve due to polyfilled differences (see code). In addition to these patches and to make sure they are applied correctly, dev dependency patches are not carried over to the build directory (see 53e304f).
  • polyfilling node built ins for the webpack.base.config.ts inside web-config for Cypress internally, as well as polyfilling correctly for the webpack-batteries-included-preprocessor through resolve.fallback, ProvidePlugin, and DefinePlugin
  • addressing some subtle differences in the path polyfill code (see f01f645)
  • addressing small issue where first bundled returned promise reference was changing under the hood, making the webpack-preprocessor time out (see 1fa6183). This promise reference seems to be preserved correctly in webpack@4, which seems odd since it should not be as the webpack@5 handles this correctly.
  • a few snapshot changes in system-tests, mainly due to difference source-map paths and console outputs
Performance considerations

@mjhenkes and I looked into the telemetry data on the initial green build of the run. We both feel confident the performance currently is about the same and no major regressions are present.

What is NOT in this PR

Loader/Plugin updates are not in this PR as they are not needed to update to webpack@5. However, we should update to the latest loaders to gain benefits of recent versions, which will be done in a follow up PR

Additionally, there are still build warnings that need to be fixed from the webpack@5 update. These will also be addressed in a follow up PR to prevent any breakages when deprecated behavior is removed.

Optimizations to the build also need to be performed, which will be addressed in a separate PR. see clean up configuration in the migration guide.

Is this a breaking change to cypress?

This is NOT a breaking change to cypress, however it does change the way cypress is bundled under the hood. This should not break end users. However, since polyfills have been removed in webpack@5, we need to make sure that dependencies that are bundled via the ProvidePlugin are available dependencies in a user's project if cypress is installed. Otherwise, bundling could fail. This means that buffer and process need to be installed with the CLI in the case a user does NOT have buffer or process as a fallback in their dependency tree. Other polyfills that are set through resolve.fallback are installed locally to the dependency (such as webpack-batteries-included-preprocessor) and can be discovered at processing time without having to hoist/install dependencies in the users root node_modules (see 697f8bf).

The other aspect that might be considered breaking is the subtle changes to the node built ins from webpack@4 to webpack@5. We know some of the APIs have changed slightly to the built ins. We have discussed this at length at Cypress, and will NOT be considering this a breaking change. The likelihood users are broken by built in changes is incredibly small, and in the case this is a problem, the user can either:

If users are using the file:preprocessor hook inside plugins, users can still use webpack@4 still and will not be broken, even though cypress is bundled with webpack 5. The only stipulation to continuing using webpack@4 is that users remain on Node 16 as webpack@4 has this issue that will not be backpatched from webpack. We recommend users upgrade to recent versions of webpack and node, as Node 16 will be EOL in Q3 of 2023

Do we need to publish new major versions of webpack-preprocessor, webpack-dev-server, and webpack-batteries-included-preprocessor?

The only package that will require a major version publish from this change will be @cypress/webpack-batteries-included-preprocessor as it will be shipping with webpack@5 from now on. The breaking changes will be included in this PR, but will NOT be published in this PR as it is flagged as a chore and NOT BREAKING_CHANGE. The BREAKING_CHANGE commit will be handled in a subsequent PR (see #27469). The strategy for release of this PR will be:

Steps to test

Give it a run for yourself locally and make sure everything is good on your end, as well as downloading and testing the binary. We have a green circle build for CI testing to make sure everything is good there.

How has the user experience changed?

PR Tasks

@AtofStryker AtofStryker changed the title Chore/update to webpack5 minimum lift Chore: update to webpack v5 Aug 1, 2023
@AtofStryker AtofStryker changed the title Chore: update to webpack v5 chore: update to webpack v5 Aug 1, 2023
@AtofStryker AtofStryker marked this pull request as ready for review August 1, 2023 21:15
@cypress
Copy link

cypress bot commented Aug 1, 2023

7 flaky tests on run #49630 ↗︎

0 466 20 0 Flakiness 7

Details:

chore: add changelog event
Project: cypress Commit: 721d6a5ffc
Status: Passed Duration: 18:40 💡
Started: Aug 9, 2023 3:42 PM Ended: Aug 9, 2023 4:00 PM
Flakiness  cypress\e2e\specs.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
... > shows No Specs page with specPattern from config Output Screenshots Video
Flakiness  cypress\e2e\create-from-component.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
... > Shows create from component card for React projects Output Screenshots Video
Flakiness  cypress\e2e\runs.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
App: Runs > no internet connection > shows correct message on create org modal Output Screenshots Video
Flakiness  cypress\e2e\cypress-in-cypress.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
Cypress in Cypress > scales the AUT correctly in component Output Screenshots Video
Flakiness  cypress\e2e\specs_list_latest_runs.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
App/Cloud Integration - Latest runs and Average duration > when no runs are recorded > shows placeholders for all visible specs Output Screenshots Video

The first 5 flaky specs are shown, see all 7 specs in Cypress Cloud.

This comment has been generated by cypress-bot as a result of this project's GitHub integration settings.

@lmiller1990 lmiller1990 self-requested a review August 1, 2023 21:58
@lmiller1990
Copy link
Contributor

lmiller1990 commented Aug 1, 2023

This should also add support for many historic issue that had "fixes", now those will work out of the box. Example issues:

And any others relating to wepback compilation errors and newer JS syntax.

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Left some comments / questions, looks good!

Unresolved question: how to release this? I think this will be a Cy 13 breaking change. Migration path isn't clear, though - if there's some way to modify the webpack config without installing @cypress/webpack-preprocessor, this is going to be hard.

I suspect this IS NOT a problem. The reason is the docs say:

Note that installing @cypress/webpack-preprocessor is also required. This allows you to update its version separately from this wrapper. npm install --save-dev @cypress/webpack-batteries-included-preprocessor @cypress/webpack-preprocessor

So anyone who wanted to this is on the OLD version of preprocessor. Since we will make this breaking, it'll bump the major. If they upgrade, they'll need to make changes. We might need some notes on how to do that, but they could just refer to the webpack 4-5 migration guide.

* in order to guarantee there is a version of the dependency accessible by the cypress CLI, either in the cypress directory
* or the root of their project. Currently, these two dependencies are 'buffer' and 'process'
*/
describe('dependencies', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I have some questions about this. If webpack 4 polyfilled all core Node.js libs out of the box, does that mean you could (and can)

  • install cypress 12
  • write a spec that imports fs
  • have it run successfully (eg, fs won't error out)

I haven't tried this yet, but worth considering. I know we don't do this in our code base, but I'm sure some code bases rely on those polyfills (especially crypto).

I wonder if we need to polyfill ALL the core modules to maintain backwards compatibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it depends. fs is probably a bad example here since we intentionally leave it empty in the webpack-batteries-included-preprocessor and don't expect that built in to be available. But for something like crypto for your example, you could do all those steps and it will not error out since we install the polyfill. I think you talked about it in another spot in this PR, but this comment explains it for anyone else reading


expect(dependencies.buffer).to.be.ok

const buffer = require('buffer')
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we assert that

require('node:buffer') !== require('buffer')

That would verify the Buffer you get is not the core Node.js one. You can use require('node:<module>') to get the core one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that might be a good idea, considering we really want to just make sure the buffer is installed in the package through the package.json and its accessible

stream: require.resolve('stream-browserify'),
string_decoder: require.resolve('string_decoder/'),
sys: require.resolve('util/'),
timers: require.resolve('timers-browserify'),
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, maybe we do polyfill them all. My previous comment may be irrelevant.

Big breaking change here - who knows if these implementations match whatever webpack 4 was doing.

Tracking down the right polyfill here must have been complex.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, maybe we do polyfill them all. My previous comment may be irrelevant.

Big breaking change here - who knows if these implementations match whatever webpack 4 was doing.

This for sure breaks the webpack-batteries-included-preprocessor . In this case, we polyfill most of them and are fairly explicit about the ones we don't in the config. We also have a few tests in place since just about everything goes through the preprocessor. The tests that we do check for the polyfills are this system test in plugins_spec.js which uses this spec and checks for just about every polyfill in this gist except for the ones starting with _, in particular the readable-stream dependencies. There is also this unit test that pretty much tests the same thing. At least for the built ins we are want to convey we support we should be covered.

Tracking down the right polyfill here must have been complex.

this gist for sure helped to figure out what was going on

const nextBundle = utils.createDeferred<string>()
/**
* Webpack 5 fix:
* If the bundle is the initial bundle, do not create the deferred promise
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice job figuring this out 💯

packages/driver/src/cy/commands/files.ts Show resolved Hide resolved
packages/web-config/webpack.config.base.ts Outdated Show resolved Hide resolved
patches/enhanced-resolve+5.15.0.dev.patch Show resolved Hide resolved
@AtofStryker
Copy link
Contributor Author

Unresolved question: how to release this? I think this will be a Cy 13 breaking change. Migration path isn't clear, though - if there's some way to modify the webpack config without installing @cypress/webpack-preprocessor, this is going to be hard.

This is the big thing to figure out here. Unless there is a way to ship new major versions of the npm dependencies without shipping a major version of the binary, This will need to go in with v13. And if we aren't sure on any pieces, this might be the safest bet.

@lmiller1990 lmiller1990 self-requested a review August 2, 2023 02:43
Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

I am happy with the code, I am going to request changes to BLOCK this until we have a decision on merging / release - this is definitely not chore and most likely needs to be retargeted to target the v13 release branch

@lmiller1990
Copy link
Contributor

I think it's possible to ship this early but bundle the older version in the binary. If Cy 13 is going out this month, it's not worth it, if we expect delays, we should look into it, though.

@AtofStryker
Copy link
Contributor Author

@lmiller1990 I updated the PR description to describe how we are going to release this. We will first merge this in as a chore, with a follow up PR that will apply the BREAKING_CHANGE commit to @cypress/webpack-batteries-included-preprocessor. We are not concerned about built ins breaking and in the very rare case it does impact a user, leveraging the npm preprocessors are an option. I will work on getting the breaking change PR ready for @cypress/webpack-batteries-included-preprocessor` and will update you and the description when ready

@AtofStryker
Copy link
Contributor Author

@lmiller1990 linked #27469 in the PR description in draft. I think this is ready for a re review 😄

Copy link
Member

@jennifer-shehane jennifer-shehane left a comment

Choose a reason for hiding this comment

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

@AtofStryker Suggested changes for the changelog wording.

cli/CHANGELOG.md Outdated Show resolved Hide resolved
Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@@ -7,6 +7,10 @@ _Released 08/15/2023 (PENDING)_

- Fixed an issue where having `cypress.config` in a nested directory would cause problems with locating the `component-index.html` file when using component testing. Fixes [#26400](https://github.com/cypress-io/cypress/issues/26400).

**Dependency Updates:**

- Upgraded [`webpack`](https://www.npmjs.com/package/webpack) from `v4` to `v5`. This means that we are now bundling your `e2e` tests with webpack 5. We don't anticipate this causing any noticeable changes. However, if you'd like to keep bundling your `e2e` tests with wepback 4 you can use the same process as before by pinning [@cypress/webpack-batteries-included-preprocessor](https://www.npmjs.com/package/@cypress/webpack-batteries-included-preprocessor) to `v2.x.x` and hooking into the [file:preprocessor](https://docs.cypress.io/api/plugins/preprocessors-api#Usage) plugin event. This will restore the previous bundling process. Additionally, if you're using [@cypress/webpack-batteries-included-preprocessor](https://www.npmjs.com/package/@cypress/webpack-batteries-included-preprocessor) already, a new version has been published to support webpack `v5`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Would they also need to install webpack@4 to keep things working the same?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not in this case because v2 of webpack-batteries-included-preprocesor ships with 4. its not backwards compatible unlike the regular webpack-preprocessor

whatwg-url@7.1.0 which has a dependency on punycode node expected API.
since punycode is now polyfilled for us implicitly via the punycode npm
package, the API signatures are a bit different
https://github.com/mathiasbynens/punycode.js/blob/main/punycode.js#L101
vs https://nodejs.org/api/punycode.html#punycodeucs2. The patch uses the
punycode npm package expected API and is needed for source maps to work
for cy.origin() dependencies for Cypress.require()
…lled when building the binary / installing prod dependencies
AtofStryker and others added 22 commits August 8, 2023 22:07
…t to avoid having to polyfill Buffer from webpack
…ifferent webpack compiled terminal formatting in the snapshot between local and CI.
…ed as a dep as its used in the config [run ci]
@AtofStryker AtofStryker force-pushed the chore/update_to_webpack5_minimum_lift branch 2 times, most recently from 5d45654 to 721d6a5 Compare August 9, 2023 02:27
@AtofStryker
Copy link
Contributor Author

jobs are passing but for whatever reason the snyk workflows wont run. We are going to admin merge this branch is barring everything else in CI is passing. Passing snyk jobs from previous runs to show no vulnerabilities to build deps https://github.com/cypress-io/cypress/actions/runs/5730373496 & https://github.com/cypress-io/cypress/actions/runs/5730373491

@nagash77 nagash77 merged commit 171d1fa into develop Aug 9, 2023
126 of 127 checks passed
@nagash77 nagash77 deleted the chore/update_to_webpack5_minimum_lift branch August 9, 2023 15:59
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Aug 15, 2023

Released in 12.17.4.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v12.17.4, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Aug 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Investigate Webpack 5 Impact
6 participants