Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the application’s size #2

Closed
rdeltour opened this issue Oct 11, 2018 · 7 comments
Closed

Reduce the application’s size #2

rdeltour opened this issue Oct 11, 2018 · 7 comments

Comments

@rdeltour
Copy link
Member

rdeltour commented Oct 11, 2018

Current, Ace weighs around 300MB, which is huge. There are two primary reasons:

  • being based on Electron (which bundles a custom-built chromium engine)
  • bundling a local chromium engine that can be programmatically driven (by puppeteer) to run accessibility checks

There are a couple approaches to improve the situation, while keeping a cross-platform HTML+CSS+JS code base, unfortunately none of which seems to be ideal or even fully available to us at this stage:

Using puppeteer to drive the Electron-bundle chromium instance

This would remove the need to bundle our own copy of Chromium. However:

  • Electron cannot be launched as-is as a local chromium executable, since its own chromium engine is custom-built (see the article “Electron internals: Building Chromium as a library” for the background story on how it's built).
  • Electron could be possibly launched with the --remote-debugging-port flag to enable remote debugging and allow Puppeteer to connect to it (with the connect() API). So far, our experiments with the current approach failed:
    • the version of chromium bundled with Electron is lagging behind the state-of-the-art chromium, which mean Electron is theoretically compatible only with earlier versions of puppeteer
    • Electron doesn't seem to provide the Target API from the Chrome DevTools protocol, which is used by Puppeteer to open new browser pages.
    • independently of the above, this may create additional security concerns.

Bundling a lighter build of Chromium

By default, Puppeteer bundles the default Chromium build. We could save a few MB by only bundling chromium's headless shell instead. Pupetteer would make this feasible by skipping the chromium download at install (or depending on puppeteer-core), then using its BrowserFetcher API to download the headless shell.
However, at the time of writing no pre-built binaries of headless_shell are available.

See also puppeteer/puppeteer#3140

Compiling the code to a native GUI

There are a few promising libraries:

  • React Native, which unfortunately has no official support for desktop application, so isn't deemed production-ready.
  • libui, and libraries based on it like Proton Native. These are still experimental projects at this stage.

The huge benefit of using this approach is that the GUI itself would be much more lightweight, and it would allow us to independently control the version of the local chromium engine used by Ace (with puppeteer).

Porting to NW.js?

NW.js is an alternative to Electron, but it seems to be based on default chromium builds. It could possibly allow to be driven by puppeteer, and is more up-to-date with latest chromium versions.

Porting to NW.js wouldn't solve the performance-related issues of the app not being native however, and the build ecosystem (notably for creating installers and updaters) is less mature than it is in the Electron world.

Developing per-platform native UIs

That could solve all our issues, and would be better for performance. However we're quite happy with the HTML+CSS+JS cross-platform development workflow, and we just don't have the resources to develop different code bases for each target OS ¯\_(ツ)_/¯.

@danielweck
Copy link
Member

Unless I am mistaken, API usage of Puppeteer is limited to:

const browser = await puppeteer.launch({ args });
// ...
const page = await browser.newPage();
await page.goto(url);
// ...
const scriptElemHandle = await page.addScriptTag({ path });
await page.evaluate((scriptElem) => {
// ...
}, scriptElemHandle);
// ...
const results = await page.evaluate(() => new Promise((resolve, reject) => {
// ...
}));
await page.close();
// ...
await browser.close();

...all of which can be performed via Electron's own Chromium renderer process, either in a separate BrowserWindow, or via webview objects or sandboxed iframes inside the main BrowserWindow. The not-so-trivial part would be to refactor the use of Puppeteer (const puppeteer = require('puppeteer'); etc.) to something like PuppeteerAdapter which would proxy the API calls to either the "real" Puppeteer, or Electron's own Chromium.

@rdeltour
Copy link
Member Author

...all of which can be performed via Electron's own Chromium renderer process

you're right, thanks for tip! (in fact, quite coincidentally, I was thinking about that too today while sipping my morning coffee 😄 ). It would require some refactoring of ace-core of course. Another issue could be to "hide" these extra windows off-screen, while keeping control of their size (as some checks depend on the viewport size). I'm not familiar enough with Electron’s API, and haven't looked at the doc yet, do you know if this is possible?

@danielweck
Copy link
Member

A single off-screen Electron BrowserWindow would probably be more efficient than opening / closing separate "hard" webview instances for every HTML document in the EPUB publication, especially as HTTP resources are cached in the shared browser context (session).

That being said, the main question is whether or not "hiding" a window off-screen has undesirable side-effects when automating a11y tests ... I'm not sure. To be verified.

@danielweck
Copy link
Member

By the way, have you looked into Carlo?

Carlo provides Node applications with the rich rendering capabilities powered by the Google Chrome browser. It uses Puppeteer project to communicate with the locally installed browser instance, provides remote call infrastructure for communication between Node and the browser.

https://github.com/GoogleChromeLabs/carlo

@rdeltour
Copy link
Member Author

rdeltour commented Nov 2, 2018

By the way, have you looked into Carlo?

Yes, I've just seen a tweet about that yesterday. It's definitely interesting, but not fully adapted to our requirements I think (for instance it will display an error message when Chrome isn't installed on the user's environment, which will not fulfill the easy-install experience we're promising).

@danielweck
Copy link
Member

Work in progress: daisy/ace#227

@danielweck
Copy link
Member

Fixed: #42

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants