egoist / rollup-plugin-postcss

Seamless integration between Rollup and PostCSS.
MIT License
674 stars 213 forks source link

Extract CSS separately for every file of the array of rollup entry points #160

Open toli444 opened 5 years ago

toli444 commented 5 years ago

Summary

When an array of entry points is provided to Rollup, it turns every entry point to separate output chunks. It would be great if there was a possibility to have the same for CSS files with this plugin. As for now the plugin just generates one CSS file which contains all the styles. Extracting CSS into a single file makes tree-shaking no to work, in case I want to ship only critical styles in the bundle.

Current behaviour

Bundle structure:

.
└───components
│   └─── Input
│       │   index.js
│   └─── Button
│       │   index.js
└───folder2
│   index.js
│   chunk.js
│   styles.css

Proposed behaviour

Bundle structure:

.
└───components
│   └─── Input
│       │   index.js
│       │   styles.css
│   └─── Button
│       │   index.js
│       │   styles.css
└───folder2
│   index.js
│   chunk.js
│   styles.css

To reproduce

This is the rollup config that I have to reproduce the issue with this plugin:

rollupConfig = {
    input: ['./src/components/Button/index.js', './src/components/Input/index.js'],
    output: [
        {
            dir: lib,
            format: 'cjs',
            sourcemap: true,
            exports: 'named'
        },
    ],
    plugins: [
        postcss({
                modules: true,
                extract: true,
                sourceMap: true,
                minimize: true
            })
    ]
}
tianyingchun commented 5 years ago

has any progress for this feature ?

krvajal commented 5 years ago

This is what I am doing


const entryPoints = {
  entry1: 'src/entry1.js',
  entry2: 'src/entry2.js',
}

// this needs to be a different instance every time
function getPlugins(){
    return [postcss()]
}

const configs = Object.keys(entryPoints).reduce((configs, entry) => {
  const input = entryPoints[entry]

  const config = {
    input,
    output: {
      file: `build/${entry}.js`,
      format: 'esm',
      name: entry,
      globals,
    },
    plugins: getPlugins(),
    external,
  }
  configs.push(config)
  return configs
}, [])

module.exports = configs;
mlnor27 commented 4 years ago

@krvajal This is a bad workaround as it repeats the bundle process for each entry + produces code duplication...

Is there anything planned for this matter anytime soon ? @egoist

whatisaphone commented 4 years ago

This is particularly important if you're bundling multiple apps that each contain their own styles for html, body, etc.

frattaro commented 4 years ago

Here's a use case:

You have a large react-rollup component library that is consumed by a create-react-app application. They only need one component, and also need to run postcss on that component's css to ensure it's properly scoped. The component library already ships each component as a separate entry point, but can't get the per-component css extracted, and are unable to support postcss in the consuming application.

SasanFarrokh commented 3 years ago

Could we do not extract css for our component library, but extract them in our final build website?, i mean somehow mark the css injection codes for later extraction?

wedneyyuri commented 3 years ago

Same problem here, I would like to break in small chunks to expose a components package which will be imported later using NextJS.

hnrchrdl commented 3 years ago

I also have this requirement. I would like my app to be able to import the library css separately for every component.

kamaladenalhomsi commented 3 years ago

well so far this is my workaround:

prerequisites:

yarn add -D glob or npm install --dev glob
// rollup.config.js

const glob = require('glob')
const path = require('path')
const postcss = require('rollup-plugin-postcss')

const bundleCss = () => {
  var config = []
  var files = glob.sync(path.resolve(__dirname, '**/*.css'))
  files.forEach(file => {
    var filename = file.substr(file.lastIndexOf('/') + 1, file.length).toLowerCase()
    config.push(
      postcss({
        include: file,
        extract: path.resolve(`dist/${filename}`),
        minimize: true
      })
    )
  })
  return config
}

modules.exports = {
  plugins: [
    ...bundleCss()
  ]
}

basically I am looping over all css files in my project, and returning an array of postcss plugin for each file

3lang3 commented 2 years ago

has any progress for this feature ?

laizp commented 2 years ago

I have this requirement to.

Brandonitas commented 1 year ago

has any progress for this feature?

iyinchao commented 1 year ago

+1, this would be very handy

DanielAmenou commented 1 year ago

I created a plugin - rollup-plugin-lib-style that generates CSS separately for every file and imports these generated files, so the consumer of the package will not need to import each CSS file separately. You can give it a try

gde-pass commented 1 year ago

Anything new about that ?

uditalias commented 1 year ago

has any progress for this feature?

tianyingchun commented 1 year ago

i pareparing create simular plugin to generates css modular support less, sass, postcss for rollup multi entries bundle at one time.

tianyingchun commented 1 year ago

@uditalias try @flatjs/forge-plugin-styling https://www.npmjs.com/package/@flatjs/forge-plugin-styling

image image image image image image image image
tianyingchun commented 1 year ago

BTW: rollup entries:

 'src/module1/module1.ts',
          'src/module2/module2.ts',
          'src/module0/index.ts',
          'src/module-no-style/index.ts',
cherylcarpenter commented 1 year ago

Hoping we can keep this issue open. My use case is that I am using rollup for a React Component Library. I want each js module to have it's own css sidecar.

joemaller commented 10 months ago

I'm looking to migrate a project out of webpack which should output one css file for each entry point. Output files are used in separate contexts, and styles should apply to each individually.

Here's a simplified example of what should happen:

// main.js
import "main.scss";

// main.scss
body { color: red }

// admin.js
import "admin.scss"

// admin.scss
body { color: blue }

Output should look the same as above, except the scss files would be compiled and output as css.

Instead, I get two js files and a single css file, with a filename based on the first entrypoint in rollup.config:

// main.css
body { color: blue } 
body { color: red }

(concatenation order appears to be bottom-up, but I'm not certain about that)

SunHuawei commented 10 months ago

Hoping we can keep this issue open. My use case is that I am using rollup for a React Component Library. I want each js module to have it's own css sidecar.

Cannot agree more! My case is when using preserveModules: true, I expect it can keep the CSS references for each module(file) so that only the necessary CSS can be included in the final bundle when the end user builds with webpack.

cristian-eriomenco commented 2 months ago

Agree same problem. To add more, when using css modules with extract: true, ALL of your <component>.module.css gets aggregated in a dist/index.css. Now imagine importing only a Button component, the end result is unnecessary css being loaded, which doesn't quite align with tree-shaking/code-splitting concepts very well.

At the same time if you do extract: false then your resulting css is bundled as <component>.module.css.js alongside your <component>.js but this time you get degraded user experience caused by flickering, especially if this component is not/cannot be SSRed.

In summary at the moment its a choice between a large and heavy index.css or a split inlined css as js with degraded user experiece due to flickering / page shifts etc