Skip to content

Commit f806a5f

Browse files
committed
Use static-module to extract css
1 parent 90f1046 commit f806a5f

File tree

6 files changed

+73
-35
lines changed

6 files changed

+73
-35
lines changed

index.js

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const ConcatStream = require('concat-stream')
2-
const isRequire = require('is-require')()
2+
const staticModule = require('static-module')
33
const through = require('through2')
4-
const falafel = require('falafel')
54
const assert = require('assert')
65
const fs = require('fs')
76

@@ -22,16 +21,28 @@ function cssExtract (bundle, opts) {
2221
addHooks()
2322

2423
function addHooks () {
25-
// run before the "debug" step in browserify pipeline
26-
bundle.pipeline.get('debug').unshift(through.obj(write, flush))
2724
const writeStream = (typeof outFile === 'function')
2825
? outFile()
29-
: ConcatStream(writeOutFile)
26+
: ConcatStream(fs.writeFileSync.bind(fs, outFile))
27+
28+
// run before the "label" step in browserify pipeline
29+
// this makes sure insert-css requires are found before plugins like bundle-collapser run
30+
bundle.pipeline.get('label').unshift(through.obj(write, flush))
3031

3132
function write (chunk, enc, cb) {
32-
const css = extract(chunk)
33-
writeStream.write(css)
34-
cb(null, chunk)
33+
// A small performance boost: don't do ast parsing unless we know it's needed
34+
if (String(chunk.source).indexOf('insert-css') === -1) {
35+
return cb(null, chunk)
36+
}
37+
38+
var sm = createStaticModule(writeStream)
39+
sm.write(chunk.source)
40+
sm.pipe(ConcatStream(function (source) {
41+
// chunk.source is expected to be a string
42+
chunk.source = String(source)
43+
cb(null, chunk)
44+
}))
45+
sm.end()
3546
}
3647

3748
// close stream and signal end
@@ -40,29 +51,10 @@ function cssExtract (bundle, opts) {
4051
cb()
4152
}
4253
}
43-
44-
function writeOutFile (buffer) {
45-
fs.writeFileSync(outFile, buffer)
46-
}
4754
}
4855

49-
// extract css from chunks
50-
// obj -> str
51-
function extract (chunk) {
52-
// Do a performant check before building the ast
53-
if (String(chunk.source).indexOf('insert-css') === -1) return ''
54-
55-
const css = []
56-
const ast = falafel(chunk.source, { ecmaVersion: 6 }, walk)
57-
chunk.source = ast.toString()
58-
return css.join('\n')
59-
60-
function walk (node) {
61-
if (!isRequire(node)) return
62-
if (!node.arguments) return
63-
if (!node.arguments[0]) return
64-
if (node.arguments[0].value !== 'insert-css') return
65-
css.push(node.parent.arguments[0].value)
66-
node.parent.update('0')
67-
}
56+
function createStaticModule (writeStream) {
57+
return staticModule({
58+
'insert-css': writeStream.write.bind(writeStream)
59+
})
6860
}

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
"license": "MIT",
2222
"dependencies": {
2323
"concat-stream": "^1.5.1",
24-
"falafel": "^1.2.0",
25-
"is-require": "0.0.1",
24+
"static-module": "^1.3.0",
2625
"through2": "^2.0.1"
2726
},
2827
"devDependencies": {

test/expected-static.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.foo {background: green}

test/index.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test('css-extract', function (t) {
1414
t.throws(cssExtract.bind(null, {}), 123, /object/)
1515
})
1616

17-
t.test('should extract css', function (t) {
17+
t.test('should extract sheetify css to given stream', function (t) {
1818
t.plan(2)
1919
browserify(path.join(__dirname, 'source.js'))
2020
.transform('sheetify/transform')
@@ -31,7 +31,7 @@ test('css-extract', function (t) {
3131
}
3232
})
3333

34-
t.test('should write file', function (t) {
34+
t.test('should extract sheetify css to file', function (t) {
3535
t.plan(3)
3636
tmpDir({unsafeCleanup: true}, onDir)
3737

@@ -54,4 +54,42 @@ test('css-extract', function (t) {
5454
})
5555
}
5656
})
57+
58+
t.test('should extract static insert-css statements', function (t) {
59+
t.plan(2)
60+
browserify(path.join(__dirname, 'source-static.js'))
61+
.plugin(cssExtract, { out: createWs })
62+
.bundle()
63+
64+
function createWs () {
65+
return bl(function (err, data) {
66+
t.ifError(err, 'no error')
67+
const exPath = path.join(__dirname, './expected-static.css')
68+
const expected = fs.readFileSync(exPath, 'utf8').trim()
69+
t.equal(String(data), expected, 'extracted all the CSS')
70+
})
71+
}
72+
})
73+
74+
t.test('should not extract dynamic insert-css statements', function (t) {
75+
t.plan(4)
76+
const sourcePath = path.join(__dirname, 'source-dynamic.js')
77+
78+
browserify(sourcePath)
79+
.plugin(cssExtract, { out: readCss })
80+
.bundle(readJs)
81+
82+
function readCss () {
83+
return bl(function (err, data) {
84+
t.ifError(err, 'no error')
85+
t.equal(String(data), '', 'no css extracted')
86+
})
87+
}
88+
89+
function readJs (err, data) {
90+
t.ifError(err, 'no error')
91+
const source = fs.readFileSync(sourcePath, 'utf8')
92+
t.ok(String(data).indexOf(String(source)) !== -1, 'source is still in built bundle')
93+
}
94+
})
5795
})

test/source-dynamic.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
insert('.foo {}')
2+
3+
function insert (foo) {
4+
require('insert-css')(foo)
5+
}

test/source-static.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var insertCss = require('insert-css')
2+
3+
insertCss('.foo {background: green}')

0 commit comments

Comments
 (0)