Workaround for Vercel Deployment Failure After Updating to Yarn Berry

tl;dr) Include not only ".yarn" but also "node_modules" into the list of external package folders to avoid ESLint errors!

Workaround for Vercel Deployment Failure After Updating to Yarn Berry
tl;dr)
Include not only ".yarn" but also "node_modules" into the list of external package folders to avoid ESLint errors!

I was trying to update the package manager of our repository from Yarn Classic (yarn v1) to Yarn Berry (yarn v2), by following the Yarn migration document. I enabled the plug and play (PnP) mode, resolved missing package dependency issues, and confirmed that yarn build works properly on my local machine.

The unexpected ESLint errors came up on Vercel.

Shown on the screenshot above, numerous errors occurred from the deployment. However, there are only two types of errors:

Error: There should be no empty line within import group  import/order
Error: `next/router` import should occur after import of `@mui/material/styles`  import/order
Of course, this is one example, and the module names were different for each error.

Looking through the ESLint rules

I checked the line of codes, from which the error occurred:

This file had a "no empty line within import group" error on 3rd line.

Here, the lines 1-3 are external module imports, and the lines 5-7 are internal module imports. Our ESLint rules contain import/order rule that enforces a newline between import groups, and it was throwing an error that there should NOT be an empty line between the import groups!

{
  ...,
  "settings": {
    "import/external-module-folders": ["node_modules", ".yarn"], ...
  },
  "rules": {
    "import/order": ["error", {
      "groups": ["builtin", "external", "internal"],
      "pathGroups": [
        {
          "pattern": "react",
          "group": "external",
          "position": "before"
        },
        {
          "pattern": "@mui/**",
          "group": "external",
          "position": "after"
        }
      ],
      "pathGroupsExcludedImportTypes": ["react"],
      "newlines-between": "always",
      "alphabetize": { "order": "asc" }
    }], ...
  }
}
Partial snippet of the ESLint configuration (eslintrc.json).

In fact, there was a known issue that the eslint-plugin-import will not recognize the plug-and-play modules in the .yarn folder because of module resolution. Therefore, the plugin has an option, named import/external-module-folders, to declare the list of external module folders as mentioned in the plugin reference. Although I correctly added the folder into the list, it seemed that ESLint did not properly recognize the external modules.

However, this issue was not being reproduced in my local environment, so I had to try some fixes and check if it worked on Vercel.

It was very painful, indeed! ๐Ÿ˜ฉ

Debugging from Vercel

After several attempts and failures, I tried enabling the debug mode (--debug option) of ESLint, and this gave me a hint. Checking the ESLint debug log, I was able to find out a weird information:

Partial logs from Vercel deployment

It looked that node_modules folder exists even though we switched to the Yarn PnP mode. Since the package manager will not create the folder, it was likely to be created from Vercel side, such as build cache. The Vercel documentation noted that the folder is being cached to decrease the build time. However, I did not enable build cache for redeployments, so it was highly confusing where it came from.

Anyway, I added node_modules into the list of the external module folders, and the deployment was done without any errors. ๐Ÿคจ

Confused but satisfied

Although the deployment works properly for now, and the web application does not have any issues because of the workaround, I am still confused what is the root cause of this issue. There could be a cache issue within Vercel, but I might be wrong with the Yarn migration.

Also, it is quite painful that I spent 2-3 days on the migration, but it looks quite effective. The time spent on the package managment has been significantly decreased as the following screenshot:

Comparison between yarn classic and yarn berry

We should figure it out for a longer time, but it looks good! ๐Ÿ‘