Bug 1188509-Bundle Hello standalone JS for performance, r=Standard8

This commit is contained in:
Dan Mosedale 2015-09-28 13:18:22 -07:00
parent 70030d1018
commit d33a347593
8 changed files with 163 additions and 39 deletions

View File

@ -27,3 +27,6 @@ content/shared/js/views.js
standalone/content/js/standaloneRoomViews.js
standalone/content/js/webapp.js
ui/ui-showcase.js
# Don't need to check the built tree
standalone/dist

View File

@ -3,3 +3,4 @@ node_modules
*.pyc
content/config.js
content/VERSION.txt
dist

View File

@ -21,6 +21,23 @@ install: npm_install
npm_install:
@npm install
# build the dist dir, which contains a production version of the code and
# assets
.PHONY: dist
dist:
cp -pr content dist
$(NODE_LOCAL_BIN)/webpack -v --display-errors
sed 's#webappEntryPoint.js#js/standalone.js#' \
< content/index.html > dist/index.html
.PHONY: distclean
distclean:
rm -fr dist
.PHONY: distserver
distserver: remove_old_config dist
LOOP_CONTENT_DIR=dist node server.js
test:
@echo "Not implemented yet."

View File

@ -18,15 +18,35 @@
<link rel="localization" href="l10n/{locale}/loop.properties">
<script>
(function() {
function insertScript(url) {
var node = document.createElement("script");
var sibling = document.getElementsByTagName("script")[0];
node.async = 1;
node.src = url;
sibling.parentNode.insertBefore(node, sibling);
}
function insertScript(url, sync) {
var node = document.createElement("script");
var sibling = document.getElementsByTagName("script")[0];
node.async = !sync;
node.src = url;
sibling.parentNode.insertBefore(node, sibling);
}
/**
* Synchronously load the supplied script into the DOM (using <script>).
* Eventually, we probably want to do a full build step even for
* development, after which this can go away.
*
* Instead of having to specify the scripts we need here, and in
* some webpack config file for bundling, we specify them in
* webappEntryPoint.js, which require()s them. Webpack handles that
* during bundling, but for the current dev-server setup, where we don't
* (yet) have a full build step, we need to provide a require() function.
*
* @param webpackUrl - a URL, possibly preceded by webpack loader syntax.
* webpack loader syntax is stripped off
*
*/
function require(url) {
var devTimeUrl = url.replace(/^script!/, '');
insertScript(devTimeUrl, true);
}
(function() {
// window.navigator.doNotTrack "yes" is for old versions of FF
// window.navigator.doNotTrack "1" is for current versions of FF + Chrome + Opera
// window.doNotTrack is Safari + IE11
@ -120,34 +140,11 @@
// We don't use the SDK's CSS. This will prevent spurious 404 errors.
window.OTProperties.cssURL = "about:blank";
</script>
<script type="text/javascript" src="shared/libs/sdk.js"></script>
<script type="text/javascript" src="libs/l10n-gaia-02ca67948fe8.js"></script>
<script type="text/javascript" src="shared/libs/react-0.12.2.js"></script>
<script type="text/javascript" src="shared/libs/lodash-3.9.3.js"></script>
<script type="text/javascript" src="shared/libs/backbone-1.2.1.js"></script>
<!-- app scripts -->
<script type="text/javascript" src="config.js"></script>
<script type="text/javascript" src="shared/js/utils.js"></script>
<script type="text/javascript" src="shared/js/crypto.js"></script>
<script type="text/javascript" src="shared/js/mixins.js"></script>
<script type="text/javascript" src="shared/js/actions.js"></script>
<script type="text/javascript" src="shared/js/validate.js"></script>
<script type="text/javascript" src="shared/js/dispatcher.js"></script>
<script type="text/javascript" src="shared/js/websocket.js"></script>
<script type="text/javascript" src="shared/js/otSdkDriver.js"></script>
<script type="text/javascript" src="shared/js/store.js"></script>
<script type="text/javascript" src="shared/js/activeRoomStore.js"></script>
<script type="text/javascript" src="shared/js/views.js"></script>
<script type="text/javascript" src="shared/js/textChatStore.js"></script>
<script type="text/javascript" src="shared/js/textChatView.js"></script>
<script type="text/javascript" src="shared/js/urlRegExps.js"></script>
<script type="text/javascript" src="shared/js/linkifiedTextView.js"></script>
<script type="text/javascript" src="js/standaloneAppStore.js"></script>
<script type="text/javascript" src="js/standaloneMozLoop.js"></script>
<script type="text/javascript" src="js/standaloneRoomViews.js"></script>
<script type="text/javascript" src="js/standaloneMetricsStore.js"></script>
<script type="text/javascript" src="js/webapp.js"></script>
<!-- note that for 'make dist', webappEntryPoint.js is replaced by -->
<!-- the standalone.js bundle -->
<script type="text/javascript" src="webappEntryPoint.js"></script>
<script>
// Wait for all the localization notes to load

View File

@ -0,0 +1,44 @@
// When processed by webpack, this file bundles up all the JS for the
// standalone client.
//
// When loaded by the development server, index.html supplies a require
// function to load these.
// Right now, these are manually ordered so that all dependencies are
// satisfied. Before long, we'd like to convert these into real modules
// and/or better shims, and push the dependencies down into the modules
// themselves so that this manual management step goes away.
// To get started, we're using webpack's script loader to load these things in
// as-is.
/* global require */
require("script!shared/libs/sdk.js");
require("script!./libs/l10n-gaia-02ca67948fe8.js");
require("script!shared/libs/react-0.12.2.js");
require("script!shared/libs/lodash-3.9.3.js");
require("script!shared/libs/backbone-1.2.1.js");
require("script!shared/js/utils.js");
require("script!shared/js/crypto.js");
require("script!shared/js/mixins.js");
require("script!shared/js/actions.js");
require("script!shared/js/validate.js");
require("script!shared/js/dispatcher.js");
require("script!shared/js/websocket.js");
require("script!shared/js/otSdkDriver.js");
require("script!shared/js/store.js");
require("script!shared/js/activeRoomStore.js");
require("script!shared/js/views.js");
require("script!shared/js/urlRegExps.js");
require("script!shared/js/textChatStore.js");
require("script!shared/js/textChatView.js");
require("script!shared/js/linkifiedTextView.js");
require("script!./js/standaloneAppStore.js");
require("script!./js/standaloneMozLoop.js");
require("script!./js/standaloneRoomViews.js");
require("script!./js/standaloneMetricsStore.js");
require("script!./js/webapp.js");

View File

@ -14,7 +14,9 @@
"devDependencies": {
"eslint": "1.2.x",
"eslint-plugin-react": "3.2.x",
"express": "4.x"
"express": "4.x",
"script-loader": "0.6.x",
"webpack": "1.12.x"
},
"scripts": {
"test": "make test",

View File

@ -20,6 +20,10 @@ var feedbackApiUrl = process.env.LOOP_FEEDBACK_API_URL ||
var feedbackProductName = process.env.LOOP_FEEDBACK_PRODUCT_NAME || "Loop";
var loopServerUrl = process.env.LOOP_SERVER_URL || "http://localhost:5000";
// This is typically overridden with "dist" so that it's possible to test the
// optimized version, once it's been built to the "dist" directory
var standaloneContentDir = process.env.LOOP_CONTENT_DIR || "content";
// Remove trailing slashes as double slashes in the url can confuse the server
// responses.
if (loopServerUrl[loopServerUrl.length - 1] === "/") {
@ -70,10 +74,11 @@ app.use("/standalone/content", express.static(path.join(__dirname, "content")));
// does what we need for running in the github loop-client context, the second one
// handles running in the hg repo under mozilla-central and is used so that the shared
// files are in the right location.
app.use("/content", express.static(path.join(__dirname, "content")));
app.use("/content", express.static(path.join(__dirname, standaloneContentDir)));
app.use("/content", express.static(path.join(__dirname, "..", "content")));
// These two are based on the above, but handle call urls, that have a /c/ in them.
app.use("/content/c", express.static(path.join(__dirname, "content")));
app.use("/content/c", express.static(path.join(__dirname,
standaloneContentDir)));
app.use("/content/c", express.static(path.join(__dirname, "..", "content")));
// Two lines for the same reason as /content above.
@ -85,7 +90,7 @@ app.use("/test", express.static(path.join(__dirname, "..", "test")));
function serveIndex(req, res) {
"use strict";
return res.sendfile(path.join(__dirname, "content", "index.html"));
return res.sendFile(path.join(__dirname, standaloneContentDir, "index.html"));
}
app.get(/^\/content\/[\w\-]+$/, serveIndex);

View File

@ -0,0 +1,55 @@
/* eslint-env node */
// Webpack hurts to debug (lots of trial-and-error), so put non-trivial
// functionality in other script logic whenever practical.
var path = require("path");
function getSharedDir() {
"use strict";
var fs = require("fs");
// relative path to the shared directory in m-c
var mozillaCentralShared =
path.resolve(path.join(__dirname, "..", "content", "shared"));
try {
// if this doesn't blow up...
fs.statSync(mozillaCentralShared);
// that directory is there, so return it
return mozillaCentralShared;
} catch (ex) {
// otherwise, assume that we're in loop-client, where the shared
// directory is in the content directory
return path.join(__dirname, "content", "shared");
}
}
/**
* See http://webpack.github.io/docs/configuration.html on how this works.
* Make generous use of a search engine and stack overflow to interpret
* those docs.
*/
module.exports = {
entry: "./content/webappEntryPoint.js",
// We want the shared modules to be available without the requirer needing
// to know the path to them, especially that path is different in
// mozilla-central and loop-client.
resolve: {
alias: {
shared: getSharedDir()
}
},
output: {
filename: "standalone.js",
path: path.join(__dirname, "dist", "js"),
// Reduce false-positive warnings when viewing in editors which read
// our eslint config files (which disallows tabs).
sourcePrefix: " "
}
};