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
25
README.md
25
README.md
|
@ -35,11 +35,8 @@ Get up and running with our Movies sample app:
|
|||
|
||||
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:
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
`npm install`
|
||||
`npm start`
|
||||
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
|
||||
selected to run the app.
|
||||
|
@ -96,27 +93,27 @@ the responder system.
|
|||
|
||||
# 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
|
||||
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.
|
||||
We are looking forward to the community helping us target other platforms as
|
||||
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
|
||||
replace the `TicTacToeApp.js` with your own. Then, in `AppDelegate.m`, update
|
||||
`moduleName` to match your call to
|
||||
`Bundler.registerComponent(<moduleName>, <componentName>)` at the bottom of your
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
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.
|
||||
|
||||
##### 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
|
||||
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
|
||||
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
|
||||
sorts of native components, such as `UINavigationController` (available as
|
||||
`<NavigatorIOS>`), `MKMapView` (not available yet), or your own custom
|
||||
|
|
|
@ -81,7 +81,7 @@ function openStackFrameInEditor(req, res, next) {
|
|||
function getAppMiddleware(options) {
|
||||
return ReactPackager.middleware({
|
||||
dev: true,
|
||||
projectRoot: options.projectRoot,
|
||||
projectRoots: options.projectRoots,
|
||||
blacklistRE: blacklist(false),
|
||||
cacheVersion: '2',
|
||||
polyfillModuleNames: [
|
||||
|
@ -98,9 +98,13 @@ function runServer(
|
|||
var app = connect()
|
||||
.use(loadRawBody)
|
||||
.use(openStackFrameInEditor)
|
||||
.use(getAppMiddleware(options))
|
||||
.use(connect.static(options.projectRoot))
|
||||
.use(connect.logger())
|
||||
.use(getAppMiddleware(options));
|
||||
|
||||
options.projectRoots.forEach(function(root) {
|
||||
app.use(connect.static(root));
|
||||
});
|
||||
|
||||
app.use(connect.logger())
|
||||
.use(connect.compress())
|
||||
.use(connect.errorHandler());
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ var docblock = require('./docblock');
|
|||
var path = require('path');
|
||||
var isAbsolutePath = require('absolute-path');
|
||||
var debug = require('debug')('DependecyGraph');
|
||||
var util = require('util');
|
||||
|
||||
var readFile = q.nfbind(fs.readFile);
|
||||
var readDir = q.nfbind(fs.readdir);
|
||||
|
@ -22,6 +23,7 @@ function DependecyGraph(options) {
|
|||
this._packageByRoot = Object.create(null);
|
||||
this._packagesById = Object.create(null);
|
||||
this._moduleById = Object.create(null);
|
||||
this._debugUpdateEvents = [];
|
||||
this._fileWatcher = options.fileWatcher;
|
||||
|
||||
// Kick off the search process to precompute the dependency graph.
|
||||
|
@ -196,16 +198,20 @@ DependecyGraph.prototype._search = function() {
|
|||
return readDir(dir)
|
||||
.then(function(files){
|
||||
return q.all(files.map(function(filePath) {
|
||||
return realpath(path.join(dir, filePath));
|
||||
return realpath(path.join(dir, filePath)).catch(handleBrokenLink);
|
||||
}));
|
||||
})
|
||||
.then(function(filePaths) {
|
||||
filePaths = filePaths.filter(function(filePath) {
|
||||
if (filePath == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !self._ignoreFilePath(filePath);
|
||||
});
|
||||
|
||||
var statsP = filePaths.map(function(filePath) {
|
||||
return lstat(filePath);
|
||||
return lstat(filePath).catch(handleBrokenLink);
|
||||
});
|
||||
|
||||
return [
|
||||
|
@ -397,6 +403,8 @@ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root
|
|||
return;
|
||||
}
|
||||
|
||||
this._debugUpdateEvents.push({event: eventType, path: filePath});
|
||||
|
||||
if (eventType === 'delete') {
|
||||
var module = this._graph[absPath];
|
||||
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.
|
||||
*/
|
||||
|
@ -471,4 +486,9 @@ function withExtJs(file) {
|
|||
}
|
||||
}
|
||||
|
||||
function handleBrokenLink(e) {
|
||||
debug('WARNING: error stating, possibly broken symlink', e.message);
|
||||
return q();
|
||||
}
|
||||
|
||||
module.exports = DependecyGraph;
|
||||
|
|
|
@ -119,8 +119,13 @@ HasteDependencyResolver.prototype.wrapModule = function(module, code) {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
HasteDependencyResolver.prototype.end = function() {
|
||||
return this._fileWatcher.end();
|
||||
};
|
||||
|
||||
HasteDependencyResolver.prototype.getDebugInfo = function() {
|
||||
return this._depGraph.getDebugInfo();
|
||||
};
|
||||
|
||||
module.exports = HasteDependencyResolver;
|
||||
|
|
|
@ -108,3 +108,25 @@ Package.prototype._getMappings = function() {
|
|||
}
|
||||
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) {
|
||||
// Verify that the root exists.
|
||||
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
||||
}
|
||||
|
||||
Packager.prototype.getGraphDebugInfo = function() {
|
||||
return this._resolver.getDebugInfo();
|
||||
};
|
||||
|
||||
|
||||
module.exports = Packager;
|
||||
|
|
|
@ -144,6 +144,7 @@ describe('processRequest', function(){
|
|||
expect(response).toEqual("this is the first source");
|
||||
expect(packageFunc.mock.calls.length).toBe(1);
|
||||
triggerFileChange('all','path/file.js', options.projectRoots[0]);
|
||||
jest.runAllTimers();
|
||||
})
|
||||
.then(function(){
|
||||
expect(packageFunc.mock.calls.length).toBe(2);
|
||||
|
|
|
@ -67,12 +67,49 @@ Server.prototype.buildPackageFromUrl = function(reqUrl) {
|
|||
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) {
|
||||
var requestType;
|
||||
if (req.url.match(/\.bundle$/)) {
|
||||
requestType = 'bundle';
|
||||
} else if (req.url.match(/\.map$/)) {
|
||||
requestType = 'map';
|
||||
} else if (req.url.match(/^\/debug/)) {
|
||||
this._processDebugRequest(req.url, res);
|
||||
return;
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue