Skip to content

Commit 9986850

Browse files
committed
Plugin for reduce-css to handle postcss
* Use `postcss-simple-import` to add cache in watch mode. We need watch each file before it is compiled, cause it may fail in compilation and the imported file never emitted to watchify. * Default postcss plugins: autoprefixer, postcss-advanced-variables, postcss-custom-url, postcss-extend, postcss-mixins, postcss-nested, postcss-simple-import. * Use `postcss-processor-splicer` to support custom postcss plugins.
1 parent 688805d commit 9986850

File tree

31 files changed

+472
-70
lines changed

31 files changed

+472
-70
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/node_modules/
22
.DS_Store
33
npm-debug.log
4-
/build/
4+
build/
55
/coverage/

example/gulpfile.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
var gulp = require('gulp')
2+
var del = require('del')
3+
var reduce = require('reduce-css')
4+
var postcss = require('..')
5+
var path = require('path')
6+
var fixtures = path.resolve.bind(path)
7+
8+
gulp.task('clean', function () {
9+
return del('build')
10+
})
11+
12+
gulp.task('single-bundle', ['clean'], function () {
13+
return reduce
14+
.on('error', console.log.bind(console))
15+
.on('log', console.log.bind(console))
16+
.on('instance', function (b) {
17+
b.plugin(postcss)
18+
})
19+
.src('*.css', {
20+
basedir: fixtures('src'),
21+
factor: 'common.css',
22+
})
23+
.pipe(reduce.dest('build', null, {
24+
maxSize: 0,
25+
assetOutFolder: fixtures('build', 'images'),
26+
}))
27+
})
28+
29+
gulp.task('watch-single-bundle', ['clean'], function () {
30+
reduce.watch()
31+
.on('error', console.log.bind(console))
32+
.on('log', console.log.bind(console))
33+
.on('instance', function (b) {
34+
b.plugin(postcss)
35+
})
36+
.src('*.css', {
37+
basedir: fixtures('src'),
38+
factor: 'common.css',
39+
})
40+
.pipe(reduce.dest, 'build', null, {
41+
maxSize: 0,
42+
assetOutFolder: fixtures('build', 'images'),
43+
})
44+
})
45+
46+
gulp.task('multiple-bundles', ['clean'], function () {
47+
return reduce
48+
.on('error', console.log.bind(console))
49+
.on('log', console.log.bind(console))
50+
.on('instance', function (b) {
51+
b.plugin(postcss)
52+
})
53+
.src('*.css', {
54+
basedir: fixtures('src'),
55+
factor: {
56+
needFactor: true,
57+
common: 'common.css',
58+
},
59+
})
60+
.pipe(reduce.dest('build', null, {
61+
maxSize: 0,
62+
useHash: true,
63+
assetOutFolder: fixtures('build', 'images'),
64+
}))
65+
})
66+
67+
gulp.task('watch-multiple-bundles', ['clean'], function () {
68+
reduce.watch()
69+
.on('error', console.log.bind(console))
70+
.on('log', console.log.bind(console))
71+
.on('instance', function (b) {
72+
b.plugin(postcss)
73+
})
74+
.src('*.css', {
75+
basedir: fixtures('src'),
76+
factor: {
77+
needFactor: true,
78+
common: 'common.css',
79+
},
80+
})
81+
.pipe(reduce.dest, 'build', null, {
82+
maxSize: 0,
83+
useHash: true,
84+
assetOutFolder: fixtures('build', 'images'),
85+
})
86+
})
87+

example/src/a.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@deps "./reset";
2+
@deps "./button";
3+
@import "color";
4+
a{
5+
color: $blue;
6+
}
7+

example/src/b.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@deps "./reset";
2+
@deps "./button";
3+
@import "color";
4+
.button {
5+
background-color: $blue;
6+
}
7+

example/src/button/button.png

9.9 KB
Loading

example/src/button/index.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "color";
2+
.button {
3+
background-color: $red;
4+
background-image: url(button.png);
5+
}

example/src/node_modules/color/index.css

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/src/reset.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
html, body {
2+
margin: 10;
3+
padding: 0;
4+
}
5+

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ gulp.task('lint', function () {
2525
.pipe(eslint.failAfterError())
2626
})
2727

28-
gulp.task('test', ['lint'], test)
28+
gulp.task('test', test)
2929
gulp.task('coverage',
3030
require('callback-sequence')(instrument, test, report)
3131
)

index.js

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,73 @@
11
var Pipeline = require('postcss-processor-splicer')
22
var CacheHandler = require('deps-cache')
3-
var postcss = require('postcss')
4-
var mix = require('util-mix')
5-
6-
var PROCESSORS = [
7-
require('postcss-simple-import'),
8-
require('postcss-custom-url'),
9-
require('postcss-advanced-variables'),
10-
require('postcss-mixins'), // should come before postcss-nested
11-
require('postcss-nested'),
12-
require('postcss-extend'),
13-
require('autoprefixer'),
14-
]
3+
var path = require('path')
154

165
module.exports = function (b, opts) {
176
opts = opts || {}
187

19-
var pipeline = Pipeline(PROCESSORS)
8+
var pipeline = new Pipeline([
9+
require('postcss-simple-import'),
10+
require('postcss-custom-url'),
11+
require('postcss-advanced-variables'),
12+
require('postcss-mixins'), // should come before postcss-nested
13+
require('postcss-nested'),
14+
require('postcss-extend'),
15+
require('autoprefixer'),
16+
])
2017

2118
if (typeof opts.processorFilter === 'function') {
2219
opts.processorFilter(pipeline)
2320
} else if (Array.isArray(opts.processorFilter)) {
2421
pipeline.push.apply(pipeline, opts.processorFilter)
2522
}
2623

27-
var i = pipeline.indexOf('postcss-simple-import')
28-
if (i !== -1) {
29-
pipeline.splice(i, 1,
30-
rebuildAtImport(b, pipeline.get(i))
31-
)
24+
var atImport = pipeline.get('postcss-simple-import')
25+
26+
var atImportOpts = atImport[1] || {}
27+
atImport[1] = atImportOpts
28+
29+
var cache = atImportOpts.cache || {}
30+
atImportOpts.cache = cache
31+
32+
var cacheHandler = new CacheHandler(cache)
33+
34+
var importer = atImportOpts.importer
35+
atImportOpts.importer = function (id, from, state) {
36+
return state.resolve(id, { basedir: path.dirname(from) })
37+
.then(function (dep) {
38+
cacheHandler.add(from, dep)
39+
// watchify reports file rather than `dep`,
40+
// so emit dep and make watchify report it
41+
b.emit('file', dep)
42+
// watch dep
43+
state.postcssOpts.entry.emit('file', dep)
44+
if (importer) {
45+
return importer(id, from, state)
46+
}
47+
})
3248
}
3349

34-
var postcssProcessor = postcss(pipeline.build())
50+
// watchify emit `update` whenever file changes detected
51+
b.on('update', function (files) {
52+
cacheHandler.invalidate(files)
53+
})
54+
pipeline.splice('postcss-simple-import', 1, atImport)
55+
56+
var processor = pipeline.build()
3557
b.processor(function (result) {
36-
// b.emit('file', result.from)
3758
var postcssOpts = {
3859
from: result.from,
3960
to: result.from,
4061
entry: result, // for atImport
4162
}
42-
return postcssProcessor
43-
.process(result.css, postcssOpts)
63+
return processor.process(result.css, postcssOpts)
4464
.then(function (res) {
4565
result.css = res.css
66+
}, function (err) {
67+
cacheHandler.invalidate(Object.keys(cache))
68+
throw err
4669
})
4770
})
4871

4972
}
5073

51-
function rebuildAtImport(b, atImport) {
52-
var opts
53-
if (Array.isArray(atImport)) {
54-
opts = atImport[1]
55-
atImport = atImport[0]
56-
}
57-
opts = mix({ cache: {} }, opts)
58-
59-
var onImport = opts.onImport
60-
opts.onImport = function (from, imports, postcssOpts) {
61-
cacheHandler.add(from, imports)
62-
63-
var result = postcssOpts.entry
64-
imports.forEach(function (dep) {
65-
// watchify reports file rather than `dep`,
66-
// so emit dep and make watchify report it
67-
b.emit('file', dep)
68-
// watch dep
69-
result.emit('file', dep)
70-
})
71-
72-
if (onImport) {
73-
onImport(from, imports, postcssOpts)
74-
}
75-
}
76-
77-
var cacheHandler = new CacheHandler(opts.cache)
78-
// watchify emit `update` whenever file changes detected
79-
b.on('update', function (files) {
80-
cacheHandler.invalidate(files)
81-
})
82-
83-
return [atImport, opts]
84-
}
85-

0 commit comments

Comments
 (0)