postcss / autoprefixer

Parse CSS and add vendor prefixes to rules by Can I Use
https://twitter.com/autoprefixer
MIT License
21.65k stars 1.26k forks source link

env option does not work #1337

Closed bensampaio closed 4 years ago

bensampaio commented 4 years ago

I am working in a monorepo with the following root configuration:

.browserslistrc

[legacy]
last 2 versions
not dead

[modern]
last 2 Chrome versions
last 2 ChromeAndroid versions
last 2 Firefox versions
last 2 FirefoxAndroid versions
last 2 Safari versions
last 2 iOS versions
last 2 Edge versions

[node]
node 12

babel.config.js

module.exports = {
    presets: [
        ['@babel/preset-env', {
            browserslistEnv: 'node',
            corejs: 3,
            useBuiltIns: 'usage',
        }],
        '@babel/preset-react',
        '@babel/preset-typescript',
    ],
};

Then in packages/app I have a webpack.config.js file that uses autoprefixer as a plugin for the postcss-loader and also uses the babel-loader. This is how it looks like:

module.exports = {
    // ...
    module: {
        rules: [
            {
                loader: 'babel-loader',
                options: {
                    cacheDirectory: true,
                    overrides: [{
                        presets: [
                            ['@babel/preset-env', {
                                browserslistEnv: 'legacy',
                                corejs: 3,
                                useBuiltIns: 'usage',
                            }],
                        ],
                    }],
                    rootMode: 'upward',
                },
                test: /\.(jsx?|tsx?)$/,
                type: 'javascript/auto',
            },
            {
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            esModule: true,
                        },
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            esModule : true,
                            importLoaders: 2,
                        },
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                        plugins: [
                            autoprefixer({ env: 'legacy' }),
                        ],
                    },
                    {
                        loader: 'sass-loader',
                    },
                ],
                test: /\.scss$/,
            },
        ],
    },
    // ...
};

When I run this config, babel-loader transpiles the code as expected, it detects all the targets specified in the legacy environment in the .browserslistrc at the root of the monorepo. However, autoprefixer (v9.8.4) does not seem to be able to detect any browser configuration because I tried console.log(autoprefixer({ env: 'legacy' }).info()) and the output was No browsers selected. I also tried moving the .browserslistrc to packages/app but the result was the same.

Is this a bug? Or am I doing anything wrong?

ai commented 4 years ago

Can you try to run

npx browserslist
npx browserslist --env="legacy"
npm ls | grep autoprefixer
npm ls | grep browserslist
bensampaio commented 4 years ago
and_chr 81
and_ff 68
and_qq 10.4
and_uc 12.12
android 81
baidu 7.12
chrome 83
chrome 81
edge 83
edge 81
firefox 77
firefox 76
ie 11
ios_saf 13.4-13.5
ios_saf 13.3
kaios 2.5
op_mini all
op_mob 46
opera 68
opera 67
safari 13.1
safari 13
samsung 11.1-11.2
samsung 10.1
ai commented 4 years ago

Can you show the full output of npm ls | grep autoprefixer? I assume that you can have multiple versions of Autoprefixer.

bensampaio commented 4 years ago

There is really just one, this is the output I get:

│ ├─┬ autoprefixer@9.8.4

I do get multiple for browserslist:

│ │ ├── browserslist@4.12.2 deduped
│ │ │ ├── browserslist@4.12.2 deduped
│ │ ├── browserslist@4.12.2 deduped
│ ├─┬ browserslist@4.12.2
│ │ ├── browserslist@4.12.2 deduped
├── @my/browserslist-config@0.1.0
│ │ ├── browserslist@4.12.2 deduped
ai commented 4 years ago

OK. Can you find this file in your node_modules https://github.com/postcss/autoprefixer/blob/21becd444a2fe65648ec994c204884ace4c0dc82/lib/browsers.js#L55

and add this debug code:

    opts.path = this.options.from
    opts.env = this.options.env
+  console.log(opts)
+  console.log((new Error('stack')).stack)
    return browserslist(requirements, opts)
bensampaio commented 4 years ago

The first console.log looks like this:

