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

feat: check postcss versions to avoid using PostCSS 7 #527

Merged
merged 9 commits into from Jun 10, 2021
Merged

feat: check postcss versions to avoid using PostCSS 7 #527

merged 9 commits into from Jun 10, 2021

Conversation

shlyk
Copy link
Contributor

@shlyk shlyk commented May 15, 2021

This PR contains a:

  • bugfix
  • new feature
  • code refactor
  • test update
  • typo fix
  • metadata update

Motivation / Use-Case

Added code that helps the developer understand that it is necessary to use an explicit version of PostCSS. Closes #507.

Breaking Changes

No breaking changes.

Additional Info

cc @ai

@shlyk shlyk changed the title feat: check postcss versions to avoid using PostCSS 7 feat: check postcss versions to avoid using PostCSS 7 cc @ai May 15, 2021
@shlyk shlyk changed the title feat: check postcss versions to avoid using PostCSS 7 cc @ai feat: check postcss versions to avoid using PostCSS 7 May 15, 2021
@ai
Copy link
Contributor

ai commented May 15, 2021

LGTM

@alexander-akait can you start CI?

@alexander-akait alexander-akait marked this pull request as ready for review May 15, 2021 12:36
src/index.js Outdated
// Check postcss versions to avoid using PostCSS 7
if (!isCheckedPostCSSVersion && postcss().version.startsWith("7.")) {
isCheckedPostCSSVersion = true;
const pkg = readPackageJson();
Copy link
Member

Choose a reason for hiding this comment

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

It will add one more fs call for each css file, reduce perf very well

Copy link
Contributor

Choose a reason for hiding this comment

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

As I understand, fs call will be only once and only for postcss 7

Copy link
Member

Choose a reason for hiding this comment

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

We can solve it on two ways:

  • webpack already reads package.json, need look where we store it
  • using this.fs, so each call will be cacheable

Copy link
Member

Choose a reason for hiding this comment

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

But it is invalid, in monorepos you can have multiple packages with different versions of postcss

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@alexander-akait can you show examples of such repositories? I'm talking about the mono repository.

@ai
Copy link
Contributor

ai commented May 15, 2021

Previous discussion about this problem #507

@alexander-akait
Copy link
Member

alexander-akait commented May 15, 2021

We will positive false/false positive for monorepos and will spam warnings, it is bad, also we need more strong check here, we can read css file node_modules, we should not try to read package json in this case.

@ai
Copy link
Contributor

ai commented May 15, 2021

Anyway we will run this check only for PostCSS 7 case, which will be rare case.

Should we add deep search and check for package.json? Another option is an environment variable to disable check in rare cases.

@alexander-akait
Copy link
Member

15638766 downloads by week https://www.npmjs.com/package/postcss, it is big number, can't say how many uses potcss-loader, but I think it is big number too.

Should we add deep search and check for package.json? Another option is an environment variable to disable check in rare cases.

To be honest, this is not an easy task, you can see the algorithm in npm/yarn/pnpm and found it is not easy. Also it is not make sense for yarn PnP/pnpm (will be failed by default) and npm v7 (automatically install peer deps)

@ai
Copy link
Contributor

ai commented May 15, 2021

15638766 downloads by week https://www.npmjs.com/package/postcss, it is big number, can't say how many uses potcss-loader, but I think it is big number too.

A lot of PostCSS 7 downloads is coming from plugins. The real number is much smaller.

Right now using PostCSS 7 is insecure because of vulnerability. It forced migration.

To be honest, this is not an easy task, you can see the algorithm in npm/yarn/pnpm and found it is not easy.

We do not need to cover all cases here. We just need to prevent popular error. Edge cases can be fixed by:

  1. We can have an environment variable to disable check
  2. We can use warning instead of error.

Also it is not make sense for yarn PnP/pnpm (will be failed by default) and npm v7 (automatically install peer deps)

I think npm 7 do not install peer dependencies for old dependencies on npm 6→7 migration. It will help only for new project or during installing new postcss-loader.

@alexander-akait
Copy link
Member

I think npm 7 do not install peer dependencies for old dependencies on npm 6→7 migration. It will help only for new project or during installing new postcss-loader.

https://github.blog/2021-02-02-npm-7-is-now-generally-available/#peer-dependencies

@ai
Copy link
Contributor

ai commented May 15, 2021

Since many packages in the ecosystem have come to rely on loose peer dependencies resolutions, npm 7 will print a warning and work around most peer conflicts that exist deep within the package tree, since you can’t fix those anyway.

Yeap. As I understand, npm 7 will not fix old missed peer dependencies.

@shlyk
Copy link
Contributor Author

shlyk commented May 15, 2021

Please help me understand what to do next. Add a warning and an environment variable? Or do you want to do this task more thoroughly in another PR?

@alexander-akait
Copy link
Member

Please help me understand what to do next. Add a warning and an environment variable? Or do you want to do this task more thoroughly in another PR?

I understand your excitement, but it's okay, we just need to discuss a little more and as soon as we come to a decision I immediately ping you

@alexander-akait
Copy link
Member

Yeap. As I understand, npm 7 will not fix old missed peer dependencies.

npm 7 install them by default, no matter whether it is old or new

Anyway the main problem is not npm/yarn/pnpm, searching package.json is the main problem.

I think we should use, simplified, but covered most of cases:

const cwd = process.cwd();
let dir = cwd;
for (;;) {
    try {
        // `this` - is loader context
        if (this.fs.statSync(path.join(dir, 'package.json')).isFile()) break;
    } catch (e) {}
    const parent = path.dirname(dir);
    if (dir === parent) {
      dir = undefined;
      break;
    }
    dir = parent;
}

It's just that from my experience these things usually create more problems than they solve... Package manager output is the place where you need read warnings/errors. All of these workarounds are trying to train the developer to be attentive, but if you do not read errors from your tty, you may need to learn more.. Just my opinion.

@ai
Copy link
Contributor

ai commented May 15, 2021

yarn output is full on warnings about deprecated nested dependencies, which you can't fix. They hide important warning which you can fix.

We know that people ignore this warning. Speaking about “the right way” will not solve the problem.

Another way to fix the problem, is to catch errors from PostCSS and show warning about missed dependency before re-throwing the error.

@alexander-akait
Copy link
Member

Another way to fix the problem, is to catch errors from PostCSS and show warning about missed dependency before re-throwing the error.

Sounds very good, I like it

@ai
Copy link
Contributor

ai commented May 15, 2021

@shlyk a new plan:

  1. Wrap postcss.process can in try catch
  2. On error from postcss we are starting old check
  3. Instead of throwing error, we print warning

@shlyk
Copy link
Contributor Author

shlyk commented May 15, 2021

@shlyk a new plan:

  1. Wrap postcss.process can in try catch
  2. On error from postcss we are starting old check
  3. Instead of throwing error, we print warning

OK

@shlyk
Copy link
Contributor Author

shlyk commented May 15, 2021

@ai and @alexander-akait, please check it out.

src/index.js Outdated
postcssFactory().version.startsWith("7.")
) {
// For caching reasons, we use the readFileSync function from the context, not the function from the `fs` module.
const pkg = readPackageJson(this.fs.readFileSync);
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to check that pacjage.json exists first (print nothing on no file).

Otherwise, it will throw Can’t read file error if package.json was in a different place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, done.

src/index.js Outdated
// not the functions from the `fs` module.
if (
!hasExplicitDependencyOnPostCSS &&
isFileExists(PACKAGE_JSON_PATH, this.fs.existsSync) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Run postcssFactory().version.startsWith("7.") before isFileExists to avoid unnecessary file check for PostCSS 8 users

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 also changed it to call statSync(...).isFile() instead of existsSync(), because existsSync() is not available in this version of Webpack.

src/utils.js Outdated
@@ -408,10 +409,24 @@ function normalizeSourceMapAfterPostcss(map, resourceContext) {
return newMap;
}

function isFileExists(filePath, existsSync = fs.existsSync) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need default value for any cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, I removed the default value. They don't seem to be needed here.

@ai
Copy link
Contributor

ai commented May 17, 2021

@alexander-akait we are ready for your review

src/index.js Outdated
} from "./utils";

let hasExplicitDependencyOnPostCSS = false;

const PACKAGE_JSON_PATH = path.resolve(process.cwd(), "package.json");
Copy link
Member

Choose a reason for hiding this comment

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

cwd can be src (i.e. src/package.json), but it is invalid I provided example above with recusing searching

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it would be possible to use iterators to search for a file (from similar solutions), but it seems that this is not essential here. I took your solution, especially since there is a similar solution in the Webpack source code.

Copy link
Contributor Author

@shlyk shlyk May 17, 2021

Choose a reason for hiding this comment

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

I also use null and undefined to cache calls. For some, this may seem implicit. I can try to make it more explicit, if necessary.

@shlyk
Copy link
Contributor Author

shlyk commented May 20, 2021

@alexander-akait and @ai, are we doing something extra? Any other questions?

@ai
Copy link
Contributor

ai commented May 20, 2021

LGTM. @alexander-akait let’s merge =^_^=

@alexander-akait
Copy link
Member

I'm a little busy now, tomorrow I will merge and do release 👍

@codecov
Copy link

codecov bot commented May 20, 2021

Codecov Report

Merging #527 (833f56b) into master (0c6dcdc) will decrease coverage by 2.11%.
The diff coverage is 72.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #527      +/-   ##
==========================================
- Coverage   97.04%   94.93%   -2.12%     
==========================================
  Files           5        5              
  Lines         271      296      +25     
  Branches       88       96       +8     
==========================================
+ Hits          263      281      +18     
- Misses          8       14       +6     
- Partials        0        1       +1     
Impacted Files Coverage Δ
src/utils.js 92.18% <46.15%> (-3.35%) ⬇️
src/index.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0c6dcdc...833f56b. Read the comment docs.

@alexander-akait
Copy link
Member

@shlyk Can you accept CLA (link in github actions checks)?

@shlyk
Copy link
Contributor Author

shlyk commented May 21, 2021

@alexander-akait done.

@alexander-akait
Copy link
Member

You need to use the same email in commits, can you add it?

@shlyk
Copy link
Contributor Author

shlyk commented May 24, 2021

@alexander-akait done.

@shlyk
Copy link
Contributor Author

shlyk commented Jun 2, 2021

@alexander-akait, it looks like something needs to be done. Is there anything I can do to help?

@alexander-akait
Copy link
Member

@shlyk You still have commits without email (look at your commits above), can you fix it?

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.

Check postcss versions to avoid using PostCSS 7
4 participants