@@ -4,6 +4,8 @@ const co = require('co');
4
4
const express = require ( 'express' ) ;
5
5
const filesize = require ( 'filesize' ) ;
6
6
const fs = require ( 'fs' ) ;
7
+ const imagemin = require ( 'imagemin' ) ;
8
+ const imageminMozjpeg = require ( 'imagemin-mozjpeg' ) ;
7
9
const Jimp = require ( 'jimp' ) ;
8
10
const Nightmare = require ( 'nightmare' ) ;
9
11
const path = require ( 'path' ) ;
@@ -102,7 +104,9 @@ module.exports = _options => new Promise((resolve, reject) => {
102
104
console . log ( chalk . red ( ' * FAILED to create screenshot:' ) , component . screenshot . name ) ;
103
105
continue ; // eslint-disable-line
104
106
}
105
- const tmpObj = tmp . fileSync ( { dir : path . dirname ( component . screenshot . path ) } ) ;
107
+
108
+ const screenshotDir = path . dirname ( component . screenshot . path ) ;
109
+ const tmpPngObj = tmp . fileSync ( { dir : screenshotDir } ) ;
106
110
componentRect . height = Math . min ( componentRect . height , options . screenshotViewportHeight ) ;
107
111
yield nightmare
108
112
// we can not use .screenshot() with componentRect, so constrain the viewport instead
@@ -111,13 +115,12 @@ module.exports = _options => new Promise((resolve, reject) => {
111
115
componentRect . height || options . screenshotViewportHeight
112
116
) . scrollTo ( componentRect . y , componentRect . x )
113
117
// .wait(1000)
114
- // do *not* use componentRect in .screenshot() below or risk distortions
115
- . screenshot ( tmpObj . name ) ;
116
- const tmpFileSize = fs . statSync ( tmpObj . name ) . size ;
117
- tmpTotalFileSize += tmpFileSize ;
118
+ . screenshot ( tmpPngObj . name ) ; // do *not* use componentRect here or risk distortions
118
119
119
- // Resize and convert
120
- const screenshot = yield Jimp . read ( tmpObj . name ) ;
120
+ // Resize and convert to JPEG, and optimize
121
+ const tmpJpegDirObj = tmp . dirSync ( { dir : screenshotDir , unsafeCleanup : true } ) ;
122
+ const tmpJpegPath = path . join ( tmpJpegDirObj . name , path . basename ( component . screenshot . path ) ) ;
123
+ const screenshot = yield Jimp . read ( tmpPngObj . name ) ;
121
124
yield new Promise ( ( write_resolve , write_reject ) => {
122
125
if ( component . frontMatter . screenshot === undefined ||
123
126
component . frontMatter . screenshot . autocrop !== false ) {
@@ -131,18 +134,36 @@ module.exports = _options => new Promise((resolve, reject) => {
131
134
const scale = Math . max ( scaleHeight , scaleWidth ) ;
132
135
screenshot
133
136
. scale ( scale > 0 ? scale : 1.0 )
134
- . quality ( options . screenshotCompressionQuality )
135
- . write ( component . screenshot . path , ( err ) => {
136
- if ( err ) {
137
- write_reject ( err ) ;
137
+ // Do not use .quality() here, default max quality helps optimizers below
138
+ . write ( tmpJpegPath , ( jimp_err ) => {
139
+ if ( jimp_err ) {
140
+ write_reject ( jimp_err ) ;
138
141
}
139
- write_resolve ( ) ;
142
+ // Optimize
143
+ imagemin ( [ tmpJpegPath ] , screenshotDir , {
144
+ plugins : [
145
+ imageminMozjpeg ( { quality : options . mozjpegQuality } ) ,
146
+ // imageminJpegRecompress(), // this guy is useless
147
+ // imageminJpegtran(), // this guy is useless
148
+ ] ,
149
+ } ) . then ( ( ) => {
150
+ write_resolve ( ) ;
151
+ } ) . catch ( ( imagemin_err ) => {
152
+ write_reject ( imagemin_err ) ;
153
+ } ) ;
140
154
} ) ;
141
155
} ) ;
142
156
143
- tmpObj . removeCallback ( ) ;
157
+ const tmpFileSize = fs . statSync ( tmpPngObj . name ) . size ;
158
+ tmpTotalFileSize += tmpFileSize ;
144
159
const screenshotFileSize = fs . statSync ( component . screenshot . path ) . size ;
145
160
screenshotTotalFileSize += screenshotFileSize ;
161
+
162
+ // Cleanup
163
+ tmpPngObj . removeCallback ( ) ;
164
+ fs . unlinkSync ( tmpJpegPath ) ;
165
+ tmpJpegDirObj . removeCallback ( ) ;
166
+
146
167
console . log (
147
168
' * Created screenshot:' ,
148
169
component . screenshot . path ,
@@ -163,17 +184,4 @@ module.exports = _options => new Promise((resolve, reject) => {
163
184
} ) ;
164
185
165
186
resolve ( renderPromise ) ;
166
-
167
- // TODO: optimize all PNG files, eventually resize to smaller width
168
- // const imagemin = require('imagemin');
169
- // const imageminPngquant = require('imagemin-pngquant');
170
- // imagemin(['components/*.{jpg,png}'], ??, {
171
- // plugins: [
172
- // imageminPngquant({quality: '65-80'})
173
- // ]
174
- // }).then(files => {
175
- // console.log(files);
176
- // //=> [{data: <Buffer 89 50 4e …>, path: 'build/images/foo.jpg'}, …]
177
- // });
178
- //
179
187
} ) ; // return promise
0 commit comments