Updates from Tuesday, March 3rd

- [ReactNative] Fix OSS Projects | Spencer Ahrens <sahrens@fb.com>
- [react-packager] check-in node_modules and update tests | Amjad Masad <amasad@fb.com>
- [react-packager] Cleanup package.json | Amjad Masad <amasad@fb.com>
- [react-packager] Implement bundle minification | Amjad Masad <amasad@fb.com>
- [react-packager] Add dev option to CLI | James Ide | Amjad Masad <amasad@fb.com>
- [react-packager] Add uglify-js library | Amjad Masad <amasad@fb.com>
- [f8] Make map zoomable on double-tap | Alex Kotliarskyi <frantic@fb.com>
This commit is contained in:
Spencer Ahrens 2015-03-03 08:38:50 -08:00
parent 9dd01d4a17
commit f76e0b593d
6 changed files with 74 additions and 11 deletions

View File

@ -29,6 +29,10 @@ var options = parseCommandLine([{
}, { }, {
command: 'root', command: 'root',
description: 'add another root(s) to be used by the packager in this project', description: 'add another root(s) to be used by the packager in this project',
}, {
command: 'dev',
default: true,
description: 'produce development packages with extra warnings enabled',
}]); }]);
if (!options.projectRoots) { if (!options.projectRoots) {
@ -93,7 +97,7 @@ function openStackFrameInEditor(req, res, next) {
function getAppMiddleware(options) { function getAppMiddleware(options) {
return ReactPackager.middleware({ return ReactPackager.middleware({
dev: true, dev: options.dev,
projectRoots: options.projectRoots, projectRoots: options.projectRoots,
blacklistRE: blacklist(false), blacklistRE: blacklist(false),
cacheVersion: '2', cacheVersion: '2',

View File

@ -2,6 +2,7 @@
var _ = require('underscore'); var _ = require('underscore');
var base64VLQ = require('./base64-vlq'); var base64VLQ = require('./base64-vlq');
var UglifyJS = require('uglify-js');
module.exports = Package; module.exports = Package;
@ -27,6 +28,7 @@ Package.prototype.addModule = function(
}; };
Package.prototype.finalize = function(options) { Package.prototype.finalize = function(options) {
options = options || {};
if (options.runMainModule) { if (options.runMainModule) {
var runCode = ';require("' + this._mainModuleId + '");'; var runCode = ';require("' + this._mainModuleId + '");';
this.addModule( this.addModule(
@ -40,12 +42,49 @@ Package.prototype.finalize = function(options) {
Object.seal(this._modules); Object.seal(this._modules);
}; };
Package.prototype.getSource = function() { Package.prototype.getSource = function(options) {
return this._source || ( if (!this._source) {
this._source = _.pluck(this._modules, 'transformedCode').join('\n') + '\n' + options = options || {};
'RAW_SOURCE_MAP = ' + JSON.stringify(this.getSourceMap({excludeSource: true})) + this._source = _.pluck(this._modules, 'transformedCode').join('\n');
';\n' + '\/\/@ sourceMappingURL=' + this._sourceMapUrl if (options.inlineSourceMap) {
); var sourceMap = this.getSourceMap({excludeSource: true});
this._source += '\nRAW_SOURCE_MAP = ' + JSON.stringify(sourceMap) + ';';
}
this._source += '\n\/\/@ sourceMappingURL=' + this._sourceMapUrl;
}
return this._source;
};
Package.prototype.getMinifiedSourceAndMap = function() {
var source = this.getSource({inlineSourceMap: false});
try {
return UglifyJS.minify(source, {
fromString: true,
outSourceMap: 'bundle.js',
inSourceMap: this.getSourceMap(),
});
} catch(e) {
// Sometimes, when somebody is using a new syntax feature that we
// don't yet have transform for, the untransformed line is sent to
// uglify, and it chokes on it. This code tries to print the line
// and the module for easier debugging
var errorMessage = 'Error while minifying JS\n';
if (e.line) {
errorMessage += 'Transformed code line: "' +
source.split('\n')[e.line - 1] + '"\n';
}
if (e.pos) {
var fromIndex = source.lastIndexOf('__d(\'', e.pos);
if (fromIndex > -1) {
fromIndex += '__d(\''.length;
var toIndex = source.indexOf('\'', fromIndex);
errorMessage += 'Module name (best guess): ' +
source.substring(fromIndex, toIndex) + '\n';
}
}
errorMessage += e.toString();
throw new Error(errorMessage);
}
}; };
Package.prototype.getSourceMap = function(options) { Package.prototype.getSourceMap = function(options) {

View File

@ -21,7 +21,7 @@ describe('Package', function() {
ppackage.addModule('transformed foo;', 'source foo', 'foo path'); ppackage.addModule('transformed foo;', 'source foo', 'foo path');
ppackage.addModule('transformed bar;', 'source bar', 'bar path'); ppackage.addModule('transformed bar;', 'source bar', 'bar path');
ppackage.finalize({}); ppackage.finalize({});
expect(ppackage.getSource()).toBe([ expect(ppackage.getSource({inlineSourceMap: true})).toBe([
'transformed foo;', 'transformed foo;',
'transformed bar;', 'transformed bar;',
'RAW_SOURCE_MAP = "test-source-map";', 'RAW_SOURCE_MAP = "test-source-map";',
@ -34,7 +34,7 @@ describe('Package', function() {
ppackage.addModule('transformed bar;', 'source bar', 'bar path'); ppackage.addModule('transformed bar;', 'source bar', 'bar path');
ppackage.setMainModuleId('foo'); ppackage.setMainModuleId('foo');
ppackage.finalize({runMainModule: true}); ppackage.finalize({runMainModule: true});
expect(ppackage.getSource()).toBe([ expect(ppackage.getSource({inlineSourceMap: true})).toBe([
'transformed foo;', 'transformed foo;',
'transformed bar;', 'transformed bar;',
';require("foo");', ';require("foo");',
@ -42,6 +42,21 @@ describe('Package', function() {
'\/\/@ sourceMappingURL=test_url', '\/\/@ sourceMappingURL=test_url',
].join('\n')); ].join('\n'));
}); });
it('should get minified source', function() {
var minified = {
code: 'minified',
map: 'map',
};
require('uglify-js').minify = function() {
return minified;
};
ppackage.addModule('transformed foo;', 'source foo', 'foo path');
ppackage.finalize();
expect(ppackage.getMinifiedSourceAndMap()).toBe(minified);
});
}); });
describe('sourcemap package', function() { describe('sourcemap package', function() {

View File

@ -6,6 +6,7 @@ jest
.dontMock('q') .dontMock('q')
.dontMock('os') .dontMock('os')
.dontMock('underscore') .dontMock('underscore')
.setMock('uglify-js')
.dontMock('../'); .dontMock('../');
var q = require('q'); var q = require('q');

View File

@ -10,6 +10,7 @@ jest.setMock('worker-farm', function() { return function() {}; })
return setTimeout(fn, 0); return setTimeout(fn, 0);
} }
}) })
.setMock('uglify-js')
.dontMock('../'); .dontMock('../');
var q = require('q'); var q = require('q');

View File

@ -51,6 +51,7 @@ var validateOpts = declareOpts({
function Server(options) { function Server(options) {
var opts = validateOpts(options); var opts = validateOpts(options);
this._dev = opts.dev;
this._projectRoots = opts.projectRoots; this._projectRoots = opts.projectRoots;
this._packages = Object.create(null); this._packages = Object.create(null);
this._packager = new Packager(opts); this._packager = new Packager(opts);
@ -72,13 +73,14 @@ Server.prototype._onFileChange = function(type, filepath, root) {
}; };
Server.prototype._rebuildPackages = function() { Server.prototype._rebuildPackages = function() {
var dev = this._dev;
var buildPackage = this._buildPackage.bind(this); var buildPackage = this._buildPackage.bind(this);
var packages = this._packages; var packages = this._packages;
Object.keys(packages).forEach(function(key) { Object.keys(packages).forEach(function(key) {
var options = getOptionsFromPath(url.parse(key).pathname); var options = getOptionsFromPath(url.parse(key).pathname);
packages[key] = buildPackage(options).then(function(p) { packages[key] = buildPackage(options).then(function(p) {
// Make a throwaway call to getSource to cache the source string. // Make a throwaway call to getSource to cache the source string.
p.getSource(); p.getSource({inlineSourceMap: dev});
return p; return p;
}); });
}); });
@ -159,10 +161,11 @@ Server.prototype.processRequest = function(req, res, next) {
var options = getOptionsFromPath(url.parse(req.url).pathname); var options = getOptionsFromPath(url.parse(req.url).pathname);
var building = this._packages[req.url] || this._buildPackage(options); var building = this._packages[req.url] || this._buildPackage(options);
this._packages[req.url] = building; this._packages[req.url] = building;
var dev = this._dev;
building.then( building.then(
function(p) { function(p) {
if (requestType === 'bundle') { if (requestType === 'bundle') {
res.end(p.getSource()); res.end(p.getSource({inlineSourceMap: dev}));
Activity.endEvent(startReqEventId); Activity.endEvent(startReqEventId);
} else if (requestType === 'map') { } else if (requestType === 'map') {
res.end(JSON.stringify(p.getSourceMap())); res.end(JSON.stringify(p.getSourceMap()));