remove jss prefix from production build

345 Views Asked by At

I am using react version 17 and we use webpack to bundle our deps.

import React from "react";
import { Chip } from "@material-ui/core";
import {
  createGenerateClassName,
  createStyles,
  makeStyles,
  StylesProvider,
  Theme,
} from "@material-ui/core/styles";
// eslint-disable-next-line import/no-extraneous-dependencies
import { create } from "jss";
import shortid from "shortid";

const generateClassName = createGenerateClassName({
  productionPrefix: "my-prod-",
  seed: shortid.generate(),
});

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    whiteText: {
      color: "white",
      backgroundColor: "rgb(24, 190, 148)",
    },
    redText: {
      color: "white",
      backgroundColor: "rgb(233, 109, 118)",
    },
    grayText: {
      color: "gray",
      backgroundColor: "rgb(238,228,228)",
    },
  })
);

const Synced = "Synced";
const OutOfSync = "OutOfSync";
const Unknown = "Unknown";

const SyncStatusChip = ({ status }) => {
  const classes = useStyles();

  return (
    <StylesProvider generateClassName={generateClassName}>
      {status === Synced && <Chip size="small" label={status} className={classes.whiteText} />}
      {status === OutOfSync && <Chip size="small" label={status} className={classes.redText} />}
      {status === Unknown && <Chip size="small" label={status} className={classes.grayText} />}
    </StylesProvider>
  );
};

export default SyncStatusChip;

I read a lot of documentation and answers regarding the modification of class names. In our production builds whenever we use make styles we see that it adds a class that start with jss. Problem is that these names sometimes collide with other random generated class names and it creates a lot of UI issues.

even trying my own generate method to generate class names, i still see this stupid class names that start with jss. Sometimes, i wish i wasn't doing frontend. :/

enter image description here

4

There are 4 best solutions below

2
harsh bangari On

You can update the babel-plugin-jss configuration to use the useCSS option.

// babel.config.js
module.exports = {
  plugins: [
    [
      "babel-plugin-jss",
      {
        useCSS: true,
      },
    ],
  ],
};
2
Hithesh kumar On

You need to modify your webpack configuration. uses the MiniCssExtractPlugin to extract CSS into separate files. It also uses the postcss-loader to apply the postcss-preset-env plugin, which includes autoprefixer to add vendor prefixes to your CSS.

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      autoprefixer: {
                        flexbox: 'no-2009',
                      },
                      stage: 3,
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
    }),
  ],
};
0
Ronak Bokaria On

Custom Class Names

It requires

babel-plugin-styled-components

and the custom babel configuration.

After styled-components is installed, babel-plugin-styled-components and babel-plugin-macros come with it in package-lock.json

There are a few options to set the custom babel configuration:

Eject the Create React App

  • Use react-app-rewired
  • Use craco (Create React App Configuration Override)

Here, we eject the Create React App by executing npm run eject. The ejected package.json has the following babel configuration:

"babel": {
  "presets": [
    "react-app"
  ]
}

namespace A namespace will ensure that the generated class names be unique. This is a handy way to avoid name collisions among applications.

Let’s try this babel configuration in package.json:

"babel": {
  "presets": [
    "react-app"
  ],
  "plugins": [
    [
      "babel-plugin-styled-components", 
      {
        "namespace": "my-styled-components-project",
        "displayName": false,
        "fileName": false
      }
    ]
  ]
}

displayName displayName is the component name. This makes it easier to find styled components in the application.

"babel": {
  "presets": [
    "react-app"
  ],
  "plugins": [
    [
      "babel-plugin-styled-components", 
      {
        "namespace": "my-styled-components-project",
        "displayName": true,
        "fileName": false
      }
    ]
  ]
}
0
Hithesh kumar On

generateClassName function returns a class name with a custom prefix based on the sheet options and the rule key. You can customize this function to generate class names that fit your needs.

Note: StylesProvider component to wrap your application. This component is responsible for generating unique class names for your styles.

// webpack.config.js

const { StylesProvider } = require('@material-ui/core/styles');

module.exports = {
  // ...
  plugins: [
    // ...
    new StylesProvider({
      generateClassName: (rule, sheet) => {
        // Customize the class name prefix
        return `${sheet.options.classNamePrefix}-${rule.key}`;
      },
    }),
  ],
};

const { StylesProvider } = require('@material-ui/core/styles');

const options = {
  classNamePrefix: 'my-app',
};

const stylesProvider = new StylesProvider({
  generateClassName: (rule, sheet) => {
    const { classNamePrefix } = sheet.options;
    const { key } = rule;

    return `${classNamePrefix}-${key}`;
  },
});

const sheet = stylesProvider.createStyleSheet({
  root: {
    backgroundColor: 'red',
  },
});

const classes = sheet.classes;

console.log(classes.root); // Output: "my-app-root"