Skip to content

Commit 6c2448b

Browse files
authored
Merge pull request #4 from isleofcode/feat/chrome-headless
Feat/chrome headless
2 parents e41f3cb + bd71249 commit 6c2448b

File tree

6 files changed

+254
-4
lines changed

6 files changed

+254
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"listr": "^0.12.0",
5050
"lodash": "^4.17.4",
5151
"phantomjs-prebuilt": "^2.1.14",
52+
"puppeteer": "^0.12.0",
5253
"request": "^2.81.0",
5354
"rsvp": "^4.0.1"
5455
},

src/page.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,13 @@ export class Page {
102102
async render(options = {}, ...args) {
103103
assert.ok(!this.isDestroyed && !this.isDestroying && this.isLoaded);
104104

105-
if (isString(options)) {
105+
let pagePathParamKey = this.renderer.constructor.pagePathParamKey;
106+
107+
if (isString(pagePathParamKey) && isString(options)) {
106108
let filename = options;
107109

108110
options = isPresent(args[0]) ? args[0] : {};
109-
options.filename = filename;
111+
options[pagePathParamKey] = filename;
110112
}
111113

112114
if (isString(options.filename) && !isString(options.format)) {

src/renderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let defaultRenderer;
1616

1717
export class Renderer extends EventEmitter {
1818
static get rendererConstructor() {
19-
return this._rendererConstructor || require('./renderers/phantom').default;
19+
return this._rendererConstructor || require('./renderers/chrome').default;
2020
}
2121

2222
static set rendererConstructor(value) {

src/renderers/chrome/index.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import _ from 'lodash';
2+
import path from 'path';
3+
import puppeteer from 'puppeteer';
4+
5+
import Renderer from '../../renderer';
6+
7+
const { isString } = _;
8+
9+
const DEFAULT_BOOT_OPTIONS = {}; // use puppeteer defaults, https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
10+
11+
export class ChromeRenderer extends Renderer {
12+
static get DEFAULT_BOOT_OPTIONS() {
13+
return this._DEFAULT_BOOT_OPTIONS || DEFAULT_BOOT_OPTIONS;
14+
}
15+
16+
static set DEFAULT_BOOT_OPTIONS(value) {
17+
this._DEFAULT_BOOT_OPTIONS = value;
18+
}
19+
20+
static get pagePathParamKey() {
21+
return 'path';
22+
}
23+
24+
constructor(attrs = {}) {
25+
super(attrs);
26+
27+
this.bootOptions = this.bootOptions ||
28+
this.constructor.DEFAULT_BOOT_OPTIONS;
29+
}
30+
31+
get browser() {
32+
return this._browser;
33+
}
34+
35+
set browser(value) {
36+
this._browser = value;
37+
}
38+
39+
get bootOptions() {
40+
return this._bootOptions;
41+
}
42+
43+
set bootOptions(value) {
44+
this._bootOptions = value;
45+
}
46+
47+
async boot() {
48+
if (this.isBooted) {
49+
return;
50+
}
51+
52+
try {
53+
if (!this.isBooting) {
54+
let bootOptions = this.bootOptions;
55+
56+
this.isBooting = true;
57+
this.browser = bootOptions.hasOwnProperty('browserWSEndpoint') ?
58+
await puppeteer.connect(bootOptions) :
59+
await puppeteer.launch(bootOptions);
60+
61+
this.isBooted = true;
62+
}
63+
} catch (err) {
64+
this.isBooted = false;
65+
throw err;
66+
}
67+
}
68+
69+
async shutdown() {
70+
let browser = this.browser;
71+
72+
if (browser !== null && browser !== undefined) {
73+
browser.close();
74+
this.browser = undefined;
75+
}
76+
77+
this.isBooted = false;
78+
}
79+
80+
async ping() {
81+
return this.browser.pages();
82+
}
83+
84+
async loadPage(page, options) {
85+
let chromePage = page._chromePage;
86+
87+
if (chromePage === null || chromePage === undefined) {
88+
chromePage = await this.browser.newPage();
89+
page._chromePage = chromePage;
90+
}
91+
92+
page.isLoading = true;
93+
94+
try {
95+
let { url, html } = options;
96+
97+
if (html !== undefined && html !== null) {
98+
await chromePage.setContent(html);
99+
} else {
100+
if (url !== undefined && url !== null) {
101+
delete options.url;
102+
} else {
103+
url = page.id;
104+
}
105+
106+
await chromePage.goto(url, options);
107+
}
108+
109+
page.isLoaded = true;
110+
} catch (err) {
111+
page.isLoaded = false;
112+
throw err;
113+
}
114+
}
115+
116+
async renderPage(page, options = {}) {
117+
let { path: filepath, type } = options;
118+
let buffer;
119+
120+
if (!isString(type)) {
121+
type = isString(filepath) ? path.extname(filepath).slice(1) : 'html';
122+
type = type.length > 0 ? type : 'html';
123+
}
124+
125+
switch (type) {
126+
case 'html':
127+
buffer = await page._chromePage.content();
128+
break;
129+
case 'pdf':
130+
let { emulateMedia } = options;
131+
132+
if (emulateMedia !== null && emulateMedia !== undefined) {
133+
await page._chromePage.emulateMedia(emulateMedia);
134+
delete options.emulateMedia;
135+
}
136+
137+
buffer = await page._chromePage.pdf(options);
138+
break;
139+
default:
140+
buffer = await page._chromePage.screenshot(options);
141+
break;
142+
}
143+
144+
return isString(filepath) ? filepath : buffer;
145+
}
146+
147+
async unloadPage(page, ...args) {
148+
await page._chromePage.close();
149+
150+
return true;
151+
}
152+
}
153+
154+
export default ChromeRenderer;

src/renderers/phantom/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export class PhantomRenderer extends Renderer {
4040
return denodeify(request);
4141
}
4242

43+
static get pagePathParamKey() {
44+
return 'filename';
45+
}
46+
4347
constructor(attrs = {}) {
4448
super(attrs);
4549

yarn.lock

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ acorn@^5.1.1:
2424
version "5.1.1"
2525
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
2626

27+
agent-base@^4.1.0:
28+
version "4.1.1"
29+
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.1.1.tgz#92d8a4fc2524a3b09b3666a33b6c97960f23d6a4"
30+
dependencies:
31+
es6-promisify "^5.0.0"
32+
2733
ajv-keywords@^1.0.0:
2834
version "1.5.1"
2935
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
@@ -142,6 +148,10 @@ async-each@^1.0.0:
142148
version "1.0.1"
143149
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
144150

151+
async-limiter@~1.0.0:
152+
version "1.0.0"
153+
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
154+
145155
asynckit@^0.4.0:
146156
version "0.4.0"
147157
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -914,7 +924,7 @@ concat-stream@1.5.0:
914924
readable-stream "~2.0.0"
915925
typedarray "~0.0.5"
916926

917-
concat-stream@^1.6.0:
927+
concat-stream@1.6.0, concat-stream@^1.6.0:
918928
version "1.6.0"
919929
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
920930
dependencies:
@@ -976,6 +986,12 @@ debug@0.7.4:
976986
version "0.7.4"
977987
resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39"
978988

989+
debug@2.2.0:
990+
version "2.2.0"
991+
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
992+
dependencies:
993+
ms "0.7.1"
994+
979995
debug@2.6.8, debug@^2.6.8:
980996
version "2.6.8"
981997
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
@@ -988,6 +1004,12 @@ debug@^2.1.1, debug@^2.2.0:
9881004
dependencies:
9891005
ms "0.7.3"
9901006

1007+
debug@^2.4.1:
1008+
version "2.6.9"
1009+
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
1010+
dependencies:
1011+
ms "2.0.0"
1012+
9911013
deep-eql@^2.0.1:
9921014
version "2.0.2"
9931015
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a"
@@ -1092,10 +1114,20 @@ es6-map@^0.1.5:
10921114
es6-symbol "~3.1.1"
10931115
event-emitter "~0.3.5"
10941116

1117+
es6-promise@^4.0.3:
1118+
version "4.1.1"
1119+
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
1120+
10951121
es6-promise@~4.0.3:
10961122
version "4.0.5"
10971123
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.0.5.tgz#7882f30adde5b240ccfa7f7d78c548330951ae42"
10981124

1125+
es6-promisify@^5.0.0:
1126+
version "5.0.0"
1127+
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
1128+
dependencies:
1129+
es6-promise "^4.0.3"
1130+
10991131
es6-set@~0.1.5:
11001132
version "0.1.5"
11011133
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
@@ -1332,6 +1364,15 @@ extglob@^0.3.1:
13321364
dependencies:
13331365
is-extglob "^1.0.0"
13341366

1367+
extract-zip@^1.6.5:
1368+
version "1.6.5"
1369+
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440"
1370+
dependencies:
1371+
concat-stream "1.6.0"
1372+
debug "2.2.0"
1373+
mkdirp "0.5.0"
1374+
yauzl "2.4.1"
1375+
13351376
extract-zip@~1.5.0:
13361377
version "1.5.0"
13371378
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.5.0.tgz#92ccf6d81ef70a9fa4c1747114ccef6d8688a6c4"
@@ -1674,6 +1715,13 @@ http-signature@~1.1.0:
16741715
jsprim "^1.2.2"
16751716
sshpk "^1.7.0"
16761717

1718+
https-proxy-agent@^2.1.0:
1719+
version "2.1.0"
1720+
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.0.tgz#1391bee7fd66aeabc0df2a1fa90f58954f43e443"
1721+
dependencies:
1722+
agent-base "^4.1.0"
1723+
debug "^2.4.1"
1724+
16771725
iconv-lite@^0.4.17:
16781726
version "0.4.18"
16791727
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
@@ -2167,6 +2215,10 @@ mime-types@^2.1.12, mime-types@~2.1.7:
21672215
dependencies:
21682216
mime-db "~1.27.0"
21692217

2218+
mime@^1.3.4:
2219+
version "1.4.1"
2220+
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
2221+
21702222
mimic-fn@^1.0.0:
21712223
version "1.1.0"
21722224
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
@@ -2232,6 +2284,10 @@ mocha@^3.5.0:
22322284
mkdirp "0.5.1"
22332285
supports-color "3.1.2"
22342286

2287+
ms@0.7.1:
2288+
version "0.7.1"
2289+
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
2290+
22352291
ms@0.7.3:
22362292
version "0.7.3"
22372293
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
@@ -2506,6 +2562,10 @@ progress@~1.1.8:
25062562
version "1.1.8"
25072563
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
25082564

2565+
proxy-from-env@^1.0.0:
2566+
version "1.0.0"
2567+
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
2568+
25092569
pseudomap@^1.0.2:
25102570
version "1.0.2"
25112571
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -2514,6 +2574,19 @@ punycode@^1.4.1:
25142574
version "1.4.1"
25152575
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
25162576

2577+
puppeteer@^0.12.0:
2578+
version "0.12.0"
2579+
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-0.12.0.tgz#9c421930851594dfdd479d07646666a74ced7719"
2580+
dependencies:
2581+
debug "^2.6.8"
2582+
extract-zip "^1.6.5"
2583+
https-proxy-agent "^2.1.0"
2584+
mime "^1.3.4"
2585+
progress "^2.0.0"
2586+
proxy-from-env "^1.0.0"
2587+
rimraf "^2.6.1"
2588+
ws "^3.0.0"
2589+
25172590
qs@~6.3.0:
25182591
version "6.3.2"
25192592
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
@@ -2785,6 +2858,10 @@ safe-buffer@^5.0.1:
27852858
version "5.0.1"
27862859
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
27872860

2861+
safe-buffer@~5.1.0:
2862+
version "5.1.1"
2863+
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
2864+
27882865
"semver@2 || 3 || 4 || 5":
27892866
version "5.4.1"
27902867
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
@@ -3073,6 +3150,10 @@ uid-number@^0.0.6:
30733150
version "0.0.6"
30743151
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
30753152

3153+
ultron@~1.1.0:
3154+
version "1.1.0"
3155+
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864"
3156+
30763157
user-home@^1.1.1:
30773158
version "1.1.1"
30783159
resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
@@ -3136,6 +3217,14 @@ write@^0.2.1:
31363217
dependencies:
31373218
mkdirp "^0.5.1"
31383219

3220+
ws@^3.0.0:
3221+
version "3.2.0"
3222+
resolved "https://registry.yarnpkg.com/ws/-/ws-3.2.0.tgz#d5d3d6b11aff71e73f808f40cc69d52bb6d4a185"
3223+
dependencies:
3224+
async-limiter "~1.0.0"
3225+
safe-buffer "~5.1.0"
3226+
ultron "~1.1.0"
3227+
31393228
xtend@^4.0.0:
31403229
version "4.0.1"
31413230
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"

0 commit comments

Comments
 (0)