Published npm package does not apply styles

Viewed 3400

I'm currently working on creating an npm package. Which is basically a React component with added styles using SCSS. When I test it out, the class names are there, but no styles are being applied.

Here is the repo for the package. I use a separated webpack config for building the specific folder where the component is.

Here's the webpack configuration I'm using:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const EsLintFormatter = require('eslint-formatter-pretty');
const path = require('path');

const pkg = require('../../package.json');
const { SRC_PATH, BUILD_PATH } = require('./constants');
const setStyleLoaders = require('./style-loaders');
const alias = require('./alias');

const packageName = pkg.name;

module.exports = ({ NODE_ENV }) => ({
  mode: 'production',
  entry: `${SRC_PATH}/components/Carousel/Carousel.js`,
  output: {
    path: BUILD_PATH,
    filename: 'index.js',
    library: packageName,
    libraryTarget: 'commonjs2',
    umdNamedDefine: true,
    publicPath: '/build/',
  },
  node: {
    net: 'empty',
    tls: 'empty',
    dns: 'empty',
  },
  resolve: {
    alias: {
      ...alias,
      react: path.resolve(__dirname, './node_modules/react'),
      'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
    },
  },
  externals: {
    react: 'react',
    reactDom: 'react-dom',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: [
          { loader: 'babel-loader' },
          {
            loader: 'eslint-loader',
            options: {
              formatter: EsLintFormatter,
            },
          },
        ],
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: setStyleLoaders(NODE_ENV),
      },
      {
        test: /\.(png|pje?g|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'images',
            },
          },
        ],
      },
      {
        test: /\.(woff|woff2|tff|otf|eot)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'fonts',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({ filename: 'index.css' }),
  ],
});

...and here's my package.json

{
  "name": "react-clear-carousel",
  "version": "0.1.0-beta.1",
  "description": "A test",
  "main": "build/index.js",
  "scripts": {
    "start": "cross-env NODE_ENV=development webpack-dev-server --env.NODE_ENV=development --config config/webpack/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --env.NODE_ENV=production --config config/webpack/webpack.config.publish.js",
    "stylelint": "stylelint 'src/**/*.scss' --config stylelint.config.js; exit 0",
    "eslint": "eslint 'src/**/*.js'; exit 0",
    "es:fix": "eslint 'src/**/*.js' --fix",
    "style:fix": "stylelint 'src/**/*.scss' --fix",
    "lint": "npm run eslint && npm run stylelint",
    "publish:beta": "npm publish --tag=beta",
    "test": "jest"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/RobCC/web-playground.git"
  },
  "author": "robcc",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/RobCC/web-playground/issues"
  },
  "files": [
    "dist"
  ],
  "jest": {
    "setupFilesAfterEnv": [
      "<rootDir>/config/jest/setup.js"
    ],
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/jest/fileMock.js",
      "\\.(css|less|scss)$": "identity-obj-proxy",
      "^~/(.*)": "<rootDir>/$1",
      "^#/(.*)": "<rootDir>/src/$1"
    }
  },
  "homepage": "https://github.com/RobCC/web-playground#readme",
  "peerDependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "prop-types": "^15.7.2"
  },
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "^7.9.0",
    "@babel/plugin-proposal-class-properties": "^7.8.3",
    "@babel/plugin-proposal-export-default-from": "^7.8.3",
    "@babel/plugin-proposal-export-namespace-from": "^7.8.3",
    "@babel/preset-env": "^7.9.0",
    "@babel/preset-react": "^7.9.1",
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.2",
    "@types/react": "^16.9.25",
    "@types/react-dom": "^16.9.5",
    "@welldone-software/why-did-you-render": "^4.0.5",
    "autoprefixer": "^9.7.4",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.1.0",
    "chalk": "^3.0.0",
    "clean-webpack-plugin": "^3.0.0",
    "core-js": "^3.6.4",
    "cross-env": "^7.0.2",
    "css-loader": "^3.4.2",
    "cssnano": "^4.1.10",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb": "^18.1.0",
    "eslint-formatter-pretty": "^3.0.1",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-react": "^7.19.0",
    "eslint-plugin-react-hooks": "^2.5.1",
    "file-loader": "^6.0.0",
    "html-webpack-plugin": "^3.2.0",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^25.1.0",
    "log-symbols": "^3.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "postcss-loader": "^3.0.0",
    "pr*op-types": "^15.7.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "regenerator-runtime": "^0.13.5",
    "sass": "^1.26.3",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.1.3",
    "stylelint": "^13.2.1",
    "stylelint-config-recommended": "^3.0.0",
    "stylelint-formatter-pretty": "^2.0.0",
    "stylelint-scss": "^3.16.0",
    "stylelint-webpack-plugin": "^1.2.3",
    "ts-loader": "^6.2.1",
    "typescript": "^3.8.3",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  },
  "dependencies": {
    "weak-key": "^1.0.2"
  }
}

This is the result when testing the published package:

Classnames applied

Edit 1:

There are no errors on the Network and Console tab in devtools. I also can't find the file loaded, even though it's there in the package. It seems like the js file is not using it, but it should.

Edit 2:

Thanks for pointing me on the right direction!

I added import 'react-clear-carousel/build/index.css'; to include the CSS file from my package. I can see the file now (on devtools), but the styles are not being applied since css-loader is modularizing it and adding additional suffix and prefix (even though it already had them), thus having different class names that the ones my component has.

eg. My component is rendered as <div class="carousel_swimlane--kXSjh">, but the styles in the DOM are named as index_carousel_swimlane--kXSjh--2C.

I guess the question is now, how do I tell Webpack to pass this CSS as is? And if there's a way for me to deliver the CSS file without other people having to change their Webpack configuration.

Class names have double suffixes

1 Answers

Looking at your repo I see that you are importing your scss but attributing it's properties to classNames.

className should be the name of the class, and you can either attribute your imported styles to style or you can load your compiled css into the DOM using <link rel="stylesheet" type="text/css" href="styles.min.css">

The reason you're not seeing a stylesheet in the network tab is because you've simply forgotten to declare a stylesheet.

Related