Skip to content

Commit

Permalink
feat(main): upgraded to pptr v2 and optimized chrome launcher
Browse files Browse the repository at this point in the history
Upgraded to pptr v2 to limit number of total running instances to 1. Optimized chrome launcher flags
to fix the connection error issues.

fix #62 fix #58
  • Loading branch information
onderceylan committed Nov 1, 2019
1 parent 9c3c155 commit a14e8e6
Show file tree
Hide file tree
Showing 10 changed files with 1,215 additions and 575 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
node: [8, 10, 12]
os: [ubuntu-latest, macOS-latest]
os: [ubuntu-latest, macOS-latest, windows-latest]

steps:
- uses: actions/checkout@v1
Expand Down
267 changes: 191 additions & 76 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"url": "https://github.com/onderceylan/pwa-asset-generator.git"
},
"engines": {
"node": ">=6.4.0"
"node": ">=8.16.0"
},
"keywords": [
"pwa",
Expand Down Expand Up @@ -56,14 +56,14 @@
"meow": "5.0.0",
"mime-types": "2.1.24",
"progress": "2.0.3",
"puppeteer-core": ">=1.20.0",
"puppeteer-core": "2.0.0",
"slash": "3.0.0",
"tslib": "1.10.0"
},
"devDependencies": {
"@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^8.1.0",
"@jedmao/semantic-release-npm-github-config": "^1.0.6",
"@jedmao/semantic-release-npm-github-config": "^1.0.7",
"@types/cheerio": "^0.22.13",
"@types/jest": "^24.0.18",
"@types/lodash.isequal": "^4.5.5",
Expand All @@ -86,7 +86,7 @@
"jest": "^24.8.0",
"lint-staged": "^9.2.1",
"prettier": "^1.18.2",
"semantic-release": "^15.13.21",
"semantic-release": "^15.13.28",
"ts-jest": "^24.1.0",
"typescript": "^3.6.3"
},
Expand Down
356 changes: 21 additions & 335 deletions src/__snapshots__/cli.test.ts.snap

Large diffs are not rendered by default.

902 changes: 877 additions & 25 deletions src/__snapshots__/main.test.ts.snap

Large diffs are not rendered by default.

77 changes: 6 additions & 71 deletions src/cli.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// TODO: replace execa with exec/execFile of child_process as it doesn't support node < 8.3.0
import execa from 'execa';
import file from './helpers/file';

