rollup/rollup-plugin-node-resolve

Handle CSS files

IvanSanchez opened this issue · 4 comments

Some NPM packages specify CSS files in them, e.g.: https://github.com/Leaflet/Leaflet/blob/master/package.json#L23 and https://github.com/twbs/bootstrap/blob/master/package.json#L20

It would be desirable that rollup-plugin-npm would load these files by means of rollup-plugin-postcss.

I'm not sure I understand how this would work? If you did...

import 'leaflet';

...then Rollup wouldn't be able to know that you wanted to import leaflet/dist/leaflet.css – it would assume you wanted the JavaScript. Whereas if it was a CSS import...

@import 'leaflet';

...then surely it's the responsibility of a PostCSS plugin to locate the file and include it, rather than rollup-plugin-npm?

Off the top of my head, this should work, if rollup-plugin-postcss is present:

import 'leaflet/dist/leaflet.css';

Or have I misunderstood?

Or have I misunderstood?

No, no. You have a good point and I didn't explain myself very well.

The use case here is bundling libraries. e.g. I want to bundle up leaflet, bootstrap, jquery and turfjs - and I don't want to care about the name of the entry point for the javascript (main or jsnext:main or whatever), and I don't want to care about the entry point for the CSS, or for whatever else is needed to make the code work in a single bundle.

So right now, when one writes in javascript

import 'leaflet'

...then it is my understanding that rollup-plugin-npm reads the package.json file and somehow translates that into...

import 'node_modules/leaflet/dist/leaflet.js'

...and what I would like instead is detect rollup-plugin-postcss (or make an option to enable it) so it would do this instead:

import 'node_modules/leaflet/dist/leaflet.js'
import 'node_modules/leaflet/dist/leaflet.css'

And then, with some postcss-js magic, bundle the CSS inside the JS.


I can currently achieve this via a crazy set of gobblejs transforms, but it feels way too clunky. Somehow I think that rollup-plugin-npm is the right place to bundle up the JS and CSS of a node module, and not handle the CSS files of node modules in a separate stage.

Ah, interesting. Here's a sketch for an approach that seems like it could work:

  • Plugins like rollup-plugin-postcss include a meta property, like meta: { css: true }
  • rollup-plugin-npm includes an option hook that scans each item in options.plugins to see if any has a meta.css property
  • If there is such a plugin, rollup-plugin-npm looks for a pkg.style at the same time as it's looking for main or jsnext:main. If it finds one, instead of resolving to the main file, it resolves to a virtual module ID
  • rollup-plugin-npm adds a load hook that, given a virtual module ID like __npm:leaflet returns a module importing both leaflet/dist/leaflet-src.js and leaflet/dist/leaflet.css
  • From there, whatever CSS-aware plugin exists (doesn't have to be PostCSS, as long as it exposes meta.css) takes over

That seems doable. It should probably be hidden behind an option though.

The tricky part is what to do about relative paths, such as images – does PostCSS have some magic for ensuring these are correct? Or maybe inlining as data URIs?

Sounds sane and doable. Me like!

The tricky part is what to do about relative paths, such as images – does PostCSS have some magic for ensuring these are correct? Or maybe inlining as data URIs?

Apparently there is https://github.com/assetsjs/postcss-assets for just that.

Given the amount of hacks for images and CSS paths (see this if you dare), I'd expect developers to be able to pop the images in the correct directories. IMHO, some use cases call for lazy loading of images whose URLs are defined in the CSS, other use cases call for preloading everything.

Maybe there could be more properties in a package.json file pointing to image and/or font files, and copy them around, but that's gobblejs territory, not rollup territory.