Niedzielski has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/371768 )
Change subject: Chore: rebuild and reload when dev code changes
......................................................................
Chore: rebuild and reload when dev code changes
When running `npm start` and the server or client code changes, rebuild
the server and / or client and reload any browser viewing the app.
Notes:
- Don't use an asset manifest for developmental builds.
- Pros: simpler, no opportunity for manifest to become outdated, no
manifest HTTP request.
- Cons: production flow differs.
- Switch server to TypeScript Node. The alternative is to check that the
server is built first like:
"start": "run-p -s 'compile:server -- -w' serve:client serve",
"serve": "nodemon -q -i src -x 'sh -c \"[ -e dist/server/index.js ] && node
dist/server\"'",
- Hot Module Replacement seems like a nice improvement on this patch but
it's advanced functionality and unfortunately out of scope for this
task.
- Server rebuilds trigger a browser update by touching a client file.
webpack-dev-server does provide an API to hook into the server but
an API to trigger a browser reload does not seem to be exposed:
webpack.config.devServer.setup(app) {
// Expose endpoint to manually trigger reloads from the server when
// it's rebooted.
app.get("/reload", (req, res) => {
console.log("reload");
return res;
});
}
The wp-calypso app appears to use webpack-hot-middleware for this
functionality:
https://github.com/Automattic/wp-calypso/blob/a70587157b/docs/routing.md#single-tree-rendering.
A future task could explore a better alternative to file touching.
Bug: T173020
Change-Id: Ie9e38362b6cfdad0b3764e10ade20be4b5d6dfd0
---
M package-lock.json
M package.json
M src/server/index.ts
M src/server/templates/page.ts
M webpack.config.js
5 files changed, 1,073 insertions(+), 21 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/marvin refs/changes/68/371768/1
diff --git a/package-lock.json b/package-lock.json
index 0fffa7f..f10b3d0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -51,6 +51,15 @@
"@types/mime": "1.3.1"
}
},
+ "@types/touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/touch/-/touch-3.1.0.tgz",
+ "integrity":
"sha512-Bskfd5wztYbQ/mvU4rgHUB3fKcjW2hA6o/F0JN8O+jRPJQDN/2pPV6SmdIiFm2vLyyN/XQzoCULTE05ZOpnNbQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "8.0.20"
+ }
+ },
"abbrev": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
@@ -141,6 +150,12 @@
"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
"dev": true
},
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "dev": true
+ },
"ansi-regex": {
"version": "2.1.1",
"resolved":
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
@@ -191,6 +206,12 @@
"version": "0.0.1",
"resolved":
"https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz",
"integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved":
"https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
"dev": true
},
"array-flatten": {
@@ -308,6 +329,12 @@
"integrity":
"sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
"dev": true
},
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
"big.js": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
@@ -325,6 +352,28 @@
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz",
"integrity":
"sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==",
"dev": true
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "2.1.1",
+ "deep-equal": "1.0.1",
+ "dns-equal": "1.0.0",
+ "dns-txt": "2.0.2",
+ "multicast-dns": "6.1.1",
+ "multicast-dns-service-types": "1.1.0"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "2.1.1",
+ "resolved":
"https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
+ "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
+ "dev": true
+ }
+ }
},
"brace-expansion": {
"version": "1.1.8",
@@ -439,6 +488,12 @@
"isarray": "1.0.0"
}
},
+ "buffer-indexof": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.0.tgz",
+ "integrity": "sha1-9U9kfE9OJSKLqmVqLlfkPV8nCYI=",
+ "dev": true
+ },
"buffer-xor": {
"version": "1.0.3",
"resolved":
"https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
@@ -455,6 +510,12 @@
"version": "3.0.0",
"resolved":
"https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz",
+ "integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=",
"dev": true
},
"caller-path": {
@@ -477,6 +538,24 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
"dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved":
"https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved":
"https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ }
+ }
},
"center-align": {
"version": "0.1.3",
@@ -611,6 +690,41 @@
"readable-stream": "2.3.3"
}
},
+ "compressible": {
+ "version": "2.0.11",
+ "resolved":
"https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz",
+ "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.29.0"
+ }
+ },
+ "compression": {
+ "version": "1.7.0",
+ "resolved":
"https://registry.npmjs.org/compression/-/compression-1.7.0.tgz",
+ "integrity": "sha1-AwyfGY8WQ6BX13anOOki2kNzAS0=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.3",
+ "bytes": "2.5.0",
+ "compressible": "2.0.11",
+ "debug": "2.6.8",
+ "on-headers": "1.0.1",
+ "safe-buffer": "5.1.1",
+ "vary": "1.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
"concat-map": {
"version": "0.0.1",
"resolved":
"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -643,6 +757,12 @@
"write-file-atomic": "1.3.4",
"xdg-basedir": "2.0.0"
}
+ },
+ "connect-history-api-fallback": {
+ "version": "1.3.0",
+ "resolved":
"https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz",
+ "integrity": "sha1-5R0X+PDvDbkKZP20feMFFVbp8Wk=",
+ "dev": true
},
"console-browserify": {
"version": "1.1.0",
@@ -750,6 +870,15 @@
"randombytes": "2.0.5"
}
},
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved":
"https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "1.0.2"
+ }
+ },
"d": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
@@ -777,6 +906,12 @@
"version": "1.2.0",
"resolved":
"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "1.0.1",
+ "resolved":
"https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
},
"deep-extend": {
@@ -836,6 +971,12 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
+ "detect-node": {
+ "version": "2.0.3",
+ "resolved":
"https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
+ "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=",
+ "dev": true
+ },
"diff": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
@@ -851,6 +992,31 @@
"bn.js": "4.11.7",
"miller-rabin": "4.0.0",
"randombytes": "2.0.5"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.2.1",
+ "resolved":
"https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.1.tgz",
+ "integrity":
"sha512-eisukPHpsFmhEIDnm2mECIiT0huapmdkC0AH1Lvt613Kz2v1kwolrkecvguFazrqnpxvgYdtcMFTsmQzAeRXZQ==",
+ "dev": true,
+ "requires": {
+ "ip": "1.1.5",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "1.1.0"
}
},
"doctrine": {
@@ -1324,11 +1490,26 @@
"through": "2.3.8"
}
},
+ "eventemitter3": {
+ "version": "1.2.0",
+ "resolved":
"https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
+ "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
+ "dev": true
+ },
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
"dev": true
+ },
+ "eventsource": {
+ "version": "0.1.6",
+ "resolved":
"https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
+ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
+ "dev": true,
+ "requires": {
+ "original": "1.0.0"
+ }
},
"evp_bytestokey": {
"version": "1.0.0",
@@ -1445,6 +1626,15 @@
"resolved":
"https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved":
"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": "0.6.5"
+ }
},
"figures": {
"version": "1.7.0",
@@ -1736,6 +1926,12 @@
"integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
"dev": true
},
+ "handle-thing": {
+ "version": "1.2.5",
+ "resolved":
"https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+ "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
+ "dev": true
+ },
"has": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
@@ -1796,6 +1992,24 @@
"integrity":
"sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
"dev": true
},
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "wbuf": "1.7.2"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved":
"https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
"htmlparser2": {
"version": "3.8.3",
"resolved":
"https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
@@ -1835,6 +2049,12 @@
}
}
},
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved":
"https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
"http-errors": {
"version": "1.6.1",
"resolved":
"https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz",
@@ -1850,6 +2070,45 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
"integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
+ }
+ }
+ },
+ "http-proxy": {
+ "version": "1.16.2",
+ "resolved":
"https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz",
+ "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "1.2.0",
+ "requires-port": "1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.17.4",
+ "resolved":
"https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz",
+ "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=",
+ "dev": true,
+ "requires": {
+ "http-proxy": "1.16.2",
+ "is-glob": "3.1.0",
+ "lodash": "4.17.4",
+ "micromatch": "2.3.11"
+ },
+ "dependencies": {
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved":
"https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "2.1.1"
+ }
}
}
},
@@ -1901,6 +2160,26 @@
"resolved":
"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved":
"https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "2.0.1"
+ },
+ "dependencies": {
+ "repeating": {
+ "version": "2.0.1",
+ "resolved":
"https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "1.0.2"
+ }
+ }
+ }
},
"indexof": {
"version": "0.0.1",
@@ -1969,6 +2248,15 @@
}
}
},
+ "internal-ip": {
+ "version": "1.2.0",
+ "resolved":
"https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
+ "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
+ "dev": true,
+ "requires": {
+ "meow": "3.7.0"
+ }
+ },
"interpret": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz",
@@ -1979,6 +2267,12 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+ "dev": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
"ipaddr.js": {
@@ -2194,6 +2488,12 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
"integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+ "dev": true
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
"dev": true
},
"isarray": {
@@ -2600,6 +2900,12 @@
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
"dev": true
},
+ "loglevel": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.4.1.tgz",
+ "integrity": "sha1-lbOD+Ro8J1b9SrCTZn5DCRYfK80=",
+ "dev": true
+ },
"lolex": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/lolex/-/lolex-2.1.2.tgz",
@@ -2611,6 +2917,16 @@
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
"dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved":
"https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.2"
+ }
},
"lowercase-keys": {
"version": "1.0.0",
@@ -2632,6 +2948,12 @@
"version": "1.3.0",
"resolved":
"https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz",
"integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
"map-stream": {
@@ -2662,6 +2984,105 @@
"requires": {
"errno": "0.1.4",
"readable-stream": "2.3.3"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.4.0",
+ "object-assign": "4.1.1",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved":
"https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved":
"https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "1.1.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved":
"https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved":
"https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ }
}
},
"merge-descriptors": {
@@ -2847,6 +3268,22 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
+ "multicast-dns": {
+ "version": "6.1.1",
+ "resolved":
"https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.1.1.tgz",
+ "integrity": "sha1-bn3oalcIcqsXBYrepxYLvsqBTd4=",
+ "dev": true,
+ "requires": {
+ "dns-packet": "1.2.1",
+ "thunky": "0.1.0"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
"mute-stream": {
"version": "0.0.5",
"resolved":
"https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
@@ -2914,6 +3351,12 @@
}
}
},
+ "node-forge": {
+ "version": "0.6.33",
+ "resolved":
"https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz",
+ "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=",
+ "dev": true
+ },
"node-libs-browser": {
"version": "2.0.0",
"resolved":
"https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.0.0.tgz",
@@ -2966,7 +3409,6 @@
"lodash.defaults": "3.1.2",
"minimatch": "3.0.4",
"ps-tree": "1.1.0",
- "touch": "1.0.0",
"undefsafe": "0.0.3",
"update-notifier": "0.5.0"
}
@@ -3053,6 +3495,12 @@
"is-extendable": "0.1.1"
}
},
+ "obuf": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz",
+ "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=",
+ "dev": true
+ },
"on-finished": {
"version": "2.3.0",
"resolved":
"https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -3060,6 +3508,12 @@
"requires": {
"ee-first": "1.1.1"
}
+ },
+ "on-headers": {
+ "version": "1.0.1",
+ "resolved":
"https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
+ "dev": true
},
"once": {
"version": "1.4.0",
@@ -3075,6 +3529,16 @@
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
+ },
+ "opn": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
+ "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.1",
+ "pinkie-promise": "2.0.1"
+ }
},
"optionator": {
"version": "0.8.2",
@@ -3095,6 +3559,27 @@
"resolved":
"https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
"dev": true
+ }
+ }
+ },
+ "original": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz",
+ "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=",
+ "dev": true,
+ "requires": {
+ "url-parse": "1.0.5"
+ },
+ "dependencies": {
+ "url-parse": {
+ "version": "1.0.5",
+ "resolved":
"https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz",
+ "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=",
+ "dev": true,
+ "requires": {
+ "querystringify": "0.0.4",
+ "requires-port": "1.0.0"
+ }
}
}
},
@@ -3157,6 +3642,12 @@
"requires": {
"p-limit": "1.1.0"
}
+ },
+ "p-map": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.1.1.tgz",
+ "integrity": "sha1-BfXkrpegaDcbwqXMhr+9vBnErno=",
+ "dev": true
},
"package-json": {
"version": "1.2.0",
@@ -3312,6 +3803,25 @@
"integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=",
"dev": true
},
+ "portfinder": {
+ "version": "1.0.13",
+ "resolved":
"https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
+ "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "debug": "2.6.7",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ }
+ }
+ },
"prelude-ls": {
"version": "1.1.2",
"resolved":
"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -3418,6 +3928,12 @@
"version": "0.2.1",
"resolved":
"https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "0.0.4",
+ "resolved":
"https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz",
+ "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=",
"dev": true
},
"randomatic": {
@@ -3573,6 +4089,33 @@
"resolve": "1.4.0"
}
},
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ },
+ "dependencies": {
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved":
"https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved":
"https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ }
+ }
+ },
"regex-cache": {
"version": "0.4.3",
"resolved":
"https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
@@ -3640,6 +4183,12 @@
"caller-path": "0.1.0",
"resolve-from": "1.0.1"
}
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved":
"https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
},
"resolve": {
"version": "1.4.0",
@@ -3721,6 +4270,21 @@
"integrity": "sha1-7dOQk6MYQ3DLhZJDsr3yVefY6mc=",
"dev": true
},
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved":
"https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selfsigned": {
+ "version": "1.10.1",
+ "resolved":
"https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz",
+ "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.6.33"
+ }
+ },
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
@@ -3754,6 +4318,32 @@
"on-finished": "2.3.0",
"range-parser": "1.2.0",
"statuses": "1.3.1"
+ }
+ },
+ "serve-index": {
+ "version": "1.9.0",
+ "resolved":
"https://registry.npmjs.org/serve-index/-/serve-index-1.9.0.tgz",
+ "integrity": "sha1-0rKA/FYNYW7oG0i/D6gqvtJIXOc=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.3",
+ "batch": "0.6.1",
+ "debug": "2.6.8",
+ "escape-html": "1.0.3",
+ "http-errors": "1.6.1",
+ "mime-types": "2.1.16",
+ "parseurl": "1.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
}
},
"serve-static": {
@@ -3884,6 +4474,41 @@
"integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
"dev": true
},
+ "sockjs": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz",
+ "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "0.10.0",
+ "uuid": "2.0.3"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.1.4",
+ "resolved":
"https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
+ "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.7",
+ "eventsource": "0.1.6",
+ "faye-websocket": "0.11.1",
+ "inherits": "2.0.3",
+ "json3": "3.3.2",
+ "url-parse": "1.1.9"
+ },
+ "dependencies": {
+ "faye-websocket": {
+ "version": "0.11.1",
+ "resolved":
"https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
+ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": "0.6.5"
+ }
+ }
+ }
+ },
"source-list-map": {
"version": "2.0.0",
"resolved":
"https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
@@ -3925,6 +4550,57 @@
"resolved":
"https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
"integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
"dev": true
+ },
+ "spdy": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.8",
+ "handle-thing": "1.2.5",
+ "http-deceiver": "1.2.7",
+ "safe-buffer": "5.1.1",
+ "select-hose": "2.0.0",
+ "spdy-transport": "2.0.20"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "2.0.20",
+ "resolved":
"https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz",
+ "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.8",
+ "detect-node": "2.0.3",
+ "hpack.js": "2.1.6",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "safe-buffer": "5.1.1",
+ "wbuf": "1.7.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
},
"split": {
"version": "0.3.3",
@@ -4141,6 +4817,18 @@
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
+ "thunky": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz",
+ "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=",
+ "dev": true
+ },
+ "time-stamp": {
+ "version": "2.0.0",
+ "resolved":
"https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz",
+ "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=",
+ "dev": true
+ },
"timed-out": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz",
@@ -4164,13 +4852,19 @@
"dev": true
},
"touch": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/touch/-/touch-1.0.0.tgz",
- "integrity": "sha1-RJy+LbrlqMgDjjDXH6D/RklHxN4=",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity":
"sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"requires": {
"nopt": "1.0.10"
}
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved":
"https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
},
"tryit": {
"version": "1.0.3",
@@ -4433,6 +5127,24 @@
}
}
},
+ "url-parse": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz",
+ "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=",
+ "dev": true,
+ "requires": {
+ "querystringify": "1.0.0",
+ "requires-port": "1.0.0"
+ },
+ "dependencies": {
+ "querystringify": {
+ "version": "1.0.0",
+ "resolved":
"https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz",
+ "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=",
+ "dev": true
+ }
+ }
+ },
"user-home": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
@@ -4528,6 +5240,15 @@
"graceful-fs": "4.1.11"
}
},
+ "wbuf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz",
+ "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "1.0.0"
+ }
+ },
"webpack": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.4.1.tgz",
@@ -4569,6 +5290,270 @@
}
}
},
+ "webpack-dev-middleware": {
+ "version": "1.12.0",
+ "resolved":
"https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz",
+ "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=",
+ "dev": true,
+ "requires": {
+ "memory-fs": "0.4.1",
+ "mime": "1.3.4",
+ "path-is-absolute": "1.0.1",
+ "range-parser": "1.2.0",
+ "time-stamp": "2.0.0"
+ }
+ },
+ "webpack-dev-server": {
+ "version": "2.7.1",
+ "resolved":
"https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.7.1.tgz",
+ "integrity": "sha1-IVgPWgjNBlxxFEz29hw0W8pZqLg=",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "3.5.0",
+ "chokidar": "1.7.0",
+ "compression": "1.7.0",
+ "connect-history-api-fallback": "1.3.0",
+ "del": "3.0.0",
+ "express": "4.15.3",
+ "html-entities": "1.2.1",
+ "http-proxy-middleware": "0.17.4",
+ "internal-ip": "1.2.0",
+ "ip": "1.1.5",
+ "loglevel": "1.4.1",
+ "opn": "4.0.2",
+ "portfinder": "1.0.13",
+ "selfsigned": "1.10.1",
+ "serve-index": "1.9.0",
+ "sockjs": "0.3.18",
+ "sockjs-client": "1.1.4",
+ "spdy": "3.4.7",
+ "strip-ansi": "3.0.1",
+ "supports-color": "3.2.3",
+ "webpack-dev-middleware": "1.12.0",
+ "yargs": "6.6.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved":
"https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wrap-ansi": "2.1.0"
+ }
+ },
+ "del": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+ "dev": true,
+ "requires": {
+ "globby": "6.1.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "p-map": "1.1.1",
+ "pify": "3.0.0",
+ "rimraf": "2.5.4"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved":
"https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved":
"https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "dev": true,
+ "requires": {
+ "lcid": "1.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved":
"https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved":
"https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "1.1.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved":
"https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved":
"https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved":
"https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved":
"https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true,
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved":
"https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
+ "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "1.4.0",
+ "read-pkg-up": "1.0.1",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "1.0.2",
+ "which-module": "1.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "4.2.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "4.2.1",
+ "resolved":
"https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+ "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0"
+ }
+ }
+ }
+ },
"webpack-sources": {
"version": "1.0.1",
"resolved":
"https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.1.tgz",
@@ -4579,6 +5564,21 @@
"source-map": "0.5.6"
}
},
+ "websocket-driver": {
+ "version": "0.6.5",
+ "resolved":
"https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
+ "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=",
+ "dev": true,
+ "requires": {
+ "websocket-extensions": "0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.1",
+ "resolved":
"https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
+ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=",
+ "dev": true
+ },
"which": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
diff --git a/package.json b/package.json
index f87e793..a413a8c 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,12 @@
"version": "0.0.0",
"description": "An API driven skin for MediaWiki",
"scripts": {
- "start": "nodemon -i dist -e ts,tsx,js,json -q -x 'run-s -s build serve'",
- "build": "run-p -s compile:server 'pack:client -- -d'",
- "prod:build": "NODE_ENV=production npm-run-all --silent clean -p
compile:server 'pack:client -- -p'",
+ "start": "run-p -s serve:\\*",
+ "serve:client": "webpack-dev-server -dw",
+ "serve:server": "nodemon -q -i src/client -e ts,tsx,js,json -x 'ts-node
src/server'",
+ "prod:build": "NODE_ENV=production npm-run-all --silent clean -p
compile:server prod:pack:client",
+ "prod:pack:client": "webpack -p",
"compile:server": "tsc -p src/server",
- "pack:client": "webpack",
- "serve": "node dist/server/index.js",
"clean": "rm -rf dist",
"test": "mocha '{src,test}/**/*.test.{ts,js}'",
"test:watch": "nodemon -e ts,tsx,js,json -q -x 'npm test -s'",
@@ -45,6 +45,7 @@
"@types/express": "^4.0.36",
"@types/mocha": "^2.2.41",
"@types/node": "^8.0.20",
+ "@types/touch": "^3.1.0",
"assets-webpack-plugin": "^3.5.1",
"eslint": "^3.19.0",
"eslint-config-node-services": "^2.2.2",
@@ -59,10 +60,12 @@
"npm-run-all": "^4.0.2",
"prettier": "^1.5.3",
"sinon": "^3.0.0",
+ "touch": "^3.1.0",
"ts-loader": "^2.3.2",
"ts-node": "^3.3.0",
"typescript": "^2.4.2",
"typescript-eslint-parser": "^5.0.1",
- "webpack": "^3.4.1"
+ "webpack": "^3.4.1",
+ "webpack-dev-server": "^2.7.1"
}
}
diff --git a/src/server/index.ts b/src/server/index.ts
index 127ac85..a2c92b3 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,7 +1,12 @@
import * as express from "express";
import page, { AssetsManifest } from "./templates/page";
import app from "../common/components/app";
-const assets: AssetsManifest =
require("../../dist/public/assets-manifest.json");
+
+const isProd: boolean = process.env.NODE_ENV === "production";
+
+const assets: AssetsManifest | string = isProd
+ ? require("../../dist/public/assets-manifest.json")
+ : "http://localhost:8080";
const { PORT = 3000 } = process.env;
const server = express();
@@ -18,4 +23,13 @@
server.listen(PORT, () => {
console.log(`Server started on port http://localhost:${PORT}/`); //
eslint-disable-line no-console
+
+ if (!isProd) {
+ const touch = require("touch");
+
+ // The server is now listening. If developmental, touch the client sources
to trigger a browser
+ // reload. Negative offset accounts for:
https://github.com/webpack/watchpack/issues/25.
+ const nowish: number = Date.now() - 10 * 1000;
+ touch("src/client/index.ts", { time: nowish });
+ }
});
diff --git a/src/server/templates/page.ts b/src/server/templates/page.ts
index f2b9945..1fb15e3 100644
--- a/src/server/templates/page.ts
+++ b/src/server/templates/page.ts
@@ -10,10 +10,24 @@
// HTML to render in the body of the page
body: string,
// Manifest of filename entry points to bundled assets.
- assets: AssetsManifest
+ assets: AssetsManifest | string
}
+/**
+ * @return The path to the asset identified by entry and extension (e.g.,
index.js); either a URL
+ * (development) or a filesystem path (production).
+ */
+const asset = (
+ manifest: AssetsManifest | string,
+ entry: string,
+ extension: string
+) =>
+ typeof manifest === "string"
+ ? `${manifest}/${entry}.${extension}`
+ : manifest[entry][extension];
+
export default function page({ title, body = "", assets }: PageParams): string
{
+ const script: string = asset(assets, "index", "js");
return `
<!DOCTYPE html>
<html lang="en">
@@ -25,7 +39,7 @@
</head>
<body>
<div id="root">${body}</div>
- <script type="text/javascript" src="${assets.index.js}"></script>
+ <script type="text/javascript" src="${script}"></script>
</body>
</html>`;
}
diff --git a/webpack.config.js b/webpack.config.js
index 7811340..1475dab 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -34,7 +34,9 @@
// global build hashing, to improve caching from browsers.
// See: https://webpack.js.org/guides/caching/#output-filenames
chunkFilename: "[name].[chunkhash].js",
- filename: "[name].[chunkhash].js"
+
+ // Use constant filenames for developmental server.
+ filename: isProd ? "[name].[chunkhash].js" : "[name].js"
},
resolve: {
@@ -56,16 +58,35 @@
devtool: isProd ? "source-map" : "cheap-module-eval-source-map",
- plugins: [
- // Use path names instead of autogenerated ids for asset names
- new webpack.NamedModulesPlugin(),
+ // For development builds, serve the packaged result over
http://localhost:8080/ and live reload
+ // the browser when the bundle is rebuilt.
+ devServer: isProd
+ ? undefined
+ : {
+ // Forbid static files. All responses are in memory.
+ contentBase: false,
- // Generate a json manifest with the entry points and assets names to use
- // in the server to pass to the HTML page template
+ // Log warnings and errors in the browser console.
+ clientLogLevel: "warning",
+
+ // Show warnings and errors as an obtrusive opaque overlay in the
browser.
+ overlay: { warnings: true, errors: true },
+
+ stats: WARNINGS_STATS_PRESET
+ },
+
+ // Use path names instead of autogenerated ids for asset names
+ plugins: [new webpack.NamedModulesPlugin()]
+};
+
+if (isProd) {
+ // Generate a json manifest with the entry points and assets names to use
+ // in the server to pass to the HTML page template
+ module.exports.plugins.push(
new AssetsPlugin({
prettyPrint: true,
filename: "assets-manifest.json",
path: paths.client.output
})
- ]
-};
+ );
+}
--
To view, visit https://gerrit.wikimedia.org/r/371768
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie9e38362b6cfdad0b3764e10ade20be4b5d6dfd0
Gerrit-PatchSet: 1
Gerrit-Project: marvin
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits