Semantic-UI-CSS icon indicating copy to clipboard operation
Semantic-UI-CSS copied to clipboard

Having issue using CSS modules in Semantic ui css react typescript

Open johnfrades opened this issue 8 years ago • 3 comments

Hi, im trying to enable CSS modules in react, i am encountering this error

ERROR in ./node_modules/css-loader?{"modules":true,"importLoaders":1,"localIdentName":"[name]__[local]___[hash:base64:5]"}!./node_modules/semantic-ui-css/semantic.min.css
Module not found: Error: Can't resolve 'themes/default/assets/fonts/icons.woff2' in 'D:\REACT PROJECTS\TS\fromscratch\node_modules\semantic-ui-css'
 @ ./node_modules/css-loader?{"modules":true,"importLoaders":1,"localIdentName":"[name]__[local]___[hash:base64:5]"}!./node_modules/semantic-ui-css/semantic.min.css 6:264315-264365
 @ ./node_modules/semantic-ui-css/semantic.min.css
 @ ./src/index.tsx
 @ multi (webpack)-dev-server/client?http://localhost:3000 index.tsx

ERROR in ./node_modules/css-loader?{"modules":true,"importLoaders":1,"localIdentName":"[name]__[local]___[hash:base64:5]"}!./node_modules/semantic-ui-css/semantic.min.css
Module not found: Error: Can't resolve 'themes/default/assets/images/flags.png' in 'D:\REACT PROJECTS\TS\fromscratch\node_modules\semantic-ui-css'
 @ ./node_modules/css-loader?{"modules":true,"importLoaders":1,"localIdentName":"[name]__[local]___[hash:base64:5]"}!./node_modules/semantic-ui-css/semantic.min.css 6:202659-202708
 @ ./node_modules/semantic-ui-css/semantic.min.css
 @ ./src/index.tsx
 @ multi (webpack)-dev-server/client?http://localhost:3000 index.tsx

This is my webpack config

const webpack = require('webpack')
const path = require('path')

module.exports = {
  // put sourcemaps inline
  devtool: 'eval',

  // entry point of our application, within the `src` directory (which we add to resolve.modules below):
  entry: [
    'index.tsx'
  ],

  // configure the output directory and publicPath for the devServer
  output: {
    filename: 'app.js',
    publicPath: 'dist',
    path: path.resolve('dist')
  },

  // configure the dev server to run 
  devServer: {
    port: 3000,
    historyApiFallback: true,
    inline: true,
  },

  // tell Webpack to load TypeScript files
  resolve: {
    // Look for modules in .ts(x) files first, then .js
    extensions: ['.ts', '.tsx', '.js'],

    // add 'src' to the modules, so that when you import files you can do so with 'src' as the relative route
    modules: ['src', 'node_modules']
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: 'babel-loader'
          },
          {
            loader: 'ts-loader'
          }
        ]
      },
      {
        test: /\.css$/,
        include: /node_modules/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 1,
              localIdentName: "[name]__[local]___[hash:base64:5]"
            }
          }
        ]
      },
      {
        test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 100000,
          },
        },
      },
    ]
  }
}

johnfrades avatar Nov 21 '17 08:11 johnfrades

So currently i'm getting around this by allowing global imports in the webpack config:

rules: [{
    test: /\.css$/,
    oneOf: [{
        resourceQuery: /^\?global$/,
        use: [
            require.resolve('style-loader'),
            require.resolve('css-loader')
        ]
    }, {
        use: [
            require.resolve('style-loader'),
            {
                loader: require.resolve('css-loader'),
                options: {
                    importLoaders: 1,
                    modules: true,
                    localIdentName: '[name]__[local]___[hash:base64:5]'
                }
            },
            require('./postcss-loader')
        ]
    }]
}]

which then allows me to import global CSS files and do

import 'semantic-ui-css/semantic.min.css?global';

That gives me the styling from semantic without this error you specified.

However, now Semantic-UI is overriding ALL of my styles. I'm trying to find a way to limit Semantic's styles to the component I want it to be in, but if anyone finds a way before me then please let me know...

I'd love for there to be a fix that doesn't involve me needing to allow global CSS in the first place. Maybe something similar to what React Transition Group does which allows you to pass in a classNames={{}} prop to define css. I'm not sure if that makes sense in this context though.

dnorth avatar Mar 05 '18 01:03 dnorth

@dnorth did you ever have any luck trying to limit Semantic's styles to just a single component?

tomherren avatar Jun 20 '18 17:06 tomherren

I've been struggling with this for a while. I managed to get css modules and semantic ui css (or any external library css) working together in the end.

First add an alias for themes/default/assets

	resolve: {
	  extensions: ['.js', '.css'],
	  alias: {
	    'themes/default/assets': path.resolve(__dirname, '../node_modules/semantic-ui-css/themes/default/assets')
	  }
	}

Because you're using css modules, webpack is looking for the relative url in the semantic ui css as a module and can't find it.

Now the issue will be that all the semantic ui class names in your bundled css will be reformatted to [name]__[local]___[hash:base64:5]

I used the getLocalIdent function to use the normal class name if it's coming from the semantic ui css otherwise use the internal css-loader function with your localIdentName pattern.

const getLocalIdent = require('css-loader/lib/getLocalIdent');

{
  loader: 'css-loader',
  options: {
    modules: true,
    localIdentName: '[path][name]__[local]--[hash:base64:5]',
    getLocalIdent: (loaderContext, localIdentName, localName, options) => {
      return loaderContext.resourcePath.includes('semantic-ui-css') ?
        localName :
        getLocalIdent(loaderContext, localIdentName, localName, options);
    }
  }
}

nevace avatar Aug 10 '18 11:08 nevace