A CEF (Chromium Embedded Framework) extension which provides a Node.js module system for your CEF projects.
It's based on the stable CEF dll-wrapper API, therefore Node-CEF should be compatible with most CEF3 builds without modifying the V8
engine or compiling a custom libcef.dll
. Node-CEF is designed to work with general web pages, and it won't crash your render process like other Node.js-CEF glued projects do when any uncaught errors occur.
Note: The native (Java Script) modules are completely compatible with Node.js while the built-in and linked (*.node) modules are not ABI compatible, but you can modify these modules and build them with Node-CEF easily.
- Node.js compatible module system for your CEF project.
- Managing and installing packages with npm.
- Writing and registering your extra built-in modules easily.
- Debugging modules with Chrome DevTools.
- Assertion Testing
- Buffer
- Events
- File System
- Globals
- Modules
- OS
- VM
- Process
- Punycode
- Query String
- String Decoder
- Timers
- URL
- Utilities
See also Differences with Node.js
Any remote accesses to the ncjs
module are forbidden, currently only file://
scheme is the valid source to initialize Node-CEF.
- Child Process
- Stream
- Supports for remote modules (Sync/Async).
Please create pull requests to help us add supports for the rest modules of Node.js.
Requirement: VS2005 (VC8.0) and above, Python 2.x
- Open
Node-CEF.sln
with your Visual Studio. - Add your CEF path to "Additional Include Directories" of the
libcef_node
project. - Build solution.
Please add these libraries to your project's "Additional Dependencies":
libcef_node.lib
libcef_dll_wrapper.lib
libcef.lib
libuv.lib
Psapi.lib
Userenv.lib
Ws2_32.lib
Iphlpapi.lib
This sample shows how to integrate Node-CEF in your CEF project:
#include <include/cef_app.h>
#include <ncjs/RenderProcessHandler.h>
class MyNodeCefApp : public CefApp, public ncjs::RenderProcessHandler {
public:
CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() { return this; }
IMPLEMENT_REFCOUNTING(MyNodeCefApp);
};
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow) {
const CefMainArgs main_args(hInstance);
return CefExecuteProcess(main_args, new MyNodeCefApp, NULL);
}
What we need to do is just changing the inheritance from CefRenderProcessHandler
to ncjs::RenderProcessHandler
for your CefApp
based class.
Now your CEF project owns the Node.js module system, you can test it with:
ncjs.require('os').hostname();
Codes for MyModule.cpp:
#include "ncjs/module.h"
namespace ncjs {
class MyModule : public JsObjecT<MyModule> {
// my_module.foo()
NCJS_OBJECT_FUNCTION(Foo)(CefRefPtr<CefV8Value> object,
const CefV8ValueList& args, CefRefPtr<CefV8Value>& retval, CefString& except)
{
retval = CefV8Value::CreateString(NCJS_REFTEXT("Hello Node-CEF!"));
}
// object factory
NCJS_BEGIN_OBJECT_FACTORY()
NCJS_MAP_OBJECT_FUNCTION("foo", Foo)
NCJS_END_OBJECT_FACTORY()
};
NCJS_DEFINE_BUILTIN_MODULE(my_module, MyModule);
} // ncjs
In RenderProcessHandler::OnNodeCefCreated()
callback:
NCJS_DECLARE_BUILTIN_MODULE(MyModule);
void MyNodeCefApp::OnNodeCefCreated(CefCommandLine& args)
{
ModuleManager::Register(NCJS_BUILTIN_MODULE(MyModule));
}
Now you can access MyModule::Foo()
via Java Script:
ncjs.process.binding('my_module').foo();
Note: If your render process handler overrides any methods of CefRenderProcessHandler
, please remember to call the corresponding one of ncjs::RenderProcessHandler
's in your implementations, otherwise Node-CEF won't work.
To accompany general web pages and script, Node-CEF inject a global object identified by ncjs
to each frame in a sing web page and only will be load when this object get accessed first time, this also improve the performance hit for pages that do not use Node-CEF.
The global ncjs
object is main module of Node-CEF, all global objects (except the global
object) defined by Node.js are stored in this object, such as require
, process
, etc. You can define aliases for the objects inside ncjs
for convenience:
var require = ncjs.require;
Now you can use require
directive just like Node.js provides:
var mod = require('a/module');
The search paths for require()
in a web page is NOT relative to the *.js
file containing require()
directives but the page itself. This is because all scripts in a web page share a the same main module ncjs
which loaded by the web page.
Considering this folder structure:
./index.html
./path/to/general/java_script/code.js
./path/to/general/java_script/node_modules/my_module.js
./node_modules/my_module.js
while code.js:
var my_module = ncjs.require('my_module');
When index.html
loads code.js, the module located at ./node_modules/my_module.js
will be loaded but the ./path/to/general/java_script/node_modules/my_module.js
will be invisible to Node-CEF. Try test/require
for a completed test.
Note: All these changes above only apply to web pages, a Node.js module has its require
, exports
, etc, as well as search paths, nothing is changed for modules.
Because of the missing ArrayBuffer
and Uint8Array
supports from CEF, the subscripting operator buf[]
is not supported, use buf.get()
and buf.set()
to access buffer data.
- Event:
beforeExit
,rejectionHandled
andunhandledRejection
are not emitted. - Event:
uncaughtException
is emitted ifCefSettings::uncaught_exception_stack_size
> 0.
CEF 3 | Chromium | Linux | Mac | Windows |
---|---|---|---|---|
Branch 2704 | 51.0 | ? | ? | ? |
Branch 2623 | 49.0 | ? | ? | ? |
Branch 2526 | 47.0 | ? | ? | ? |
Branch 2454 | 45.0 | ? | ? | WORKS |
Branch 2357 | 43.0 | ? | ? | ? |
Branch 2272 | 41.0 | ? | ? | ? |
Branch 2171 | 39.0 | ? | ? | ? |
Branch 2062 | 37.0 | ? | ? | ? |
Branch 1916 | 35.0 | ? | ? | ? |
Branch 1750 | 33.0 | ? | ? | ? |
Branch 1650 | 31.0 | ? | ? | ? |
Branch 1547 | 29.0 | ? | ? | ? |
Branch 1453 | 27.0 | ? | ? | ? |
Please feedback us whether Node-CEF works with your CEF.
Reference / Porting API: Node.js v4.3.2
Node-CEF is licensed under the MIT license.
Joshua (Studio GPBeta) @2016