Skip to content

Instantly share code, notes, and snippets.

@Twipped
Last active July 22, 2019 15:22
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Twipped/7fe68263c1a653821b7d3f61d74365bd to your computer and use it in GitHub Desktop.
Save Twipped/7fe68263c1a653821b7d3f61d74365bd to your computer and use it in GitHub Desktop.
CSS Modules without webpack or browserify
var gulp = require('gulp');
var gutil = require('gulp-util');
var through = require('through2');
var sourcemaps = require('gulp-sourcemaps');
var postcss = require('gulp-postcss');
var filter = require('gulp-filter');
var concat = require('gulp-concat');
var modules = require('postcss-modules');
gulp.task('build:css:modules', function () {
// postcss-modules exports the JSON data via a callback, since postcss is
// a one to one input/output operation. We have to save this output so
// that it can be injected back into the gulp stream.
// We push these onto an array so that if something fires out of sequence
// the files wont get lost.
var pending = [];
function getJSONFromCssModules (cssFileName, json) {
pending.push({
path: cssFileName + '.json',
contents: new Buffer(JSON.stringify(json, null, 2))
});
}
// our modules are located in component folders inside shared
// ex: source/shared/components/header/styles.css
return gulp.src('source/shared/**/*.css')
// setup sourcemap processing
.pipe(sourcemaps.init())
// This is the meat of the css module processing.
// We pass in our callback from above to capture json output
.pipe(postcss([
modules({ getJSON: getJSONFromCssModules }),
]))
// Write out the sourcemap info to the css file.
.pipe(sourcemaps.write())
// As files come out of the postcss gulp workflow, the pending
// array contains the json file. Here we use through2 to inject
// those files into the gulp stream with the same path details.
.pipe(through.obj(function (file, enc, next) {
var push = this.push.bind(this);
// pushing out a clone so that the object doesn't get changed
// by later pipeline steps
push(file.clone());
pending.forEach(function (item) {
push(new gutil.File({
cwd: file.cwd,
base: file.base,
path: item.path,
contents: item.contents
}));
});
pending = [];
next();
}))
// save out the compiled css and the json file. If the css is styles.css
// then the json will be styles.css.json. Because of how node require()
// resolves, this will let you require('./styles.css') from your component
// and receive the json file.
.pipe(gulp.dest('build/shared'))
// filter out everything except the css and concat it into a single
// modules file that will be hosted publicly.
.pipe(filter('**/*.css'))
.pipe(concat('modules.css'))
.pipe(gulp.dest('public/build'));
});
@levity
Copy link

levity commented Mar 23, 2017

This is pretty interesting! I'm curious if you're using this in production or have written about this approach anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment