LoginSignup
3
3

More than 5 years have passed since last update.

css-modulesifyでPostCSSプラグインを使う

Last updated at Posted at 2016-03-11

結論

綺麗かどうかはさておき、以下のようにやると一応css-modulesifyでPostCSSのプラグインが問題なく使えました(ES2015, React環境)。来たストリームを加工してるだけの話ですが。

var fs         = require('fs');
var through2   = require('through2');
var browserify = require('browserify');
var postcss    = require('postcss');

var b = browserify('src/index.js');
b.transform("babelify", {presets: ["es2015", "react"]});

var cssProcessors = [
    require('postcss-nested'),
    require('cssnano')
];

b.plugin(require('css-modulesify'), {
  rootDir: __dirname
});

b.on('css stream', function (css) {
  var postcssStream = through2(
    function transform(chunk, enc, next){
      postcss(cssProcessors)
        .process(chunk)
        .then(function (result) {
            next(null, result.css);
        });
    }
  );

  css
    .pipe(postcssStream)
    .pipe(fs.createWriteStream('dist/modules.min.css'));
});

var bundle = b.bundle();
bundle.pipe(fs.createWriteStream('dist/bundle.js'));

gulpなら以下。

gulpfile.js
var gulp       = require('gulp');
var postcss    = require('gulp-postcss');
var streamify  = require('gulp-streamify');
var browserify = require('browserify');
var source     = require('vinyl-source-stream');

var cssProcessors = [
  require('postcss-nested'),
  require('cssnano')
];


gulp.task('build', function(){

  var browserified = function () {
    var b = browserify('src/index.js');
    b.transform("babelify", {presets: ["es2015", "react"]});
    b.plugin(require('css-modulesify'), {
      rootDir: __dirname
    });
    b.on('css stream', function (css) {
      css
        .pipe(source('modules.min.css'))
        .pipe(streamify(postcss(cssProcessors)))
        .pipe(gulp.dest('dist/'));
    });
    return b.bundle();
  };

  browserified()
    .on("error", function (err) { console.log("Error : " + err.message); })
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('dist/'));
});

そもそもの問題

CSS ModulesをBrowserifyで使うcss-modulesifyで、CSSを良い感じにminifyするプラグインcssnanoが使えませんでした。

css-modulesifyは、使いたいPostCSSプラグインを以下のようにuseオプションで設定できます。

var b = require('browserify')();
var fs = require('fs');

b.add('./main.js');
b.plugin(require('css-modulesify'), {
  rootDir: __dirname,
  use: [
    require('postcss-nested'),
    require('cssnano')
  ]
});

var bundle = b.bundle();
bundle.on('css stream', function (css) {
  css.pipe(fs.createWriteStream('mycss.css'));
});

ただこれだとデフォルトで使われているCSS Modules用のプラグイン(postcss-modules-local-by-default, postcss-modules-extract-imports, postcss-modules-scope, postcss-modules-values)を上書きしてしまいます。

なので、useではなくpostcssAfter afterを使うと、デフォルトのプラグインが走ったあとに指定したプラグインを実行させることができるよ的なことが書いてありました。

...

b.plugin(require('css-modulesify'), {
  rootDir: __dirname,
  after: [
    require('postcss-nested'),
    require('cssnano')
  ]
});

...

ですが、言われた通りにやっても、プラグインにcssnanoを使っていると書き出されるファイルが空のCSSになっていた(エラーが出て処理が止まっていた?)、というのが問題でした(cssnextも使えないっていうissueがたってました)。

なので冒頭のように、css-modulesify内ではプラグインは使わず、css-modulesifyから流れてきたCSSのストリームにPostCSSプラグインを当ててあげることで問題を回避しました。

そもそも、

Please note that this is still highly experimental.

って言われてるので問題は起こって当然なのと、これはあくまで回避策なので、状況が正確に把握でき次第issueに報告して改善に貢献しようかと思います(はやくhighly experimentalじゃなくなって欲しい...)。

※修正(2016-03-16):0.22.0の変更にあわせた

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3