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

Default camelCasing enabled by namedExport in css-loader is throwing error with typings #42

Open
bahtou opened this issue Oct 28, 2020 · 4 comments

Comments

@bahtou
Copy link

bahtou commented Oct 28, 2020

I implemented the style-loader and css-loader combo as seen in this example: https://github.com/webpack-contrib/style-loader#modules

// styles.css
.foo-baz {
  color: red;
}
.bar {
  color: blue;
}

// index.js
import { fooBaz, bar } from './styles.css';
console.log(fooBaz, bar);

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {
              esModule: true,
              modules: {
                namedExport: true,
              },
            },
          },
          {
            loader: 'css-loader',
            options: {
              esModule: true,
              modules: {
                namedExport: true,
                //exportLocalsConvention: 'camelCaseOnly'  -- default when namedExport is true
              },
            },
          },
        ],
      },
    ],
  },
};

By default, using the namedExport in css-loader automatically sets the exportLocalsConvention: 'camelCaseOnly’. Note the css class foo-baz in the styles.css file and how it is imported in the index.js file (.foo-baz, fooBaz)

Applying typings-for-css-modules-loader to the webpack configuration:

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {
              esModule: true,
              modules: {
                namedExport: true,
              },
            },
          },
          {loader: '@teamsupercell/typings-for-css-modules-loader'},
          {
            loader: 'css-loader',
            options: {
              esModule: true,
              modules: {
                namedExport: true,
                //exportLocalsConvention: 'camelCaseOnly'  -- default when namedExport is true
              },
            },
          },
        ],
      },
    ],
  },
};

The following error shows up

ERROR in [at-loader] ./index.tsx:5:10
    TS2305: Module '"./styles.css"' has no exported member 'fooBaz'.

What is the configuration missing to enable typings-for-css-modules-loader to work with the default camelCasing? Is this something the generated *.d.ts* files need to adjust for?

@bahtou
Copy link
Author

bahtou commented Oct 28, 2020

from https://github.com/TeamSupercell/typings-for-css-modules-loader/blob/master/src/index.js#L59

// let's only check `exports.locals` for keys to avoid getting keys from the sourcemap when it's enabled  
// if we cannot find locals, then the module only contains global styles

is this a correct assumption?

@kirvedx
Copy link

kirvedx commented Dec 9, 2020

That's interesting. For me, using:

// ..
{
    compileType: "module",
    namedExport: true
}
// ..

Generated an error that I must set exportLocalsConvention: "camelCaseOnly" - and the compile process wouldn't finish.

Anyways, I'm currently seeking a fix for issues with camelCase exports that aren't stripping special characters from css class names (i.e. '+'). Otherwise, my configuration is working with all the latest deps (just pasting my whole webpack.config.babel.js):

module.exports =
{
    entry: {   // We specify the entry so we can use a custom entry point
                  // Otherwise index.js is expected (anywhere in folder stucture)
        app: "./src/app.tsx"
    },
    output: {
        //filename: "bundle.js",
        path: path.resolve(__dirname, 'dist'),
    }, // Enable sourcemaps for debugging webpack's output:
    devtool: "source-map",
    resolve: { // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: ['.ts', '.tsx', '.js', '.jsx', ".css", ".scss", '.json']
    },
    module: {
        rules: [  // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader':
            {
                test: /.tsx?$/,
                use: [
                    {
                        loader: "awesome-typescript-loader"
                    }
                ]
            }, // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader':
            {
                enforce: "pre",
                test: /.js$/,
                use: [
                    {
                        loader: "source-map-loader"
                    }
                ]
            }, // ES6/7 JavaScript will be handled by babel-loader
            {
                test: /.js$/,
                //exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader"
                    }
                ]
            },
            {   // HTML Template
                test: /.html$/,
                use: [{ loader: "html-loader", options: { minimize: false } }]
            },
            {   // Image Optimization
                test: /.(gif|png|jpe?g|svg)$/i,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            exclude: /.(svg)$/i,
                            name: "./images/[name]_[hash:7].[ext]",
                            limit: 10000
                        }
                    },
                    {
                        loader: 'img-loader'
                    }
                ]
            },
            {   // SCSS Compilation
                test: /\.(scss|css)$/,
                //include: [
                //    path.resolve(__dirname, "src/scss")
                //],
                use: [
                    {
                        loader: "style-loader"
                    },
                    {
                        // We'll use a drop-in replacement for css-loader which supports importing
                        // SCSS within a typescript file
                        //loader: "css-loader"
                        //loader: "typings-for-css-modules-loader", <-- no longer maintained as of 2017??
                        loader: "@teamsupercell/typings-for-css-modules-loader",
                        options: {
                            // Options are now passed directly to "css-loader"
                        }
                    },
                    {
                        loader: "css-loader",
                        options: {  // options signature for style-loader, css-loader, and sass-loader have changed:
                            modules: {
                                compileType: "module",  // Instead of modules: true
                                namedExport: true,    // Requires exportLocalsConvention: "camelCaseOnly" instead of "camelCase"
                                exportLocalsConvention: "camelCaseOnly",
                                //mode: "local",
                                //auto: true,
                                //exportGlobals: true,
                                //exportOnlyLocals: false
                            }
                        }
                    },
                    {
                        loader: "sass-loader",
                        options: {
                            sassOptions: {  // includePaths is now embedded under sassOptions
                                includePaths: ["node_modules"]
                            }
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebPackPlugin(
            {
                favicon: "src/assets/favicon.ico",
                template: "src/index.html",
                filename: "./index.html"
            }
        ),
        new MiniCssExtractPlugin(
            {
                filename: "[name].css",
                chunkFilename: "[id].css"
            }
        )
    ],

    // When importing a module whose path matches one of the following, just assume a corresponding global
    // variable exists and use that instead. This is important as it allows us to avoid bundling all of our
    // dependencies, which subsequently allows browsers to cache those libraries between builds:
    //externals:
    //{
    //    "react": "React",
    //    "react-dom": "ReactDOM"
    //}
};

@bahtou
Copy link
Author

bahtou commented Dec 12, 2020

Here is my current webpack config for CSS:

{
  test: /\.(css|scss)$/,
  include: cssPaths,
  use: [
    {
      loader: 'style-loader',
      options: {
        esModule: true,
        modules: {
          namedExport: true
        }
      }
    },
    '@teamsupercell/typings-for-css-modules-loader',
    // 'css-modules-typescript-loader',
    {
      loader: 'css-loader',
      options: {
        url: false,
        esModule: true,
        import: false,
        modules: {
          compileType: 'module',
          mode: 'local',
          exportGlobals: true,
          localIdentName: '[local]',
          // localIdentContext
          // localIdentHashPrefix: undefined,
          // localIdentRegExp: undefined,
          // getLocalIdent: undefined,
          namedExport: true,
          exportLocalsConvention: 'camelCaseOnly',
          exportOnlyLocals: false
        },
        sourceMap: true,
        importLoaders: 1
      }
    },
    { loader: 'postcss-loader' }
  ]
}

versions:

"postcss": "^8.2.1",
"webpack": "^5.10.1",

(FWIW) I forked the project and adding some code to work with my setup.

bahtou@398a1e5#diff-3274f1a37032fb0ae4e2823def0007c634e869ae0dfc304ff6a12c36513c3a52R26

@guerc
Copy link

guerc commented Nov 15, 2021

I could work around the issue by explicitly setting exportLocalsConvention to camelCase. This will create members in both their original notation as well as in a camel-cased version. I could not find any other way and I can live with the "redundant" members in original notation for now.

Here's the part of my configuration:

{
  test: /\.css$/,
  exclude: /node_modules/,
  use: [
    'style-loader',
    '@teamsupercell/typings-for-css-modules-loader',
    {
      loader: 'css-loader',
      options: {
        modules: {
          exportLocalsConvention: 'camelCase',
          localIdentName: '[local]--[hash:base64:5]',
          mode: 'local',
        },
      },
    },
  ],
},

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

No branches or pull requests

3 participants