{
  ignoreUnknownVersions: undefined,
  stats: undefined,
  path: '/Users/me/Repositories/project/packages/app',
  env: undefined
}
Error: stack
    at Browsers.parse (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:65:18)
    at new Browsers (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:46:26)
    at loadPrefixes (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:97:20)
    at Function.info (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:129:17)
    at postCssLoader (/Users/me/Repositories/project/packages/webpack/src/helpers/loaderHelper.js:138:38)
    at createWebClientConfig (/Users/me/Repositories/project/packages/webpack/src/helpers/configHelper.js:168:21)
    at Object.<anonymous> (/Users/me/Repositories/project/packages/app/webpack.config.es6.js:7:22)
    at Module._compile (/Users/me/Repositories/project/node_modules/v8-compile-cache/v8-compile-cache.js:194:30)
    at Module._compile (/Users/me/Repositories/project/node_modules/pirates/lib/index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Object.newLoader [as .js] (/Users/me/Repositories/project/node_modules/pirates/lib/index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (/Users/me/Repositories/project/node_modules/v8-compile-cache/v8-compile-cache.js:161:20)
    at Object.<anonymous> (/Users/me/Repositories/project/packages/app/webpack.config.js:6:18)
    at Module._compile (/Users/me/Repositories/project/node_modules/v8-compile-cache/v8-compile-cache.js:194:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (/Users/me/Repositories/project/node_modules/v8-compile-cache/v8-compile-cache.js:161:20)
    at WEBPACK_OPTIONS (/Users/me/Repositories/project/node_modules/webpack-cli/bin/utils/convert-argv.js:114:13)
    at requireConfig (/Users/me/Repositories/project/node_modules/webpack-cli/bin/utils/convert-argv.js:116:6)
    at /Users/me/Repositories/project/node_modules/webpack-cli/bin/utils/convert-argv.js:123:17
    at Array.forEach (<anonymous>)
    at module.exports (/Users/me/Repositories/project/node_modules/webpack-cli/bin/utils/convert-argv.js:121:15)
    at /Users/me/Repositories/project/node_modules/webpack-cli/bin/cli.js:71:45
    at Object.parse (/Users/me/Repositories/project/node_modules/yargs/yargs.js:576:18)
    at /Users/me/Repositories/project/node_modules/webpack-cli/bin/cli.js:49:8

From this point onwards all console.log seem to look like this one:

{
  ignoreUnknownVersions: undefined,
  stats: undefined,
  path: '/Users/me/Repositories/project/packages/media/src/components/Image/Image.scss',
  env: 'legacy'
}
Error: stack
    at Browsers.parse (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:65:18)
    at new Browsers (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:46:26)
    at loadPrefixes (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:97:20)
    at plugin (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:108:20)
    at LazyResult.run (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:352:14)
    at LazyResult.asyncTick (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:280:26)
    at /Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:317:12
    at new Promise (<anonymous>)
    at LazyResult.async (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:314:23)
    at LazyResult.then (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:201:17)
    at /Users/me/Repositories/project/node_modules/postcss-loader/src/index.js:142:8

The complete list is quite long. Do you want it all or is this enough?

ai commented 4 years ago

Why do you have a different console.log outputs? Maybe you have a two postcss-loader in your webpack config?

Check out the stacktrace of the first console.log.

ai commented 4 years ago

I am closing this issue, since opts.env works in Autoprefixer. The problem is how and who call autoprefixer().

bensampaio commented 4 years ago

Why do you have a different console.log outputs? Maybe you have a two postcss-loader in your webpack config?

The first console.log was apparently due to calling autoprefixer().info(). When I remove that call I get only the other stacktrace. I am sure I have only one occurrence of postcss-loader in my config.

I am closing this issue, since opts.env works in Autoprefixer. The problem is how and who call autoprefixer().

Do you mean this is a problem of postcss-loader?

ai commented 4 years ago

Show the full webpack config.

bensampaio commented 4 years ago

I am not allowed to share the full webpack config. But I can share the contents of module.rules:

{
  "module": {
    "rules": [
      {
        "loader": "babel-loader",
        "options": {
          "cacheDirectory": true,
          "overrides": [
            {
              "presets": [
                [
                  "@babel/preset-env",
                  {
                    "corejs": 3,
                    "browserslistEnv": "legacy",
                    "useBuiltIns": "usage"
                  }
                ]
              ]
            }
          ],
          "rootMode": "upward"
        },
        "test": /\.ext/,
        "type": "javascript/auto"
      },
      {
        "loader": "file-loader",
        "options": {
          "emitFile": true,
          "name": "some/path"
        },
        "test": /\.ext/,
      },
      {
        "test": /\.ext/,
        "use": [
          {
            "loader": "file-loader",
            "options": {
              "emitFile": true,
              "name": "some/path"
            }
          },
          {
            "loader": "img-loader",
            "options": {
              "plugins": [
                svgo({
                    plugins: [
                        { removeDesc: true },
                    ],
                }),
              ]
            }
          }
        ]
      },
      {
        "loader": SvgStorePlugin.loader,
        "options": {
          "name": "assets/img/sprite.[contenthash].svg"
        },
        "test": /\.ext/
      },
      {
        "test": /\.ext/,
        "use": [
          {
            "loader": MiniCssExtractPlugin.loader,
            "options": {
              "esModule": true
            }
          },
          {
            "loader": "css-loader",
            "options": {
              "esModule": true,
              "importLoaders": 2,
              "modules": {
                "localIdentName": "value"
              },
              "onlyLocals": false,
              "sourceMap": false
            }
          },
          {
            "loader": "postcss-loader",
            "options": {
              "plugins": [
                autoprefixer({
                  env: 'legacy',
                }),
              ],
              "sourceMap": false
            }
          },
          {
            "loader": "sass-loader",
            "options": {
              "sourceMap": false
            }
          }
        ]
      }
    ],
  },
  // plugins, optimization, output and more ...
}

When I add the debug code you mentioned in https://github.com/postcss/autoprefixer/issues/1337#issuecomment-660223428 and run this config I get the following output:

{
  ignoreUnknownVersions: undefined,
  stats: undefined,
  path: '/Users/me/Repositories/project/packages/media/src/components/Image/Image.scss',
  env: 'legacy'
}
Error: stack
    at Browsers.parse (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:65:18)
    at new Browsers (/Users/me/Repositories/project/node_modules/autoprefixer/lib/browsers.js:46:26)
    at loadPrefixes (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:97:20)
    at plugin (/Users/me/Repositories/project/node_modules/autoprefixer/lib/autoprefixer.js:108:20)
    at LazyResult.run (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:352:14)
    at LazyResult.asyncTick (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:280:26)
    at /Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:317:12
    at new Promise (<anonymous>)
    at LazyResult.async (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:314:23)
    at LazyResult.then (/Users/me/Repositories/project/node_modules/postcss/lib/lazy-result.es6:201:17)
    at /Users/me/Repositories/project/node_modules/postcss-loader/src/index.js:142:8

Does this help?

ai commented 4 years ago

Can you try to make this 2 changes:

node_modules/autoprefixer/lib/autoprefixer.js:

-  let brwlstOpts = {
-    ignoreUnknownVersions: options.ignoreUnknownVersions,
-    stats: options.stats
-  }
+  let brwlstOpts = {
+    ignoreUnknownVersions: options.ignoreUnknownVersions,
+    stats: options.stats,
+    env: options.env
+  }

node_modules/autoprefixer/lib/browsers.js:

    opts.path = this.options.from;
-   opts.env = this.options.env;
    return browserslist(requirements, opts);

Will it help?

bensampaio commented 4 years ago

Yes, that works! Then autoprefixer detects my configuration:

Browsers:
  Chrome for Android: 81
  Firefox for Android: 68
  And_qq: 10.4
  UC for Android: 12.12
  Android: 81
  Baidu: 7.12
  Chrome: 83, 81
  Edge: 83, 81
  Firefox: 77, 76
  IE: 11
  iOS: 13.4-13.5, 13.3
  Kaios: 2.5
  Opera Mini: all
  Opera Mobile: 46
  Opera: 68, 67
  Safari: 13.1, 13
  Samsung: 11.1-11.2, 10.1
ai commented 4 years ago

The fix was released in 9.8.6

You can help us by retweeting about our Open Collective: https://twitter.com/PostCSS/status/1288937473276444672

bensampaio commented 4 years ago

Awesome! Thank you for looking into it so fast!