UNPKG

12.2 kBMarkdownView Raw
1# devtool
2
3[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges)
4
5Runs Node.js programs inside Chrome DevTools (using [Electron](https://github.com/atom/electron/)).
6
7```sh
8# runs a Node.js app in DevTools
9devtool src/app.js
10```
11
12This allows you to profile, debug and develop typical Node.js programs with some of the features of Chrome DevTools. See my blog post [Debugging Node.js With Chrome DevTools](http://mattdesl.svbtle.com/debugging-nodejs-in-chrome-devtools) for more details.
13
14The recording below shows setting breakpoints within an HTTP server.
15
16![movie](http://i.imgur.com/V4RQSZ2.gif)
17
18> *Note:* This tool is still in early stages. So far it has only been tested on a couple of OSX machines. :)
19
20## Install
21
22Install globally with `npm`.
23
24```sh
25npm install devtool -g
26```
27
28## Usage
29
30Run the command to open a new DevTools window.
31
32```txt
33Usage:
34 devtool [entry] [opts]
35
36Options:
37 --watch, -w enable file watching (for development)
38 --quit, -q quit application on fatal errors
39 --console, -c redirect console logs to terminal
40 --index, -i specify a different index.html file
41 --poll, -p enable polling when --watch is given
42 --show, -s show the browser window (default false)
43 --headless, -h do not open the DevTools window
44 --timeout, -t if specified, will close after X seconds
45 --break insert a breakpoint in entry point
46 --config a path to .devtoolrc config file
47 --verbose verbose Chromium logging
48 --version, -v log versions of underlying tools
49 --require, -r require path(s) before running entry
50 --browser-field, --bf resolve using "browser" field
51 --no-source-maps,
52 --no-sm disable source map generation
53 --no-node-timers,
54 --no-nt use browser timers
55 --no-browser-globals,
56 --no-bg removes window,document,navigator from required files
57```
58
59Examples:
60
61```sh
62# watch/dev a JS file, with a custom index.html
63devtool src/index.js --index index.html --watch
64
65# redirect console and pipe results to a file
66devtool main.js -q -c > foo.txt
67
68# open a REPL window
69devtool
70
71# pipe content into process.stdin
72devtool writer.js < README.md
73
74# pass clean arg list to app.js
75devtool app.js --watch -- entry
76
77# register with babel before requiring our app
78devtool -r babel-register app.js
79```
80
81You can specify `--watch` multiple times to watch different files/globs. If a custom `--index` is passed, it will also be watched for changes.
82
83If `--` is given, anything after it will be used as the arguments for the app's `process.argv`. This way you can avoid polluting your program arguments with those specific to `devtool`.
84
85The `--browser-field` or `--bf` makes the `require()` statements respect the [package.json `"browser"` field](https://gist.github.com/defunctzombie/4339901).
86
87The `--no-browser-globals` or `--no-bg` flag makes required modules behave a little more like Node, in that `window`, `navigator`, `document` and some other browser globals will be undefined in required files. Note: the console and REPL may still show some of these globals.
88
89### Advanced Configuration
90
91You can also specify advanced Electron/Node options in a `rc` configuration file, such as DevTools themes and V8 flags. See [rc configuration](./docs/rc-config.md) for more details.
92
93### Further Documentation
94
95See my blog post [Debugging Node.js With Chrome DevTools](http://mattdesl.svbtle.com/debugging-nodejs-in-chrome-devtools) for more details.
96
97## Use Cases
98
99### Debugging / Profiling
100
101For example, we can use this to profile and debug [browserify](https://github.com/substack/node-browserify), a node program that would not typically run inside Chrome DevTools. Here we use [`console.profile()`](https://developer.chrome.com/devtools/docs/console-api), a feature of Chrome.
102
103```js
104// build.js
105var browserify = require('browserify');
106
107// Start DevTools profiling...
108console.profile('build');
109
110// Bundle some browser application
111browserify('client.js').bundle(function (err, src) {
112 if (err) throw err;
113
114 // Finish DevTools profiling...
115 console.profileEnd('build');
116});
117```
118
119Now we can run `devtool` on our file:
120
121```sh
122devtool build.js
123```
124
125Some screenshots of the profiling and debugging experience:
126
127![profile](http://i.imgur.com/vSu7Lcz.png)
128
129![debug](http://i.imgur.com/O4DZHyv.png)
130
131> *Note:* Performance may vary between Node and Electron, so always take the results with a grain of salt!
132
133You can also set an initial breakpoint with the `--break` flag. This will insert a `debugger` statement (hidden behind source maps) at the start of your entry file. This way, you can add breakpoints without having to reload the program or manually add them to your source code.
134
135```sh
136# run app but break on start
137devtool src/index.js --break
138```
139
140### REPL
141
142We can also use the DevTools Console as a basic Node REPL with some nice additional features. The require statements will be relative to your current working directory. You can run the command without any entry file, like this:
143
144```sh
145devtool
146```
147
148![console](http://i.imgur.com/bnInBHA.png)
149
150When you don't specify an entry file, you can pipe JavaScript in to execute it in the browser. For example:
151
152```sh
153browserify client.js | devtool -c
154```
155
156### Browser APIs
157
158You can also mix Node modules with browser APIs, such as Canvas and WebGL. See [example/streetview.js](./example/streetview.js) and the respective script in [package.json](./package.json), which grabs a StreetView panorama with some [Google Client APIs](https://developers.google.com/discovery/libraries?hl=en) and writes the PNG image to `process.stdout`.
159
160For this, you may want to use the `--bf` or `--browser-field` flag so that modules like [nets](http://npmjs.com/package/nets) will use Web APIs where possible.
161
162Example:
163
164```sh
165devtool street.js --index street.html --quit --bf > street.png
166```
167
168Result:
169
170![street](http://i.imgur.com/GzqrTK2.png)
171
172> *Note:* For the output to drain correctly, we need to close the window *after* the buffer has been written.
173
174```js
175process.stdout.write(buffer, function () {
176 window.close();
177});
178```
179
180See [extract-streetview](https://github.com/Jam3/extract-streetview) for a practical implementation of this idea built on `devtool`.
181
182### Grunt/Gulp/Mocha
183
184To debug Grunt/Gulp/Mocha and other commands, you will need to pass the JavaScript file that runs them. You should also include `--` to avoid any argument conflicts.
185
186```sh
187# same as "gulp watch"
188devtool node_modules/gulp/bin/gulp.js -c -- watch
189
190# same as "grunt"
191devtool node_modules/grunt-cli/bin/grunt -c --
192
193# run a mocha test
194devtool node_modules/mocha/bin/_mocha -qc -- ./tests/my-spec.js
195```
196
197### Other Examples
198
199See the [example/](./example/) folder for more ideas, and the [package.json](./package.json) scripts which run them.
200
201- [example/markdown.js](./example/markdown.js) - Pipes a `.md` file into `process.stdin`, then renders GitHub Flavored Markdown to a PNG image
202- [example/es2015.js](./example/es2015.js) - ES2015 transpiling
203- [example/geolocate.js](./example/geolocate.js) - prints current `[ latitude, longitude ]` to `stdout`
204- [example/http.js](./example/http.js) - a simple Node.js server that you can throw break points into
205- [example/tape-browser.js](./example/tape-browser.js) - demonstrates piping JavaScript directly into devtool, e.g. for browser testing
206
207Also see [devtool-examples](https://github.com/Jam3/devtool-examples) for more ideas.
208
209## Features
210
211This is built on [Electron](https://github.com/atom/electron/), so it includes the Console, Profile, Debugger, etc.
212
213It also includes some additional features on top of Electron:
214
215- Improved error handling (more detailed syntax errors in console)
216- Improved source map support for required files
217- Makes various Node features behave as expected, like `require.main`, `process.argv`, `process.stdin` and [timers](https://nodejs.org/api/timers.html)
218- Console redirection back to terminal (optional)
219- File watching for development and quit-on-error flags for unit testing (e.g. continuous integration)
220- Handles `process.exit` and error codes
221- Supports `"browser"` field resolution (optional)
222- Can hide browser globals (like `window` and `navigator`) for better compatibility with Node.js modules (optional)
223- Supports config files for V8 flags, color themes, and other options
224
225## Gotchas
226
227Since this is running in Electron and Chromium, instead of Node, you might run into some oddities and gotchas.
228
229- `window` and other browser APIs are present; this may affect modules using these globals to detect Browser/Node environments
230 - The `--no-browser-globals` may help mitigate these issues
231- You must call `window.close()` to stop the process; apps will not quit on their own
232- If a native module does not work, you may need to [rebuild it for the right version of Electron](http://electron.atom.io/docs/v0.36.0/tutorial/using-native-node-modules/)
233- If you want to close or exit after writing to stderr/stdout, you should do so after a callback: `outStream.write(buf, callback)`
234- `setTimeout`, `setInterval` and related functions are shimmed for better compatibility with [Node.js `timers`](https://nodejs.org/api/timers.html)
235- `process.stdin` does not work in Windows shells, see [this Electron issue](https://github.com/electron/electron/issues/4218)
236
237## Roadmap / Contributing
238
239This project is experimental and has not been tested on a wide range of applications or Node/OS environments. If you want to help, please open an issue or submit a PR. Some outstanding areas to explore:
240
241- Improving syntax error handling, e.g. adding it to Sources panel
242- Exposing an API for programmatic usage
243- Exploring native addons
244- Testing against a wide range of Node.js applications and modules
245
246You can `git clone` and `npm install` this repo to start working from source. Type `npm run` to list all available commands.
247
248## See Also / Comparisons
249### `hihat`
250
251If you like this, you might also like [hihat](https://github.com/Jam3/hihat). It is very similar, but more focused on running and testing *browser* applications. Hihat uses [browserify](https://www.npmjs.com/package/browserify) to bundle everything into a *single* source file, and uses [watchify](https://www.npmjs.com/package/watchify) for incremental file changes.
252
253In some ways, `devtool` is a spiritual successor to `hihat`. The architecture is cleaner and better suited for large Node/Electron applications.
254
255### `iron-node`
256
257Another Electron-based debugger is [iron-node](https://github.com/s-a/iron-node). `iron-node` includes better support for native addons and a complex graphical interface that shows your `package.json` and `README.md`.
258
259Whereas `devtool` is more focused on the command-line, Unix-style piping/redirection, and Electron/Browser APIs for interesting use-cases (e.g. [Google StreetView](#browser-apis)).
260
261`devtool` shims various features to behave more like Node.js (like `require.main` and `process.exit`) and overrides the internal `require` mechanism for source maps, improved error handling and `"browser"` field resolution.
262
263### `node-inspector`
264
265You may also like [node-inspector](https://github.com/node-inspector/node-inspector), which uses remote debugging instead of building on top of Electron.
266
267This means your code will run in a true Node environment, without any `window` or other Browser/Electron APIs that may pollute scope and cause problems with certain modules. It has stronger support for large Node.js applications (i.e. native addons) and more control over the DevTools instance (i.e. can inject breakpoints and support Network requests).
268
269However, since it re-implements much of the debugging experience, it may feel clunky and fragile compared to developing inside the latest Chrome DevTools (e.g. `console.profile()` does not exist).
270
271Whereas `devtool` aims to make the experience feel more familiar to those coming from Chrome DevTools, and also promotes other features like Browser/Electron APIs.
272
273## License
274
275MIT, see [LICENSE.md](http://github.com/Jam3/devtool/blob/master/LICENSE.md) for details.