Search code examples
lessrollupjspostcss

How to configure Rollup and PostCSS to bundle LESS and CSS (Tailwind)


I am putting together a started kit to bundle a React component library with Rollup. The library includes Antd which uses LESS, and Tailwind.

I have an issue in my rollup.config.ts file:

[!] Error: Unexpected character '@' (Note that you need plugins to import files that 
are not JavaScript)
src\tailwind.css (1:0)
@import 'tailwindcss/base';
^

I don't know how to configure the 'rollup-plugin-postcss'. I see a few options:

  • use the plugin only once, that handles both LESS and CSS at the same time.
  • use the plugin twice, once for LESS files only, another for CSS files only.

In either case, I always get an error msg, because I am not able to tell the plugin to only run on css or less extensions, despite specifying them in the extensions option.

Here is my rollup config:

import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
import postcss from 'rollup-plugin-postcss'
import copy from 'rollup-plugin-copy'

const packageJson = require('./package.json')

export default {
    input: 'src/index.ts',
    output: [
        {
            file: packageJson.main,
            format: 'cjs',
            sourcemap: true
        },
        {
            file: packageJson.module,
            format: 'esm',
            sourcemap: true
        }
    ],
    plugins: [
        peerDepsExternal(),
        resolve(),
        commonjs(),
        typescript({ useTsconfigDeclarationDir: true }),
        postcss({
            config: {
                path: './postcss.config.js'
            },
            use: {               
                less: { javascriptEnabled: true }
            },
            extensions: ['.less'], // Looks like this still processes CSS despite this line.
            extract: false         
        }),
        postcss({
            config: {
                path: './postcss.config.js'
            },
            extensions: ['.css'],
            extract: false
        })        
    ]
}

src/index.ts:

import './tailwind.css'
export * from './test-component'

src/tailwind.css:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

postcss.config.js

const isProduction = process.env.NODE_ENV === 'production';

module.exports = {
    plugins: [
        require('postcss-import'),
        require('tailwindcss')('./tailwind.config.js'),
        require('autoprefixer'),
        require('postcss-preset-env')({
            browsers: ['last 2 versions', '> 5%'],
        }),
        require('cssnano'),
    ],
};


Solution

  • You have to use the postcss plugin before the commonjs one, or it will try to interpret the contents of CSS files as JavaScript. Maybe it also needs to come before the resolve one but not sure about that.

    After making those changes you probably won't need to do anything for .less files since rollup-plugin-postcss already handles them.

    Edit: after looking at the repository, you didn't need to use the postcss plugin before the other ones, just omit the postcss extensions option or set it correctly (was missing a dot in front of css):

     plugins: [
            peerDepsExternal(),
            postcss({
                minimize: true,
                modules: true,
                use: {
                    sass: null,
                    stylus: null,
                    less: { javascriptEnabled: true }
                }, 
                extract: true
            }),
            resolve(),
            commonjs(),
            typescript({
                useTsconfigDeclarationDir: true
            }),
        ]
    

    Nevertheless, to be extra safe I recommend using the plugins that handle non JS files before the ones that do it.