6

I'm putting together a repo that will be available on npm. The repo consists of multiple modules, similar to react-leaflet and react-d3. Application developers will include modules from within the npm package via require/import, e.g.:

import { ModuleOne, ModuleTwo } from 'myNpmPackage`;

I need to package CSS along with each of these modules, and that CSS will be compiled from Sass files within each module.

Given a folder structure for myNpmPackage like:

├── src
│   ├── ModuleOne
│   │   ├── index.js
│   │   ├── style.scss
│   ├── ModuleTwo
│   │   ├── index.js
│   │   ├── style.scss
├── package.json

What is a good publish flow to make those .scss files (compiled into .css) available to consumers of myNpmPackage, without requiring that consumers explicitly include / @import / link rel="stylesheet" the CSS?

I'm using gulp and browserify and would prefer to stick with that pipeline.


UPDATE: I've found parcelify does some of what I need. I add the following to myNpmPackage/package.json:

"style": "src/**/*.scss",
"transforms": [
  "sass-css-stream"
]

and add parcelify to dependencies, so that it's installed along with myNpmPackage.

Consumers of myNpmPackage must then add the following to their gulpfile:

parcelify(b, {
    bundles: {
        style: './build/modules.css'
    }
});

parcelify will use the "style" glob in myNpmPackage/package.json to round up all the .scss files in myNpmPackage's modules and bundle them into ./build/modules.css.

This is getting there, but not ideal for two reasons:

  1. The CSS files from each module are all included in the consumer application build, even if not all the modules are included;
  2. This strategy requires the consumer application developer to add code to their gulpfile instead of "just working".
ericsoco
  • 24,913
  • 29
  • 97
  • 127
  • I know you want to stick with browserify but [webpack](http://webpack.github.io/) is actually perfect for your use case – Julien Cabanès Sep 30 '15 at 14:37
  • @JulienCabanès would you mind elaborating? Maybe you're more familiar with webpack than I and can share an example of how I'd do this with webpack. – ericsoco Sep 30 '15 at 16:33

2 Answers2

2

Here is a Webpack setup that does exactly what you need:

  • only imported modules CSS are included in the build (ModuleThree is not for instance).
  • no need to update some gulpfile.js or *.config.js, each module require its own stylesheet(s) like any other dependency.

Bonus: ModuleTwo shows how to lazy load CSS and also contains a background image which will be included like any dependency as well.

Note: I didn't use ES2015 syntax but you could if you wish with babel-loader.

  • Thanks @Julien, this is great. I'm going to hold on accepting this answer since I'd rather not switch from browserify to webpack just yet...but I might change my mind soon :) – ericsoco Oct 01 '15 at 18:32
  • I realize I may be being a purist, but I'm not a fan of inlining the CSS into the HTML. Does webpack offer an option to compile required CSS/Sass files to a .css file instead of inlining? – ericsoco Oct 01 '15 at 18:39
  • 1
    Yes it does, with [this plugin](https://github.com/webpack/extract-text-webpack-plugin). I've [updated](https://github.com/JulienCabanes/Webpack-Module-Example/commit/71e599e4d4bfe246035a8dbcfa2899e73137d063#diff-11e9f7f953edc64ba14b0cc350ae7b9d) my config and now I have a single [build stylesheet](https://github.com/JulienCabanes/Webpack-Module-Example/blob/master/dist/styles.css) (except lazy load) that I have to [include manually](https://github.com/JulienCabanes/Webpack-Module-Example/blob/master/index.html#L3) with a classic `link` tag. – Julien Cabanès Oct 01 '15 at 19:09
1

It depends partly on your own development pipeline. You could render out all your SCSS into CSS upon building your app. So assuming you have a single CSS file with all styles rendered out, you can include this into a JavaScript file using various methods within the gulp ecosystem for example this plugin.

function addStyleString(str) {
    var node = document.createElement('style');
    node.innerHTML = str;
    document.body.appendChild(node);
}

addStyleString('/* CSS File 1 */');

And in your gulp pipeline:

var gfi = require("gulp-file-insert");

gulp.src('./sample.js')
  .pipe(gfi({
    "/* CSS File 1 */": "path/to/main.css"
  }))
  .pipe(gulp.dest('./dist/'));

Reference: Inject CSS stylesheet as string using Javascript

Community
  • 1
  • 1
Alex
  • 4,844
  • 7
  • 44
  • 58
  • Not sure I feel great about the whole CSS-inlined-into-JS thing, a la Radium. But thanks for the suggestion. – ericsoco Oct 01 '15 at 18:42