@@ -74,22 +74,30 @@ function normalizeManifestPaths (tokensByFile, rootDir) {
74
74
return output ;
75
75
}
76
76
77
+ function dedupeSources ( sources ) {
78
+ var foundHashes = { }
79
+ Object . keys ( sources ) . forEach ( function ( key ) {
80
+ var hash = stringHash ( sources [ key ] ) ;
81
+ if ( foundHashes [ hash ] ) {
82
+ delete sources [ key ] ;
83
+ }
84
+ else {
85
+ foundHashes [ hash ] = true ;
86
+ }
87
+ } )
88
+ }
89
+
77
90
var cssExt = / \. c s s $ / ;
78
91
79
92
// caches
80
93
//
81
94
// persist these for as long as the process is running. #32
82
95
83
- // keep track of css files visited
84
- var filenames = [ ] ;
85
-
86
96
// keep track of all tokens so we can avoid duplicates
87
97
var tokensByFile = { } ;
88
98
89
- // keep track of all source files for later builds: when
90
- // using watchify, not all files will be caught on subsequent
91
- // bundles
92
- var sourceByFile = { } ;
99
+ // we need a separate loader for each entry point
100
+ var loadersByFile = { } ;
93
101
94
102
module . exports = function ( browserify , options ) {
95
103
options = options || { } ;
@@ -103,9 +111,10 @@ module.exports = function (browserify, options) {
103
111
var jsonOutFilename = options . json || options . jsonOutput ;
104
112
var sourceKey = cssOutFilename ;
105
113
106
- // keying our source caches by the name of our output file means we can
107
- // isolate css compilation of seperate bundles that are running in parallel
108
- sourceByFile [ sourceKey ] = sourceByFile [ sourceKey ] || { } ;
114
+ var loader = loadersByFile [ sourceKey ] ;
115
+ if ( ! loader ) {
116
+ loader = loadersByFile [ sourceKey ] = new FileSystemLoader ( rootDir , plugins ) ;
117
+ }
109
118
110
119
// PostCSS plugins passed to FileSystemLoader
111
120
var plugins = options . use || options . u ;
@@ -158,10 +167,6 @@ module.exports = function (browserify, options) {
158
167
return through ( ) ;
159
168
}
160
169
161
- // collect visited filenames
162
- filenames . push ( filename ) ;
163
-
164
- var loader = new FileSystemLoader ( rootDir , plugins ) ;
165
170
return through ( function noop ( ) { } , function end ( ) {
166
171
var self = this ;
167
172
@@ -170,11 +175,6 @@ module.exports = function (browserify, options) {
170
175
171
176
assign ( tokensByFile , loader . tokensByFile ) ;
172
177
173
- // store this file's source to be written out to disk later
174
- sourceByFile [ sourceKey ] [ filename ] = loader . finalSource ;
175
-
176
- compiledCssStream . push ( loader . finalSource ) ;
177
-
178
178
self . queue ( output ) ;
179
179
self . queue ( null ) ;
180
180
} , function ( err ) {
@@ -195,19 +195,19 @@ module.exports = function (browserify, options) {
195
195
bundle . emit ( 'css stream' , compiledCssStream ) ;
196
196
197
197
bundle . on ( 'end' , function ( ) {
198
+ // under certain conditions (eg. with shared libraries) we can end up with
199
+ // multiple occurrences of the same rule, so we need to remove duplicates
200
+ dedupeSources ( loader . sources )
201
+
198
202
// Combine the collected sources for a single bundle into a single CSS file
199
- var files = Object . keys ( sourceByFile [ sourceKey ] ) ;
200
- var css ;
203
+ var css = loader . finalSource ;
201
204
202
205
// end the output stream
206
+ compiledCssStream . push ( css ) ;
203
207
compiledCssStream . push ( null ) ;
204
208
205
209
// write the css file
206
210
if ( cssOutFilename ) {
207
- css = files . map ( function ( file ) {
208
- return sourceByFile [ sourceKey ] [ file ] ;
209
- } ) . join ( '\n' ) ;
210
-
211
211
fs . writeFile ( cssOutFilename , css , function ( err ) {
212
212
if ( err ) {
213
213
browserify . emit ( 'error' , err ) ;
0 commit comments