2015-02-09 updates
[react-packager] Update other instances of projectRoot to projectRoots | Amjad Masad [react-packager] Debug page | Amjad Masad
This commit is contained in:
parent
3e59937fa9
commit
5aa5e7a875
27
README.md
27
README.md
|
@ -34,12 +34,9 @@ products with no compromises in quality or capability.
|
||||||
Get up and running with our Movies sample app:
|
Get up and running with our Movies sample app:
|
||||||
|
|
||||||
1. Once you have the repo cloned and met all the requirements above, start the
|
1. Once you have the repo cloned and met all the requirements above, start the
|
||||||
packager that will transform your JS code on-the-fly:
|
packager that will transform your JS code on-the-fly:
|
||||||
|
`npm install`
|
||||||
```
|
`npm start`
|
||||||
npm install
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
2. Open the `Examples/Movies/Movies.xcodeproj` project in Xcode.
|
2. Open the `Examples/Movies/Movies.xcodeproj` project in Xcode.
|
||||||
3. Make sure the target is set to `Movies` and that you have an iOS simulator
|
3. Make sure the target is set to `Movies` and that you have an iOS simulator
|
||||||
selected to run the app.
|
selected to run the app.
|
||||||
|
@ -96,27 +93,27 @@ the responder system.
|
||||||
|
|
||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
##### Q. How does debugging work? Can I set breakpoints in my JS?
|
Q. How does debugging work? Can I set breakpoints in my JS?
|
||||||
A. We are going to add the ability to use the Chrome developer tools soon. We
|
A. We are going to add the ability to use the Chrome developer tools soon. We
|
||||||
are very passionate about building the best possible developer experience.
|
are very passionate about building the best possible developer experience.
|
||||||
|
|
||||||
##### Q. When is this coming to Android/Windows/OS X/etc?
|
Q. When is this coming to Android/Windows/OS X/etc?
|
||||||
A. We're working on Android, and we are excited to release it as soon as we can.
|
A. We're working on Android, and we are excited to release it as soon as we can.
|
||||||
We are looking forward to the community helping us target other platforms as
|
We are looking forward to the community helping us target other platforms as
|
||||||
well :)
|
well :)
|
||||||
|
|
||||||
##### Q. How do I create my own app?
|
Q. How do I create my own app?
|
||||||
A. Copy the entire `Examples/TicTacToe` folder, rename stuff in Xcode, and
|
A. Copy the entire `Examples/TicTacToe` folder, rename stuff in Xcode, and
|
||||||
replace the `TicTacToeApp.js` with your own. Then, in `AppDelegate.m`, update
|
replace the `TicTacToeApp.js` with your own. Then, in `AppDelegate.m`, update
|
||||||
`moduleName` to match your call to
|
`moduleName` to match your call to
|
||||||
`Bundler.registerComponent(<moduleName>, <componentName>)` at the bottom of your
|
`Bundler.registerComponent(<moduleName>, <componentName>)` at the bottom of your
|
||||||
JS file, and update `jsCodeLocation` to match your JS file name and location.
|
JS file, and update `jsCodeLocation` to match your JS file name and location.
|
||||||
|
|
||||||
##### Q. Can I submit my own React Native app to the App Store?
|
Q. Can I submit my own React Native app to the App Store?
|
||||||
A. Not yet, but you will be able to soon. If you build something you want to
|
A. Not yet, but you will be able to soon. If you build something you want to
|
||||||
submit to the App Store, come talk to us ASAP.
|
submit to the App Store, come talk to us ASAP.
|
||||||
|
|
||||||
##### Q. How do I deploy to my device?
|
Q. How do I deploy to my device?
|
||||||
A. You can change `localhost` in `AppDelegate.m` to your laptop's IP address and
|
A. You can change `localhost` in `AppDelegate.m` to your laptop's IP address and
|
||||||
grab the bundle over the same Wi-Fi network. You can also download the bundle
|
grab the bundle over the same Wi-Fi network. You can also download the bundle
|
||||||
that the React packager generates, save it to the file `main.jsbundle`, and add it
|
that the React packager generates, save it to the file `main.jsbundle`, and add it
|
||||||
|
@ -124,20 +121,20 @@ as a static resource in your Xcode project. Then set the `jsCodeLocation` in
|
||||||
`AppDelegate.m` to point to that file and deploy to your device like you would
|
`AppDelegate.m` to point to that file and deploy to your device like you would
|
||||||
any other app.
|
any other app.
|
||||||
|
|
||||||
##### Q. What's up with this private repo? Why aren't you just open sourcing it now?
|
Q. What's up with this private repo? Why aren't you just open sourcing it now?
|
||||||
A. We want input from the React community before we open the floodgates so we
|
A. We want input from the React community before we open the floodgates so we
|
||||||
can incorporate your feedback, and we also have a bunch more features we want to
|
can incorporate your feedback, and we also have a bunch more features we want to
|
||||||
add to make a more complete offering before we open source.
|
add to make a more complete offering before we open source.
|
||||||
|
|
||||||
##### Q. Do you have to ship a JS runtime with your apps?
|
Q. Do you have to ship a JS runtime with your apps?
|
||||||
A. No, we just use the JavaScriptCore public API that is part of iOS 7 and
|
A. No, we just use the JavaScriptCore public API that is part of iOS 7 and
|
||||||
later.
|
later.
|
||||||
|
|
||||||
##### Q. How do I add more native capabilities?
|
Q. How do I add more native capabilities?
|
||||||
A. React Native is designed to be extensible - come talk to us, we would love to
|
A. React Native is designed to be extensible - come talk to us, we would love to
|
||||||
work with you.
|
work with you.
|
||||||
|
|
||||||
##### Q. Can I reuse existing iOS code?
|
Q. Can I reuse existing iOS code?
|
||||||
A. Yes, React Native is designed to be extensible and allow integration of all
|
A. Yes, React Native is designed to be extensible and allow integration of all
|
||||||
sorts of native components, such as `UINavigationController` (available as
|
sorts of native components, such as `UINavigationController` (available as
|
||||||
`<NavigatorIOS>`), `MKMapView` (not available yet), or your own custom
|
`<NavigatorIOS>`), `MKMapView` (not available yet), or your own custom
|
||||||
|
|
|
@ -81,7 +81,7 @@ function openStackFrameInEditor(req, res, next) {
|
||||||
function getAppMiddleware(options) {
|
function getAppMiddleware(options) {
|
||||||
return ReactPackager.middleware({
|
return ReactPackager.middleware({
|
||||||
dev: true,
|
dev: true,
|
||||||
projectRoot: options.projectRoot,
|
projectRoots: options.projectRoots,
|
||||||
blacklistRE: blacklist(false),
|
blacklistRE: blacklist(false),
|
||||||
cacheVersion: '2',
|
cacheVersion: '2',
|
||||||
polyfillModuleNames: [
|
polyfillModuleNames: [
|
||||||
|
@ -98,9 +98,13 @@ function runServer(
|
||||||
var app = connect()
|
var app = connect()
|
||||||
.use(loadRawBody)
|
.use(loadRawBody)
|
||||||
.use(openStackFrameInEditor)
|
.use(openStackFrameInEditor)
|
||||||
.use(getAppMiddleware(options))
|
.use(getAppMiddleware(options));
|
||||||
.use(connect.static(options.projectRoot))
|
|
||||||
.use(connect.logger())
|
options.projectRoots.forEach(function(root) {
|
||||||
|
app.use(connect.static(root));
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(connect.logger())
|
||||||
.use(connect.compress())
|
.use(connect.compress())
|
||||||
.use(connect.errorHandler());
|
.use(connect.errorHandler());
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ var docblock = require('./docblock');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var isAbsolutePath = require('absolute-path');
|
var isAbsolutePath = require('absolute-path');
|
||||||
var debug = require('debug')('DependecyGraph');
|
var debug = require('debug')('DependecyGraph');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
var readFile = q.nfbind(fs.readFile);
|
var readFile = q.nfbind(fs.readFile);
|
||||||
var readDir = q.nfbind(fs.readdir);
|
var readDir = q.nfbind(fs.readdir);
|
||||||
|
@ -22,6 +23,7 @@ function DependecyGraph(options) {
|
||||||
this._packageByRoot = Object.create(null);
|
this._packageByRoot = Object.create(null);
|
||||||
this._packagesById = Object.create(null);
|
this._packagesById = Object.create(null);
|
||||||
this._moduleById = Object.create(null);
|
this._moduleById = Object.create(null);
|
||||||
|
this._debugUpdateEvents = [];
|
||||||
this._fileWatcher = options.fileWatcher;
|
this._fileWatcher = options.fileWatcher;
|
||||||
|
|
||||||
// Kick off the search process to precompute the dependency graph.
|
// Kick off the search process to precompute the dependency graph.
|
||||||
|
@ -196,16 +198,20 @@ DependecyGraph.prototype._search = function() {
|
||||||
return readDir(dir)
|
return readDir(dir)
|
||||||
.then(function(files){
|
.then(function(files){
|
||||||
return q.all(files.map(function(filePath) {
|
return q.all(files.map(function(filePath) {
|
||||||
return realpath(path.join(dir, filePath));
|
return realpath(path.join(dir, filePath)).catch(handleBrokenLink);
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
.then(function(filePaths) {
|
.then(function(filePaths) {
|
||||||
filePaths = filePaths.filter(function(filePath) {
|
filePaths = filePaths.filter(function(filePath) {
|
||||||
|
if (filePath == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return !self._ignoreFilePath(filePath);
|
return !self._ignoreFilePath(filePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
var statsP = filePaths.map(function(filePath) {
|
var statsP = filePaths.map(function(filePath) {
|
||||||
return lstat(filePath);
|
return lstat(filePath).catch(handleBrokenLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -397,6 +403,8 @@ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._debugUpdateEvents.push({event: eventType, path: filePath});
|
||||||
|
|
||||||
if (eventType === 'delete') {
|
if (eventType === 'delete') {
|
||||||
var module = this._graph[absPath];
|
var module = this._graph[absPath];
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
|
@ -412,6 +420,13 @@ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DependecyGraph.prototype.getDebugInfo = function() {
|
||||||
|
return '<h1>FileWatcher Update Events</h1>' +
|
||||||
|
'<pre>' + util.inspect(this._debugUpdateEvents) + '</pre>' +
|
||||||
|
'<h1> Graph dump </h1>' +
|
||||||
|
'<pre>' + util.inspect(this._graph) + '</pre>';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches all roots for the file and returns the first one that has file of the same path.
|
* Searches all roots for the file and returns the first one that has file of the same path.
|
||||||
*/
|
*/
|
||||||
|
@ -471,4 +486,9 @@ function withExtJs(file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleBrokenLink(e) {
|
||||||
|
debug('WARNING: error stating, possibly broken symlink', e.message);
|
||||||
|
return q();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = DependecyGraph;
|
module.exports = DependecyGraph;
|
||||||
|
|
|
@ -119,8 +119,13 @@ HasteDependencyResolver.prototype.wrapModule = function(module, code) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
HasteDependencyResolver.prototype.end = function() {
|
HasteDependencyResolver.prototype.end = function() {
|
||||||
return this._fileWatcher.end();
|
return this._fileWatcher.end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HasteDependencyResolver.prototype.getDebugInfo = function() {
|
||||||
|
return this._depGraph.getDebugInfo();
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = HasteDependencyResolver;
|
module.exports = HasteDependencyResolver;
|
||||||
|
|
|
@ -108,3 +108,25 @@ Package.prototype._getMappings = function() {
|
||||||
}
|
}
|
||||||
return mappings;
|
return mappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Package.prototype.getDebugInfo = function() {
|
||||||
|
return [
|
||||||
|
'<div><h3>Main Module:</h3> ' + this._mainModuleId + '</div>',
|
||||||
|
'<style>',
|
||||||
|
'pre.collapsed {',
|
||||||
|
' height: 10px;',
|
||||||
|
' width: 100px;',
|
||||||
|
' display: block;',
|
||||||
|
' text-overflow: ellipsis;',
|
||||||
|
' overflow: hidden;',
|
||||||
|
' cursor: pointer;',
|
||||||
|
'}',
|
||||||
|
'</style>',
|
||||||
|
'<h3> Module paths and transformed code: </h3>',
|
||||||
|
this._modules.map(function(m) {
|
||||||
|
return '<div> <h4> Path: </h4>' + m.sourcePath + '<br/> <h4> Source: </h4>' +
|
||||||
|
'<code><pre class="collapsed" onclick="this.classList.remove(\'collapsed\')">' +
|
||||||
|
_.escape(m.transformedCode) + '</pre></code></div>';
|
||||||
|
}).join('\n'),
|
||||||
|
].join('\n');
|
||||||
|
};
|
||||||
|
|
|
@ -117,9 +117,15 @@ Packager.prototype._transformModule = function(module) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function verifyRootExists(root) {
|
function verifyRootExists(root) {
|
||||||
// Verify that the root exists.
|
// Verify that the root exists.
|
||||||
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Packager.prototype.getGraphDebugInfo = function() {
|
||||||
|
return this._resolver.getDebugInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = Packager;
|
module.exports = Packager;
|
||||||
|
|
|
@ -144,6 +144,7 @@ describe('processRequest', function(){
|
||||||
expect(response).toEqual("this is the first source");
|
expect(response).toEqual("this is the first source");
|
||||||
expect(packageFunc.mock.calls.length).toBe(1);
|
expect(packageFunc.mock.calls.length).toBe(1);
|
||||||
triggerFileChange('all','path/file.js', options.projectRoots[0]);
|
triggerFileChange('all','path/file.js', options.projectRoots[0]);
|
||||||
|
jest.runAllTimers();
|
||||||
})
|
})
|
||||||
.then(function(){
|
.then(function(){
|
||||||
expect(packageFunc.mock.calls.length).toBe(2);
|
expect(packageFunc.mock.calls.length).toBe(2);
|
||||||
|
|
|
@ -67,12 +67,49 @@ Server.prototype.buildPackageFromUrl = function(reqUrl) {
|
||||||
return this._buildPackage(options);
|
return this._buildPackage(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Server.prototype._processDebugRequest = function(reqUrl, res) {
|
||||||
|
var ret = '<!doctype html>';
|
||||||
|
var pathname = url.parse(reqUrl).pathname;
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 1) {
|
||||||
|
ret += '<div><a href="/debug/packages">Cached Packages</a></div>';
|
||||||
|
ret += '<div><a href="/debug/graph">Dependency Graph</a></div>';
|
||||||
|
res.end(ret);
|
||||||
|
} else if (parts[1] === 'packages') {
|
||||||
|
ret += '<h1> Cached Packages </h1>';
|
||||||
|
q.all(Object.keys(this._packages).map(function(url) {
|
||||||
|
return this._packages[url].then(function(p) {
|
||||||
|
ret += '<div><h2>' + url + '</h2>';
|
||||||
|
ret += p.getDebugInfo();
|
||||||
|
});
|
||||||
|
}, this)).then(
|
||||||
|
function() { res.end(ret); },
|
||||||
|
function(e) {
|
||||||
|
res.wrteHead(500);
|
||||||
|
res.end('Internal Error');
|
||||||
|
console.log(e.stack);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else if (parts[1] === 'graph'){
|
||||||
|
ret += '<h1> Dependency Graph </h2>';
|
||||||
|
ret += this._packager.getGraphDebugInfo();
|
||||||
|
res.end(ret);
|
||||||
|
} else {
|
||||||
|
res.writeHead('404');
|
||||||
|
res.end('Invalid debug request');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Server.prototype.processRequest = function(req, res, next) {
|
Server.prototype.processRequest = function(req, res, next) {
|
||||||
var requestType;
|
var requestType;
|
||||||
if (req.url.match(/\.bundle$/)) {
|
if (req.url.match(/\.bundle$/)) {
|
||||||
requestType = 'bundle';
|
requestType = 'bundle';
|
||||||
} else if (req.url.match(/\.map$/)) {
|
} else if (req.url.match(/\.map$/)) {
|
||||||
requestType = 'map';
|
requestType = 'map';
|
||||||
|
} else if (req.url.match(/^\/debug/)) {
|
||||||
|
this._processDebugRequest(req.url, res);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue