Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 23 additions & 31 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const ConcatStream = require('concat-stream')
const isRequire = require('is-require')()
const staticModule = require('static-module')
const through = require('through2')
const falafel = require('falafel')
const assert = require('assert')
const fs = require('fs')

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

function addHooks () {
// run before the "debug" step in browserify pipeline
bundle.pipeline.get('debug').unshift(through.obj(write, flush))
const writeStream = (typeof outFile === 'function')
? outFile()
: ConcatStream(writeOutFile)
: ConcatStream(fs.writeFileSync.bind(fs, outFile))

// run before the "label" step in browserify pipeline
// this makes sure insert-css requires are found before plugins like bundle-collapser run
bundle.pipeline.get('label').unshift(through.obj(write, flush))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I'm missing the context, but we should probably discuss this change and its implications in a separate issue if we haven't already :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I'm cool with discussing in a separate PR if that means we can land the rest of the patch right now


function write (chunk, enc, cb) {
const css = extract(chunk)
writeStream.write(css)
cb(null, chunk)
// A small performance boost: don't do ast parsing unless we know it's needed
if (String(chunk.source).indexOf('insert-css') === -1) {
return cb(null, chunk)
}

var sm = createStaticModule(writeStream)
sm.write(chunk.source)
sm.pipe(ConcatStream(function (source) {
// chunk.source is expected to be a string
chunk.source = String(source)
cb(null, chunk)
}))
sm.end()
}

// close stream and signal end
Expand All @@ -40,29 +51,10 @@ function cssExtract (bundle, opts) {
cb()
}
}

function writeOutFile (buffer) {
fs.writeFileSync(outFile, buffer)
}
}

// extract css from chunks
// obj -> str
function extract (chunk) {
// Do a performant check before building the ast
if (String(chunk.source).indexOf('insert-css') === -1) return ''

const css = []
const ast = falafel(chunk.source, { ecmaVersion: 6 }, walk)
chunk.source = ast.toString()
return css.join('\n')

function walk (node) {
if (!isRequire(node)) return
if (!node.arguments) return
if (!node.arguments[0]) return
if (node.arguments[0].value !== 'insert-css') return
css.push(node.parent.arguments[0].value)
node.parent.update('0')
}
function createStaticModule (writeStream) {
return staticModule({
'insert-css': writeStream.write.bind(writeStream)
})
}
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"license": "MIT",
"dependencies": {
"concat-stream": "^1.5.1",
"falafel": "^1.2.0",
"is-require": "0.0.1",
"static-module": "^1.3.0",
"through2": "^2.0.1"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions test/expected-static.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.foo {background: green}
42 changes: 40 additions & 2 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('css-extract', function (t) {
t.throws(cssExtract.bind(null, {}), 123, /object/)
})

t.test('should extract css', function (t) {
t.test('should extract sheetify css to given stream', function (t) {
t.plan(2)
browserify(path.join(__dirname, 'source.js'))
.transform('sheetify/transform')
Expand All @@ -31,7 +31,7 @@ test('css-extract', function (t) {
}
})

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

Expand All @@ -54,4 +54,42 @@ test('css-extract', function (t) {
})
}
})

t.test('should extract static insert-css statements', function (t) {
t.plan(2)
browserify(path.join(__dirname, 'source-static.js'))
.plugin(cssExtract, { out: createWs })
.bundle()

function createWs () {
return bl(function (err, data) {
t.ifError(err, 'no error')
const exPath = path.join(__dirname, './expected-static.css')
const expected = fs.readFileSync(exPath, 'utf8').trim()
t.equal(String(data), expected, 'extracted all the CSS')
})
}
})

t.test('should not extract dynamic insert-css statements', function (t) {
t.plan(4)
const sourcePath = path.join(__dirname, 'source-dynamic.js')

browserify(sourcePath)
.plugin(cssExtract, { out: readCss })
.bundle(readJs)

function readCss () {
return bl(function (err, data) {
t.ifError(err, 'no error')
t.equal(String(data), '', 'no css extracted')
})
}

function readJs (err, data) {
t.ifError(err, 'no error')
const source = fs.readFileSync(sourcePath, 'utf8')
t.ok(String(data).indexOf(String(source)) !== -1, 'source is still in built bundle')
}
})
})
5 changes: 5 additions & 0 deletions test/source-dynamic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
insert('.foo {}')

function insert (foo) {
require('insert-css')(foo)
}
3 changes: 3 additions & 0 deletions test/source-static.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var insertCss = require('insert-css')

insertCss('.foo {background: green}')