8

I'm using Next.JS with a few other modules. One of them, Megadraft, comes with its own CSS. I don't know if this is relevant, but I also use PurgeCSS.

Everything works fine on development mode, but the CSS seems to break in production mode. To be a little more explicit, all of the classes of Megadraft, seem to have no definition in production mode. The HTML nodes in the inspector still show that the classes are here, but they have just no definition.

Here's how I import the said CSS files in my pages/_app.js file:

// pages/_app.js
import "css/tailwind.css";
import "megadraft/dist/css/megadraft.css";

And this is my postcss.config.js:

// postcss.config.js
const purgecss = [
    "@fullhuman/postcss-purgecss",
    {
        content: [
            "./components/**/*.js",
            "./Layout/**/*.js",
            "./pages/**/*.js",
            "./node_modules/next/dist/pages/**/*.js",
            "./node_modules/next/dist/Layout/**/*.js",
            "./node_modules/next/dist/components/**/*.js"
        ],
        defaultExtractor: (content) => content.match(/[A-Za-z0-9-_:/]+/g) || [],
    },
];
module.exports = {
    plugins: [
        "postcss-import",
        "tailwindcss",
        "autoprefixer",
        ...(process.env.NODE_ENV === "production" ? [purgecss] : []),
    ],
};

I'm using next ^9.4.4. It may be worth noticing that TailwindCSS seems to work just fine (both in dev and prod), but I think it may be because it is used as a plugin in postcss...

Just in case also, I integrated webpack to my project to solve an error I had where the code was telling that I needed a loader:

// next.config.js
module.exports = {
    cssModules: true,
    webpack: (config, options) => {
        config.node = {
            fs: "empty",
        };
        config.module.rules.push({
            test: /\.(png|woff|woff2|eot|ttf|svg)$/,
            use: [
                options.defaultLoaders.babel,
                {
                    loader: "url-loader?limit=100000",
                },
                {
                    loader: "file-loader",
                },
            ],
        });
        return config;
    },
};

Anyway, if someone has an idea of why this works in development mode and not in production, it could be of great help.

Thanh-Quy Nguyen
  • 2,995
  • 7
  • 30
  • 46
  • I am using `tailwindcss ^1.4.6` and its built-in purgeCSS and the `megadraft`'s styles stay in production. You may have a look at my settings in this [Sandbox](https://codesandbox.io/s/blissful-sinoussi-wjoyf?fontsize=14&hidenavigation=1&module=%2Ftailwind.config.js&theme=dark). Download to your local machine, `npm i` and `npm build` to test. If this doesn't help, try adding `./node_modules/megadraft/lib/**/*.js` to the `content` array in your settings, as suggested [here](https://github.com/ky-is/vue-cli-plugin-tailwind#3rd-party-css). – hangindev.com Jun 16 '20 at 15:56
  • Hi, thanks for your answer! I get the following error with your Sandbox: ``` ./styles.css 1:0 Module parse failed: Unexpected character '@' (1:0) You may need an appropriate loader to handle this file type. > @tailwind base; | @tailwind components; | @tailwind utilities;``` – Thanh-Quy Nguyen Jun 16 '20 at 22:12
  • I did try to replace postcss-import + autoprefixer in my code by `postcss-preset-env` like you did though, and it still does not work... With or without my `purgecss` array, with or without `./node_modules/megadraft/lib/**/*.js` in `content`. I really don't know what may be wrong. I added my `next.config.js` to my original post, since it uses webpack and solves the bug your Sandbox shows me and may be the cause of my CSS failing not to be purged. – Thanh-Quy Nguyen Jun 16 '20 at 22:27
  • Your stack seems strange. Why would use you use `postcss` and `tailwindcss`, completely different philosophies. If you want to use tailwind, it already is using purgecss: https://tailwindcss.com/docs/controlling-file-size/#setting-up-purgecss-manually. If you're using `postcss`, you shouldn't have any CSS to begin with. – serraosays Jun 16 '20 at 22:40
  • I found that the `yarn.lock` file in the sandbox will cause the error you saw if you were using `yarn`. I removed it you may try to export the sandbox and try again... `next.config.js` is unnecessary for my settings. If that doesn't help, it would be nice if you could share your repo. – hangindev.com Jun 17 '20 at 01:08
  • @serraosays Since the stack is made of both Next and Tailwind, I took a bit of both documentations to configure my postcss. And since I'm calling external packages, the CSS actually come from there... I tried using the extractor from the documentation and removing postcss-import, but it still didn't work. – Thanh-Quy Nguyen Jun 17 '20 at 08:43
  • @Hangindev Still does not work, still with the same error... Did you manage to make it work in incognito mode? – Thanh-Quy Nguyen Jun 17 '20 at 08:43
  • I couldn't get it to work on the CodeSandbox environment but it works on my local environment that's why you have to export the sandbox to zip and download it. – hangindev.com Jun 17 '20 at 09:03
  • One thing that's likely to work with your settings is to add to the content array`"./node_modules/megadraft/dist/**/*.css"` (not `"./node_modules/megadraft/lib/**/*.js"`) – hangindev.com Jun 17 '20 at 09:26

1 Answers1

6

Option 1: use Tailwind CSS built-in PurgeCSS

// tailwind.config.css
module.exports = {
  purge: ["./components/**/*.js", "./pages/**/*.js"],
  theme: {
    extend: {}
  },
  variants: {},
  plugins: []
};

// postcss.config.js
module.exports = {
  plugins: ["tailwindcss", "postcss-preset-env"]
};

Be sure to add postcss-preset-env to the package's dev dependencies with npm i --save-dev postcss-preset-env or yarn add -D postcss-preset-env.

Option 2: Manually setup purge and add "./node_modules/megadraft/dist/**/*.css" to purgecss whitelisting content array:

// tailwind.config.css
module.exports = {
  theme: {
    extend: {}
  },
  variants: {},
  plugins: []
};

// postcss.config.js
const purgecss = ['@fullhuman/postcss-purgecss',{
  content: ["./node_modules/megadraft/dist/**/*.css", "./components/**/*.js", "./pages/**/*.js"],

  defaultExtractor: content => {
    const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []
    const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || []
    return broadMatches.concat(innerMatches)
  }
}]

module.exports = {
  plugins: [
    'tailwindcss',
    'autoprefixer',
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []
  ]
}

There may be better solutions but these two are what I can think of.

hangindev.com
  • 4,573
  • 12
  • 28