Introduction
Generally, atom-shell lets you create a web-based desktop application in pure javascript. Unlike CEF, which requires you to use C++ to write underlying code, or node-webkit, which only allows you to write everything in the web page, atom-shell gives you the power to use javascript to control the browser side.
Browser and renderer
Atom-shell is built upon Chromium's Content API, so it has the same multi-processes architecture with the Chrome browser. In summary, things about UI are done in the browser process, and each web page instance would start a new renderer process.
In atom-shell, you can just put everything in a simpler way: when you are executing javascript in browser side, you can control the application's life, create UI widget, deal with system events, and create windows which contain web pages; while on the renderer side, you can only control the web page you are showing, if you want something more like creating a new window, you should use IPC API to tell the browser to do that.
The architecture of an app
Generally, an app of atom-shell should contains at least following files:
app/
├── package.json
├── main.js
└── index.html
The format of package.json
is exactly the same with node's modules, and the script specified by the main
field is the startup script of your app, which will run under the browser side. An example of your package.json
is like this:
{
"name" : "atom",
"version" : "0.1.0",
"main" : "main.js"
}
The main.js
will be executed, and in which you should do the initialization work. To give the developers more power, atom-shell works by exposing necessary Content APIs in javascript, so developers can precisely control every piece of the app. An example of main.js
is:
var app = require('app'); // Module to control application life.
var delegate = require('atom_delegate'); // Delegate of Content API.
var Window = require('window'); // Module to create native browser window.
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
var mainWindow = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
app.terminate();
});
// This method will be called when atom-shell has done everything
// initialization and ready for creating browser windows.
delegate.browserMainParts.preMainMessageLoopRun = function() {
// Create the browser window,
mainWindow = new Window({ width: 800, height: 600 });
// and load the index.html of the app.
mainWindow.loadUrl('file://' + __dirname + '/index.html');
// Catch the event when web page in the window changes its title.
mainWindow.on('page-title-updated', function(event, title) {
// Prevent the default behaviour of 'page-title-updated' event.
event.preventDefault();
// Add a prefix for the window's original title.
this.setTitle('Atom Shell - ' + title);
});
// Hook to when the window is closed.
mainWindow.on('closed', function() {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
Finally the index.html
is the web page you want to show, in fact you actually don't need to provide it, you can just make the window load url of a remote page.
Package your app in atom-shell
To make atom-shell run your app, you should name the folder of your app as app
, and put it under Atom.app/Contents/Resources/
, like this:
Atom.app/Contents/Resources/app/
├── package.json
├── main.js
└── index.html
Then atom-shell will automatically read your package.json
. If there is no Atom.app/Contents/Resources/app/
, atom-shell will load the default empty app, which is Atom.app/Contents/Resources/browser/default_app/
.
IPC between browser and renderer
Atom-shell provides a set of javascript APIs for developers to communicate between browser and renderers. There are two types of message: asynchronous messages and synchronous messages, the former one is quite similar with node's IPC APIs, while the latter one is mainly used for implement the RPC API. Details can be found in the ipc
module reference.