test('throws error when input is not provided', async () => {
try {
Expand All @@ -10,55 +8,7 @@ test('throws error when input is not provided', async () => {
}
});

test('creates an output folder when output path does not exist', async () => {
const tempFolderName = './temp';

await execa.sync('./bin/cli', [
'./static/logo.png',
tempFolderName,
'-s=false',
'--icon-only',
]);
expect(await file.pathExists(tempFolderName)).toBe(true);
});

test('generates icons only', async () => {
const { stdout } = await execa(
'./bin/cli',
['./static/logo.png', './temp', '-s=false', '--icon-only'],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});

test('generates splash screens only', async () => {
const { stdout } = await execa(
'./bin/cli',
['./static/logo.png', './temp', '-s=false', '--splash-only'],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});

test('generates portrait splash screens only', async () => {
const { stdout } = await execa(
'./bin/cli',
[
'./static/logo.png',
'./temp',
'-s=false',
'--splash-only',
'--portrait-only',
],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});

test('generates landscape splash screens only', async () => {
test('integrates with main API and creates an output with generated meta', async () => {
const { stdout } = await execa(
'./bin/cli',
[
Expand All @@ -67,29 +17,14 @@ test('generates landscape splash screens only', async () => {
'-s=false',
'--splash-only',
'--landscape-only',
'--favicon',
'-a="%PUBLIC_URL%"',
'--dark-mode',
'--type=jpeg',
'-q=20',
],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});

test('generates icons and splash screens when both only flags exist', async () => {
const { stdout } = await execa(
'./bin/cli',
['./static/logo.png', './temp', '-s=false', '--splash-only', '--icon-only'],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});

test('generates icons and splash screens with path prefix', async () => {
const { stdout } = await execa(
'./bin/cli',
['./static/logo.png', './temp', '-s=false', '--path=%PUBLIC_URL%'],
{ env: { PAG_TEST_MODE: '1' } },
);

expect(stdout).toMatchSnapshot();
});
11 changes: 4 additions & 7 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,26 +116,23 @@ export default {
'--log-level=3', // Fatal only
'--no-default-browser-check',
'--disable-infobars',
'--disable-web-security',
'--disable-site-isolation-trials',
'--no-experiments',
'--ignore-gpu-blacklist',
'--ignore-certificate-errors',
'--ignore-certificate-errors-spki-list',
'--disable-gpu',
'--disable-default-apps',
'--enable-features=NetworkService',
'--disable-setuid-sandbox',
'--disable-features=TranslateUI',
'--disable-extensions',
'--disable-background-networking',
'--disable-sync',
'--metrics-recording-only',
'--disable-default-apps',
'--mute-audio',
'--no-first-run',
'--headless',
],

CHROME_LAUNCHER_DEBUG_PORT: 9222,
CHROME_LAUNCHER_MAX_CONN_RETRIES: 10,
EMULATED_USER_AGENT:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3641.0 Safari/537.36',
APPLE_HIG_SPLASH_SCR_SPECS_URL:
Expand All @@ -161,7 +158,7 @@ export default {
MANIFEST_ICON_FILENAME_PREFIX: 'manifest-icon',
APPLE_HIG_SPLASH_SCR_SPECS_DATA_GRID_SELECTOR: 'table tbody tr',
WAIT_FOR_SELECTOR_TIMEOUT: 1000,
BROWSER_SHELL_TIMEOUT: 60000,
BROWSER_TIMEOUT: 10000,

FAVICON_META_HTML: (size: number, url: string, mimeType: string): string =>
`<link rel="icon" type="${mimeType}" sizes="${size}x${size}" href="${url}">
Expand Down
14 changes: 10 additions & 4 deletions src/helpers/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const launchSystemBrowser = (): Promise<LaunchedChrome> => {
const launchOptions: ChromeLauncherOptions = {
chromeFlags: constants.PUPPETEER_LAUNCH_ARGS,
logLevel: 'silent',
port: constants.CHROME_LAUNCHER_DEBUG_PORT,
maxConnectionRetries: constants.CHROME_LAUNCHER_MAX_CONN_RETRIES,
};

return launch(launchOptions);
Expand Down Expand Up @@ -114,11 +116,15 @@ const getBrowserInstance = async (
chrome = await launchSystemBrowser();
browser = await getSystemBrowserInstance(chrome, launchArgs);
} catch (e) {
if (e.code === LAUNCHER_NOT_INSTALLED_ERROR_CODE) {
browser = await getLocalBrowserInstance(launchArgs);
} else {
throw e;
// Kill chrome instance if it's not possible to connect to its debuggable instance
if (
e.code !== LAUNCHER_NOT_INSTALLED_ERROR_CODE &&
chrome &&
chrome.pid > 0
) {
process.kill(chrome.pid);
}
browser = await getLocalBrowserInstance(launchArgs);
}

return { browser, chrome };
Expand Down
100 changes: 49 additions & 51 deletions src/helpers/puppets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const getAppleSplashScreenData = async (
}

logger.log('Retrieved splash screen data');
await page.close();
return splashScreenData;
};

Expand Down Expand Up @@ -197,11 +198,13 @@ const getDeviceScaleFactorData = async (
}

logger.log('Retrieved scale factor data');
await page.close();
return scaleFactorData;
};

const getSplashScreenMetaData = async (
options: Options,
browser: Browser,
): Promise<SplashScreenSpec[]> => {
const logger = preLogger(getSplashScreenMetaData.name, options);

Expand All @@ -215,9 +218,6 @@ const getSplashScreenMetaData = async (
'🤖',
);

const { browser, chrome } = await browserHelper.getBrowserInstance({
timeout: 5000,
});
let splashScreenUniformMetaData;

try {
Expand All @@ -237,8 +237,6 @@ const getSplashScreenMetaData = async (
);
}

await killBrowser(browser, chrome);

return splashScreenUniformMetaData;
};

Expand All @@ -250,6 +248,7 @@ const saveImages = async (
source: string,
output: string,
options: Options,
browser: Browser,
): Promise<SavedImage[]> => {
let address: string;
let shellHtml: string;
Expand All @@ -263,52 +262,39 @@ const saveImages = async (
shellHtml = await url.getShellHtml(source, options);
}

return (
imageList
.map(async ({ name, width, height, scaleFactor, orientation }) => {
const { browser, chrome } = await browserHelper.getBrowserInstance({
defaultViewport: {
width,
height,
},
timeout: constants.BROWSER_SHELL_TIMEOUT,
});
return Promise.all(
imageList.map(async ({ name, width, height, scaleFactor, orientation }) => {
const { type, quality } = options;
const path = file.getImageSavePath(name, output, type);

const { type, quality } = options;
const path = file.getImageSavePath(name, output, type);

try {
const page = await browser.newPage();

if (address) {
await page.goto(address);
} else {
await page.setContent(shellHtml);
}

await page.screenshot({
path,
omitBackground: !options.opaque,
type: options.type,
...(type !== 'png' ? { quality } : {}),
});

logger.success(`Saved image ${name}`);
await killBrowser(browser, chrome);

return { name, width, height, scaleFactor, path, orientation };
} catch (e) {
await killBrowser(browser, chrome);
logger.error(e.message);
throw Error(`Failed to save image ${name}`);
try {
const page = await browser.newPage();
await page.setViewport({ width, height });

if (address) {
await page.goto(address);
} else {
await page.setContent(shellHtml);
}
})
// Resolving array of promises in sequential manner to kill chrome instances properly
.reduce(
(acc, promise: Promise<SavedImage>) =>
acc.then(result => promise.then(Array.prototype.concat.bind(result))),
Promise.resolve([] as SavedImage[]),
)

await page.screenshot({
path,
omitBackground: !options.opaque,
type: options.type,
...(type !== 'png' ? { quality } : {}),
});

await page.close();

logger.success(`Saved image ${name}`);

return { name, width, height, scaleFactor, path, orientation };
} catch (e) {
logger.error(e.message);
console.error(e);
throw Error(`Failed to save image ${name}`);
}
}),
);
};

Expand All @@ -318,7 +304,10 @@ const generateImages = async (
options: Options,
): Promise<SavedImage[]> => {
const logger = preLogger(generateImages.name, options);
const splashScreenMetaData = await getSplashScreenMetaData(options);
const { browser, chrome } = await browserHelper.getBrowserInstance({
timeout: constants.BROWSER_TIMEOUT,
});
const splashScreenMetaData = await getSplashScreenMetaData(options, browser);
const allImages = [
...(!options.iconOnly
? images.getSplashScreenImages(splashScreenMetaData, options)
Expand All @@ -336,7 +325,16 @@ const generateImages = async (
// Increase MaxListeners and suppress MaxListenersExceededWarning
process.setMaxListeners(0);

return saveImages(allImages, source, output, options);
const savedImages = await saveImages(
allImages,
source,
output,
options,
browser,
);

await killBrowser(browser, chrome);
return savedImages;
};

export default {
Expand Down
Loading

0 comments on commit a14e8e6

Please sign in to comment.