Skip to content

postcss-loader dependency does not support ESM #613

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
GamzeeRakoon opened this issue Nov 29, 2022 · 8 comments · Fixed by #614
Closed

postcss-loader dependency does not support ESM #613

GamzeeRakoon opened this issue Nov 29, 2022 · 8 comments · Fixed by #614

Comments

@GamzeeRakoon
Copy link

GamzeeRakoon commented Nov 29, 2022

Bug report

while compiling css with postcss-loader it uses the dependency cosmiconfig but this does not support ESM type
and will give the error

Error [ERR_REQUIRE_ESM]: require() of ES Module ~\_frontend\postcss.config.js from ~\_frontend\node_modules\postcss-loader\node_modules\cosmiconfig\dist\loaders.js not supported.

Actual Behavior

when postcss loader uses cosmiconfig it uses non esm compatible code and gives an error and fails to compile the css

Expected Behavior

postcss loader should compile the css while being ESM compatible

How Do We Reproduce?

heres my testing repository:
https://github.com/LithRakoon/npm
npm i
npm run build
see error

Please paste the results of npx webpack info here, and mention other relevant information

  System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
    Memory: 5.70 GB / 15.89 GB
  Binaries:
    Node: 18.12.1 - C:\Program Files\nodejs\node.EXE
    npm: 9.1.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22621.819.0), Chromium (107.0.1418.56)
    Internet Explorer: 11.0.22621.1
  Packages:
    babel-loader: ^8.1.0 => 8.3.0
    css-loader: ^6.7.2 => 6.7.2
    postcss-loader: ^7.0.1 => 7.0.1
    sass-loader: ^13.2.0 => 13.2.0
    style-loader: ^0.23.1 => 0.23.1
    webpack: ^5.75.0 => 5.75.0
    webpack-cli: ^5.0.0 => 5.0.0
    webpack-dev-server: ^3.10.3 => 3.11.3
@GamzeeRakoon
Copy link
Author

forgot i made my repo private, its public now sorry for the inconvience

@alexander-akait
Copy link
Member

You can't use:

import autoprefixer from 'autoprefixer',
        import cssnano from 'cssnano' ({
            reduceIdents:  {keyframes: false},
            discardUnused: {keyframes: false}
        })

it is invalid syntax

@GamzeeRakoon
Copy link
Author

GamzeeRakoon commented Nov 29, 2022

while this is true using

import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
		
export default {
    plugins: [
		cssnano,
		autoprefixer
    ]
};

still gives the same error of a postcss-loader dependency not supporting ESM

@alexander-akait
Copy link
Member

Please use:

import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';

@GamzeeRakoon
Copy link
Author

still gives the error that a dependencie of postcss loader doesnt support esm and fails

@GamzeeRakoon GamzeeRakoon changed the title postcss-loader dependencie does not support ESM postcss-loader dependency does not support ESM Nov 29, 2022
@karolyi
Copy link

karolyi commented Nov 29, 2022

Same issue here.

@karolyi
Copy link

karolyi commented Nov 29, 2022

Related: cosmiconfig/cosmiconfig#224

@alexander-akait
Copy link
Member

alexander-akait commented Nov 29, 2022

Okay, let's fix it on our side, firstly, please fix your configuration:

import path from 'path';
import url from 'url';
import webpack from 'webpack';
import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';

const extractSASS = new MiniCssExtractPlugin.default({filename: "app.min.css"});
const jQuery = new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery"
});

const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
    mode: "production",
    entry: {
        main: [
            "./src/js/index.js"
        ],
    },
    output: {
        filename: "app.min.js",
        path:     path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test:    /\.js$/,
                exclude: /node_modules/,
                use: {
					loader: "babel-loader"
				}
            },
            {
				test: /\.scss$/,
				use:  [
                    {
                        loader: MiniCssExtractPlugin.default.loader
                    },
                    {
                        loader: "css-loader"
                    },
                    {
                        loader:  "postcss-loader",
                        options: {
                            postcssOptions: {
                                path: path.resolve(__dirname, "postcss.config.js")
                            }
                        }
                    },
                    {
                        loader: "sass-loader"
                    }
                ]
            }
        ]
    },
        plugins: [
            extractSASS,
            jQuery
        ]
};

the second please fix your postcss.config.js

import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';

export default {
    plugins: [
        autoprefixer(),
        cssnano({
            reduceIdents:  {keyframes: false},
            discardUnused: {keyframes: false}
        })
    ]
};

and then we will aply this patch on our code:

const moduleName = "postcss";
  const explorer = (0, _cosmiconfig.cosmiconfig)(moduleName, {
    searchPlaces: [
      'package.json',
      `.${moduleName}rc`,
      `.${moduleName}rc.json`,
      `.${moduleName}rc.yaml`,
      `.${moduleName}rc.yml`,
      `.${moduleName}rc.js`,
      `.${moduleName}rc.mjs`,
      `.${moduleName}rc.cjs`,
      `.config/${moduleName}rc`,
      `.config/${moduleName}rc.json`,
      `.config/${moduleName}rc.yaml`,
      `.config/${moduleName}rc.yml`,
      `.config/${moduleName}rc.js`,
      `.config/${moduleName}rc.mjs`,
      `.config/${moduleName}rc.cjs`,
      `${moduleName}.config.js`,
      `${moduleName}.config.mjs`,
      `${moduleName}.config.cjs`,
    ],
    loaders: {
      '.js': async (...args) => {
        let result;

        try {
          result = _cosmiconfig.defaultLoaders['.js'](...args);
        } catch (error) {
          let importESM;

          try {
            // eslint-disable-next-line no-new-func
            importESM = new Function("id", "return import(id);");
          } catch (e) {
            importESM = null;
          }

          if (
              error.code === "ERR_REQUIRE_ESM" &&
              require("url").pathToFileURL &&
              importESM
          ) {
            const urlForConfig = require("url").pathToFileURL(args[0]);

            result = await importESM(urlForConfig);
          } else {
            throw requireError;
          }

        }

        return result;
      },
      '.mjs': async (...args) => {
        let importESM;

        try {
          // eslint-disable-next-line no-new-func
          importESM = new Function("id", "return import(id);");
        } catch (e) {
          importESM = null;
        }

        if (
            require("url").pathToFileURL &&
            importESM
        ) {
          const urlForConfig = require("url").pathToFileURL(args[0]);

          result = await importESM(urlForConfig);
        }

        return result;
      }
    }
  });

And now ESM configuration will work

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 a pull request may close this issue.

3 participants