diff --git a/.travis.yml b/.travis.yml
index bc3fce38..3b201c1e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,25 +11,18 @@ sudo: required
 language: node_js
 node_js:
     # make sure we work with a range of node versions.
-    # As of the time of writing:
-    #  - 4.x is still in LTS (until April 2018), but some of our deps (notably
-    #    extract-zip) don't work with it
-    #  - 5.x has been EOLed for nearly a year.
-    #  - 6.x is the active 'LTS' version
-    #  - 7.x is no longer supported
-    #  - 8.x is the current 'current' version (until October 2017)
     #
-    # see: https://github.com/nodejs/LTS/
-    #
-    # anything before 6.3 ships with npm 3.9 or earlier, which had problems
-    # with symlinks in node_modules (see
-    # https://github.com/npm/npm/releases/tag/v3.10.0 'FIXES AND REFACTORING').
-    - 6.3
-    - 6
-    - 7
+    # Current status of node versions: https://github.com/nodejs/LTS/
+    # We don't work with node 6 because it doesn't support package-lock
+    # files which we need to avoid the broken version of base-x
+    - 8
+    - 10
 addons:
     chrome: stable
 install:
     # clone the deps with depth 1: we know we will only ever need that one
     # commit.
-    - scripts/fetch-develop.deps.sh --depth 1 && npm install
+    - npm install && scripts/fetch-develop.deps.sh --depth 1
+script:
+    - npm run test
+    - npm run lint
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1551e7f4..9148433b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Changes in [0.17.7](https://github.com/vector-im/riot-web/releases/tag/v0.17.7) (2018-11-22)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.6...v0.17.7)
+
+ * Warning when crypto DB is too new to use.
+ * Fix missing entries from js-sdk in rageshake logs
+
 Changes in [0.17.6](https://github.com/vector-im/riot-web/releases/tag/v0.17.6) (2018-11-19)
 ============================================================================================
 [Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.6-rc.2...v0.17.6)
diff --git a/electron_app/package.json b/electron_app/package.json
index 4fbefd00..7d32bfcc 100644
--- a/electron_app/package.json
+++ b/electron_app/package.json
@@ -2,7 +2,7 @@
   "name": "riot-web",
   "productName": "Riot",
   "main": "src/electron-main.js",
-  "version": "0.17.6",
+  "version": "0.17.7",
   "description": "A feature-rich client for Matrix.org",
   "author": "New Vector Ltd.",
   "dependencies": {
diff --git a/package-lock.json b/package-lock.json
index d21cf33f..ab504339 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,6 +46,62 @@
         "@babel/highlight": "^7.0.0"
       }
     },
+    "@babel/generator": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz",
+      "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "7.0.0-beta.44",
+        "jsesc": "^2.5.1",
+        "lodash": "^4.2.0",
+        "source-map": "^0.5.0",
+        "trim-right": "^1.0.1"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "2.5.1",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
+          "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=",
+          "dev": true
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        }
+      }
+    },
+    "@babel/helper-function-name": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz",
+      "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-get-function-arity": "7.0.0-beta.44",
+        "@babel/template": "7.0.0-beta.44",
+        "@babel/types": "7.0.0-beta.44"
+      }
+    },
+    "@babel/helper-get-function-arity": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz",
+      "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "7.0.0-beta.44"
+      }
+    },
+    "@babel/helper-split-export-declaration": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz",
+      "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "7.0.0-beta.44"
+      }
+    },
     "@babel/highlight": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
@@ -72,6 +128,129 @@
         }
       }
     },
+    "@babel/template": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz",
+      "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.44",
+        "@babel/types": "7.0.0-beta.44",
+        "babylon": "7.0.0-beta.44",
+        "lodash": "^4.2.0"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
+          "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "7.0.0-beta.44"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz",
+          "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==",
+          "dev": true,
+          "requires": {
+            "chalk": "^2.0.0",
+            "esutils": "^2.0.2",
+            "js-tokens": "^3.0.0"
+          }
+        },
+        "babylon": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
+          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==",
+          "dev": true
+        },
+        "js-tokens": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+          "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+          "dev": true
+        }
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz",
+      "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "7.0.0-beta.44",
+        "@babel/generator": "7.0.0-beta.44",
+        "@babel/helper-function-name": "7.0.0-beta.44",
+        "@babel/helper-split-export-declaration": "7.0.0-beta.44",
+        "@babel/types": "7.0.0-beta.44",
+        "babylon": "7.0.0-beta.44",
+        "debug": "^3.1.0",
+        "globals": "^11.1.0",
+        "invariant": "^2.2.0",
+        "lodash": "^4.2.0"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
+          "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "7.0.0-beta.44"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz",
+          "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==",
+          "dev": true,
+          "requires": {
+            "chalk": "^2.0.0",
+            "esutils": "^2.0.2",
+            "js-tokens": "^3.0.0"
+          }
+        },
+        "babylon": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
+          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==",
+          "dev": true
+        },
+        "globals": {
+          "version": "11.8.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz",
+          "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==",
+          "dev": true
+        },
+        "js-tokens": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+          "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+          "dev": true
+        }
+      }
+    },
+    "@babel/types": {
+      "version": "7.0.0-beta.44",
+      "resolved": "http://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz",
+      "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2",
+        "lodash": "^4.2.0",
+        "to-fast-properties": "^2.0.0"
+      },
+      "dependencies": {
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+          "dev": true
+        }
+      }
+    },
     "@webassemblyjs/ast": {
       "version": "1.7.10",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.10.tgz",
@@ -1008,16 +1187,51 @@
       }
     },
     "babel-eslint": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-6.1.2.tgz",
-      "integrity": "sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8=",
+      "version": "8.2.6",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz",
+      "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==",
       "dev": true,
       "requires": {
-        "babel-traverse": "^6.0.20",
-        "babel-types": "^6.0.19",
-        "babylon": "^6.0.18",
-        "lodash.assign": "^4.0.0",
-        "lodash.pickby": "^4.0.0"
+        "@babel/code-frame": "7.0.0-beta.44",
+        "@babel/traverse": "7.0.0-beta.44",
+        "@babel/types": "7.0.0-beta.44",
+        "babylon": "7.0.0-beta.44",
+        "eslint-scope": "3.7.1",
+        "eslint-visitor-keys": "^1.0.0"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
+          "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "7.0.0-beta.44"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz",
+          "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==",
+          "dev": true,
+          "requires": {
+            "chalk": "^2.0.0",
+            "esutils": "^2.0.2",
+            "js-tokens": "^3.0.0"
+          }
+        },
+        "babylon": {
+          "version": "7.0.0-beta.44",
+          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
+          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==",
+          "dev": true
+        },
+        "js-tokens": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+          "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+          "dev": true
+        }
       }
     },
     "babel-generator": {
@@ -1237,7 +1451,7 @@
     },
     "babel-plugin-add-module-exports": {
       "version": "0.2.1",
-      "resolved": "http://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
       "integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=",
       "dev": true
     },
@@ -1252,55 +1466,55 @@
     },
     "babel-plugin-syntax-async-functions": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
       "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
       "dev": true
     },
     "babel-plugin-syntax-async-generators": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
       "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
       "dev": true
     },
     "babel-plugin-syntax-class-properties": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
       "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
       "dev": true
     },
     "babel-plugin-syntax-decorators": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
       "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
       "dev": true
     },
     "babel-plugin-syntax-dynamic-import": {
       "version": "6.18.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
       "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
       "dev": true
     },
     "babel-plugin-syntax-exponentiation-operator": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
       "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
       "dev": true
     },
     "babel-plugin-syntax-flow": {
       "version": "6.18.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
       "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
       "dev": true
     },
     "babel-plugin-syntax-jsx": {
       "version": "6.18.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
       "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=",
       "dev": true
     },
     "babel-plugin-syntax-object-rest-spread": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
       "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
       "dev": true
     },
@@ -2060,7 +2274,7 @@
     },
     "blob": {
       "version": "0.0.4",
-      "resolved": "http://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
+      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
       "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
       "dev": true
     },
@@ -3886,7 +4100,7 @@
     },
     "css-select": {
       "version": "1.2.0",
-      "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
       "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
       "dev": true,
       "requires": {
@@ -4227,7 +4441,7 @@
       "dependencies": {
         "domelementtype": {
           "version": "1.1.3",
-          "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
           "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
         }
       }
@@ -4240,7 +4454,7 @@
     },
     "domelementtype": {
       "version": "1.3.0",
-      "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
       "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
     },
     "domhandler": {
@@ -4293,7 +4507,7 @@
     },
     "duplexer": {
       "version": "0.1.1",
-      "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
       "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
       "dev": true
     },
@@ -4599,7 +4813,7 @@
         },
         "ms": {
           "version": "0.7.2",
-          "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
           "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
           "dev": true
         }
@@ -4737,7 +4951,7 @@
         },
         "ms": {
           "version": "0.7.2",
-          "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
           "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
           "dev": true
         },
@@ -4830,7 +5044,7 @@
     },
     "emojione": {
       "version": "2.2.7",
-      "resolved": "http://registry.npmjs.org/emojione/-/emojione-2.2.7.tgz",
+      "resolved": "https://registry.npmjs.org/emojione/-/emojione-2.2.7.tgz",
       "integrity": "sha1-RkV89rmy+NoTroouTlR94G7hXpY="
     },
     "emojis-list": {
@@ -5085,6 +5299,16 @@
             "esutils": "^2.0.2"
           }
         },
+        "eslint-scope": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+          "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+          "dev": true,
+          "requires": {
+            "esrecurse": "^4.1.0",
+            "estraverse": "^4.1.1"
+          }
+        },
         "glob": {
           "version": "7.1.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
@@ -5118,7 +5342,7 @@
     },
     "eslint-config-google": {
       "version": "0.7.1",
-      "resolved": "http://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.7.1.tgz",
+      "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.7.1.tgz",
       "integrity": "sha1-VZj4SY6eB4Qg80uASVuNlZ9lH7I=",
       "dev": true
     },
@@ -5162,9 +5386,9 @@
       }
     },
     "eslint-scope": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
-      "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+      "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
       "dev": true,
       "requires": {
         "esrecurse": "^4.1.0",
@@ -5358,7 +5582,7 @@
     },
     "expect": {
       "version": "1.20.2",
-      "resolved": "http://registry.npmjs.org/expect/-/expect-1.20.2.tgz",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-1.20.2.tgz",
       "integrity": "sha1-1Fj+TFYAQDa64yMkFqP2Nh8E+WU=",
       "dev": true,
       "requires": {
@@ -5574,7 +5798,7 @@
       "dependencies": {
         "core-js": {
           "version": "1.2.7",
-          "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+          "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
           "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
         }
       }
@@ -5763,7 +5987,7 @@
       "dependencies": {
         "core-js": {
           "version": "1.2.7",
-          "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+          "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
           "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
         },
         "fbjs": {
@@ -6573,7 +6797,7 @@
     },
     "get-stream": {
       "version": "3.0.0",
-      "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
       "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
       "dev": true
     },
@@ -7428,7 +7652,7 @@
     },
     "immutable": {
       "version": "3.7.6",
-      "resolved": "http://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
+      "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
       "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
     },
     "import-cwd": {
@@ -7717,7 +7941,7 @@
     },
     "is-builtin-module": {
       "version": "1.0.0",
-      "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
       "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
       "requires": {
         "builtin-modules": "^1.0.0"
@@ -7899,7 +8123,7 @@
     },
     "is-obj": {
       "version": "1.0.1",
-      "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
       "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
       "dev": true
     },
@@ -8166,7 +8390,7 @@
     },
     "json5": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
     },
     "jsonfile": {
@@ -8292,7 +8516,7 @@
         },
         "xmlbuilder": {
           "version": "3.1.0",
-          "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-3.1.0.tgz",
+          "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-3.1.0.tgz",
           "integrity": "sha1-LIaIjy1OrehQ+jjKf3Ij9yCVFuE=",
           "dev": true,
           "requires": {
@@ -8486,7 +8710,7 @@
     },
     "load-json-file": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
       "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -8540,12 +8764,6 @@
       "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.11.tgz",
       "integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q=="
     },
-    "lodash.assign": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
-      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
-      "dev": true
-    },
     "lodash.clonedeep": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -8577,12 +8795,6 @@
       "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
       "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
     },
-    "lodash.pickby": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
-      "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=",
-      "dev": true
-    },
     "lodash.toarray": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
@@ -8723,7 +8935,7 @@
       }
     },
     "matrix-react-sdk": {
-      "version": "github:matrix-org/matrix-react-sdk#507bfb4b69c9d45ba8e1165e8865b0479fcb6d7c",
+      "version": "github:matrix-org/matrix-react-sdk#0bd1d6b778f9fc89e0f7e75557f8e7acf576be92",
       "from": "github:matrix-org/matrix-react-sdk#develop",
       "requires": {
         "babel-runtime": "^6.26.0",
@@ -8844,7 +9056,7 @@
     },
     "media-typer": {
       "version": "0.3.0",
-      "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
@@ -8990,7 +9202,7 @@
     },
     "minimist": {
       "version": "1.2.0",
-      "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
     },
     "mississippi": {
@@ -9034,7 +9246,7 @@
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "requires": {
         "minimist": "0.0.8"
@@ -9042,7 +9254,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.8",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
           "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
         }
       }
@@ -9574,7 +9786,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.10",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
           "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
         }
       }
@@ -9624,7 +9836,7 @@
     },
     "os-locale": {
       "version": "1.4.0",
-      "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+      "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
       "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
       "requires": {
         "lcid": "^1.0.0"
@@ -9908,7 +10120,7 @@
     },
     "pify": {
       "version": "2.3.0",
-      "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
     },
     "pinkie": {
@@ -9987,7 +10199,7 @@
       "dependencies": {
         "async": {
           "version": "1.5.2",
-          "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
+          "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
           "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
           "dev": true
         },
@@ -10097,7 +10309,7 @@
     },
     "postcss-import": {
       "version": "11.1.0",
-      "resolved": "http://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
       "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==",
       "dev": true,
       "requires": {
@@ -11238,7 +11450,7 @@
         },
         "htmlparser2": {
           "version": "3.3.0",
-          "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
+          "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
           "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
           "dev": true,
           "requires": {
@@ -11256,7 +11468,7 @@
         },
         "readable-stream": {
           "version": "1.0.34",
-          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
           "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
           "dev": true,
           "requires": {
@@ -12540,7 +12752,7 @@
     },
     "strip-ansi": {
       "version": "3.0.1",
-      "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
       "requires": {
         "ansi-regex": "^2.0.0"
@@ -12747,7 +12959,7 @@
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
@@ -13048,7 +13260,7 @@
     },
     "underscore.string": {
       "version": "2.4.0",
-      "resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
+      "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz",
       "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs="
     },
     "union-value": {
@@ -13502,6 +13714,16 @@
             "ms": "2.0.0"
           }
         },
+        "eslint-scope": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+          "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+          "dev": true,
+          "requires": {
+            "esrecurse": "^4.1.0",
+            "estraverse": "^4.1.1"
+          }
+        },
         "expand-brackets": {
           "version": "2.1.4",
           "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -14067,7 +14289,7 @@
           "dependencies": {
             "pify": {
               "version": "2.3.0",
-              "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+              "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
               "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
               "dev": true
             }
@@ -14332,7 +14554,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "requires": {
         "string-width": "^1.0.1",
diff --git a/package.json b/package.json
index 9453cf01..233b5b86 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "riot-web",
   "productName": "Riot",
   "main": "electron_app/src/electron-main.js",
-  "version": "0.17.6",
+  "version": "0.17.7",
   "description": "A feature-rich client for Matrix.org",
   "author": "New Vector Ltd.",
   "repository": {
@@ -70,8 +70,8 @@
     "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#b302279",
     "gfm.css": "^1.1.2",
     "highlight.js": "^9.13.1",
-    "matrix-js-sdk": "0.14.0",
-    "matrix-react-sdk": "0.14.5",
+    "matrix-js-sdk": "0.14.1",
+    "matrix-react-sdk": "0.14.6",
     "modernizr": "^3.6.0",
     "prop-types": "^15.6.2",
     "react": "^15.6.0",
@@ -84,7 +84,7 @@
     "autoprefixer": "^6.6.0",
     "babel-cli": "^6.26.0",
     "babel-core": "^6.26.3",
-    "babel-eslint": "^6.1.2",
+    "babel-eslint": "^8.1.1",
     "babel-loader": "^7.1.5",
     "babel-plugin-add-module-exports": "^0.2.1",
     "babel-plugin-transform-async-to-bluebird": "^1.1.1",
diff --git a/scripts/jenkins.sh b/scripts/jenkins.sh
index 7b5b4c8e..a0e88e4d 100755
--- a/scripts/jenkins.sh
+++ b/scripts/jenkins.sh
@@ -4,21 +4,23 @@ set -e
 
 export NVM_DIR="$HOME/.nvm"
 [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
-nvm use 6
+nvm use 10
 
 set -x
 
-# check out corresponding branches of dependencies.
-#
-# clone the deps with depth 1: we know we will only ever need that one
-# commit.
-`dirname $0`/fetch-develop.deps.sh --depth 1
-
 npm install
 
 # apparently npm 3.10.3 on node 6.4.0 doesn't upgrade #develop target with npm install unless explicitly asked.
 npm install olm
 
+# check out corresponding branches of dependencies.
+#
+# clone the deps with depth 1: we know we will only ever need that one
+# commit.
+# We need to do this after npm install otherwise modern node versions
+# just reset it back.
+`dirname $0`/fetch-develop.deps.sh --depth 1
+
 # install olm. A naive 'npm i ./olm/olm-*.tgz' fails because it uses the url
 # from our package.json (or even matrix-js-sdk's) in preference.
 #
diff --git a/src/components/structures/VectorHomePage.js b/src/components/structures/VectorHomePage.js
index 7f741303..a2e5fe05 100644
--- a/src/components/structures/VectorHomePage.js
+++ b/src/components/structures/VectorHomePage.js
@@ -17,7 +17,6 @@ limitations under the License.
 
 'use strict';
 
-import React from 'react';
 import HomePage from 'matrix-react-sdk/lib/components/structures/HomePage';
 import sanitizeHtml from 'sanitize-html';
 import { _t } from 'matrix-react-sdk/lib/languageHandler';
diff --git a/src/components/views/login/VectorCustomServerDialog.js b/src/components/views/login/VectorCustomServerDialog.js
index 8395f139..c60ff6da 100644
--- a/src/components/views/login/VectorCustomServerDialog.js
+++ b/src/components/views/login/VectorCustomServerDialog.js
@@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-var React = require("react");
-var sanitizeHtml = require("sanitize-html");
+const React = require("react");
+const sanitizeHtml = require("sanitize-html");
 import { _t } from 'matrix-react-sdk/lib/languageHandler';
 
 module.exports = React.createClass({
@@ -47,5 +47,5 @@ module.exports = React.createClass({
                 </div>
             </div>
         );
-    }
+    },
 });
diff --git a/src/components/views/login/VectorLoginFooter.js b/src/components/views/login/VectorLoginFooter.js
index 26e01c06..5fa42360 100644
--- a/src/components/views/login/VectorLoginFooter.js
+++ b/src/components/views/login/VectorLoginFooter.js
@@ -16,7 +16,7 @@ limitations under the License.
 
 'use strict';
 
-var React = require('react');
+const React = require('react');
 import { _t } from 'matrix-react-sdk/lib/languageHandler';
 import SettingsStore from 'matrix-react-sdk/lib/settings/SettingsStore';
 
@@ -29,8 +29,8 @@ module.exports = React.createClass({
     render: function() {
         // FIXME: replace this with a proper Status skin
         // ...except then we wouldn't be able to switch to the Status theme at runtime.
-        if (SettingsStore.getValue("theme") === 'status') return <div/>;
-        
+        if (SettingsStore.getValue("theme") === 'status') return <div />;
+
         return (
             <div className="mx_Login_links">
                 <a href="https://medium.com/@RiotChat">blog</a>&nbsp;&nbsp;&middot;&nbsp;&nbsp;
@@ -39,5 +39,5 @@ module.exports = React.createClass({
                 <a href="https://matrix.org">{ _t('powered by Matrix') }</a>
             </div>
         );
-    }
+    },
 });
diff --git a/src/components/views/login/VectorLoginHeader.js b/src/components/views/login/VectorLoginHeader.js
index d0ee7934..babd90d6 100644
--- a/src/components/views/login/VectorLoginHeader.js
+++ b/src/components/views/login/VectorLoginHeader.js
@@ -35,9 +35,9 @@ module.exports = React.createClass({
         return (
             <div className="mx_Login_header">
                 <div className="mx_Login_logo">
-                    <img src={this.props.icon || DEFAULT_LOGO_URI} alt="Riot"/>
+                    <img src={this.props.icon || DEFAULT_LOGO_URI} alt="Riot" />
                 </div>
             </div>
         );
-    }
+    },
 });
diff --git a/src/vector/index.js b/src/vector/index.js
index 13586cd1..67820238 100644
--- a/src/vector/index.js
+++ b/src/vector/index.js
@@ -24,6 +24,8 @@ require('gfm.css/gfm.css');
 require('highlight.js/styles/github.css');
 require('draft-js/dist/Draft.css');
 
+import './rageshakesetup';
+
 import React from 'react';
 // add React and ReactPerf to the global namespace, to make them easier to
 // access via the console
@@ -32,7 +34,7 @@ if (process.env.NODE_ENV !== 'production') {
     global.Perf = require('react-addons-perf');
 }
 
-import RunModernizrTests from './modernizr'; // this side-effects a global
+import './modernizr';
 import ReactDOM from 'react-dom';
 import sdk from 'matrix-react-sdk';
 import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
@@ -41,8 +43,6 @@ import VectorConferenceHandler from 'matrix-react-sdk/lib/VectorConferenceHandle
 import Promise from 'bluebird';
 import request from 'browser-request';
 import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
-// Also import _t directly so we can call it just `_t` as this is what gen-i18n.js expects
-import { _t } from 'matrix-react-sdk/lib/languageHandler';
 
 import url from 'url';
 
@@ -50,14 +50,12 @@ import {parseQs, parseQsFromFragment} from './url_utils';
 import Platform from './platform';
 
 import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
-import SettingsStore, {SettingLevel} from "matrix-react-sdk/lib/settings/SettingsStore";
+import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
 import Tinter from 'matrix-react-sdk/lib/Tinter';
 import SdkConfig from "matrix-react-sdk/lib/SdkConfig";
 
 import Olm from 'olm';
 
-import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
-
 import CallHandler from 'matrix-react-sdk/lib/CallHandler';
 
 import {getVectorConfig} from './getconfig';
@@ -68,33 +66,17 @@ let lastLocationHashSet = null;
 // and need to migrate, but they spam the console with warnings.
 Promise.config({warnings: false});
 
-function initRageshake() {
-    rageshake.init().then(() => {
-        console.log("Initialised rageshake: See https://bugs.chromium.org/p/chromium/issues/detail?id=583193 to fix line numbers on Chrome.");
-
-        window.addEventListener('beforeunload', (e) => {
-            console.log('riot-web closing');
-            // try to flush the logs to indexeddb
-            rageshake.flush();
-        });
-
-        rageshake.cleanup();
-    }, (err) => {
-        console.error("Failed to initialise rageshake: " + err);
-    });
-}
-
 function checkBrowserFeatures(featureList) {
     if (!window.Modernizr) {
         console.error("Cannot check features - Modernizr global is missing.");
         return false;
     }
-    var featureComplete = true;
-    for (var i = 0; i < featureList.length; i++) {
+    let featureComplete = true;
+    for (let i = 0; i < featureList.length; i++) {
         if (window.Modernizr[featureList[i]] === undefined) {
             console.error(
                 "Looked for feature '%s' but Modernizr has no results for this. " +
-                "Has it been configured correctly?", featureList[i]
+                "Has it been configured correctly?", featureList[i],
             );
             return false;
         }
@@ -115,7 +97,7 @@ function getScreenFromLocation(location) {
     return {
         screen: fragparts.location.substring(1),
         params: fragparts.params,
-    }
+    };
 }
 
 // Here, we do some crude URL analysis to allow
@@ -140,10 +122,10 @@ function onHashChange(ev) {
 // so a web page can update the URL bar appropriately.
 function onNewScreen(screen) {
     console.log("newscreen "+screen);
-    var hash = '#/' + screen;
+    const hash = '#/' + screen;
     lastLocationHashSet = hash;
     window.location.hash = hash;
-};
+}
 
 // We use this to work out what URL the SDK should
 // pass through when registering to allow the user to
@@ -180,7 +162,7 @@ function makeRegistrationUrl(params) {
     return url;
 }
 
-function getConfig(configJsonFilename) {
+export function getConfig(configJsonFilename) {
     return new Promise(function(resolve, reject) {
         request(
             { method: "GET", url: configJsonFilename },
@@ -216,16 +198,15 @@ function onTokenLoginCompleted() {
     // if we did a token login, we're now left with the token, hs and is
     // url as query params in the url; a little nasty but let's redirect to
     // clear them.
-    var parsedUrl = url.parse(window.location.href);
+    const parsedUrl = url.parse(window.location.href);
     parsedUrl.search = "";
-    var formatted = url.format(parsedUrl);
+    const formatted = url.format(parsedUrl);
     console.log("Redirecting to " + formatted + " to drop loginToken " +
                 "from queryparams");
     window.location.href = formatted;
 }
 
 async function loadApp() {
-    initRageshake();
     MatrixClientPeg.setIndexedDbWorkerScript(window.vector_indexeddb_worker_script);
     CallHandler.setConferenceHandler(VectorConferenceHandler);
 
@@ -273,7 +254,6 @@ async function loadApp() {
     }
 
     // as quickly as we possibly can, set a default theme...
-    const styleElements = Object.create(null);
     let a;
     const theme = "dharma";//SettingsStore.getValue("theme");
     for (let i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
@@ -297,7 +277,7 @@ async function loadApp() {
                 // in case it is the first time loading Riot.
                 // `InstallTrigger` is a Object which only exists on Firefox
                 // (it is used for their Plugins) and can be used as a
-                // feature check. 
+                // feature check.
                 // Firefox loads css always before js. This is why we dont use
                 // onload or it's EventListener as thoose will never trigger.
                 if (typeof InstallTrigger !== 'undefined') {
@@ -349,19 +329,19 @@ async function loadApp() {
                 initialScreenAfterLogin={getScreenFromLocation(window.location)}
                 defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
             />,
-            document.getElementById('matrixchat')
+            document.getElementById('matrixchat'),
         );
     } else {
         console.error("Browser is missing required features.");
         // take to a different landing page to AWOOOOOGA at the user
-        var CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
+        const CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
         window.matrixChat = ReactDOM.render(
             <CompatibilityPage onAccept={function() {
                 if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
                 console.log("User accepts the compatibility risks.");
                 loadApp();
             }} />,
-            document.getElementById('matrixchat')
+            document.getElementById('matrixchat'),
         );
     }
 }
diff --git a/src/vector/indexeddb-worker.js b/src/vector/indexeddb-worker.js
index 2e94509a..ff0d8f79 100644
--- a/src/vector/indexeddb-worker.js
+++ b/src/vector/indexeddb-worker.js
@@ -18,4 +18,4 @@ import {IndexedDBStoreWorker} from 'matrix-js-sdk/lib/indexeddb-worker.js';
 
 const remoteWorker = new IndexedDBStoreWorker(postMessage);
 
-onmessage = remoteWorker.onMessage;
+export const onmessage = remoteWorker.onMessage;
diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js
index 5ced2a2a..8b384b20 100644
--- a/src/vector/platform/ElectronPlatform.js
+++ b/src/vector/platform/ElectronPlatform.js
@@ -27,7 +27,7 @@ import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
 remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
 
 // try to flush the rageshake logs to indexeddb before quit.
-ipcRenderer.on('before-quit', function () {
+ipcRenderer.on('before-quit', function() {
     console.log('riot-desktop closing');
     rageshake.flush();
 });
diff --git a/src/vector/platform/VectorBasePlatform.js b/src/vector/platform/VectorBasePlatform.js
index 4bf300a5..16b9d178 100644
--- a/src/vector/platform/VectorBasePlatform.js
+++ b/src/vector/platform/VectorBasePlatform.js
@@ -60,8 +60,8 @@ export default class VectorBasePlatform extends BasePlatform {
             // This needs to be in in a try block as it will throw
             // if there are more than 100 badge count changes in
             // its internal queue
-            let bgColor = "#d00",
-                notif = this.notificationCount;
+            let bgColor = "#d00";
+            let notif = this.notificationCount;
 
             if (this.errorDidOccur) {
                 notif = notif || "×";
@@ -114,7 +114,7 @@ export default class VectorBasePlatform extends BasePlatform {
         dis.dispatch({
             action: 'check_updates',
             value: false,
-        })
+        });
     }
 
     getUpdateCheckStatusEnum() {
diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js
index cfe51346..2955b84a 100644
--- a/src/vector/platform/WebPlatform.js
+++ b/src/vector/platform/WebPlatform.js
@@ -26,7 +26,7 @@ import Promise from 'bluebird';
 import url from 'url';
 import UAParser from 'ua-parser-js';
 
-var POKE_RATE_MS = 10 * 60 * 1000; // 10 min
+const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
 
 export default class WebPlatform extends VectorBasePlatform {
     constructor() {
diff --git a/src/vector/rageshakesetup.js b/src/vector/rageshakesetup.js
new file mode 100644
index 00000000..b240e159
--- /dev/null
+++ b/src/vector/rageshakesetup.js
@@ -0,0 +1,46 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/*
+ * Separate file that sets up rageshake logging when imported.
+ * This is necessary so that rageshake logging is set up before
+ * anything else. Webpack puts all import statements at the top
+ * of the file before any code, so imports will always be
+ * evaluated first. Other imports can cause other code to be
+ * evaluated (eg. the loglevel library in js-sdk, which if set
+ * up before rageshake causes some js-sdk logging to be missing
+ * from the rageshake.)
+ */
+
+import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
+
+function initRageshake() {
+    rageshake.init().then(() => {
+        console.log("Initialised rageshake: See https://bugs.chromium.org/p/chromium/issues/detail?id=583193 to fix line numbers on Chrome.");
+
+        window.addEventListener('beforeunload', (e) => {
+            console.log('riot-web closing');
+            // try to flush the logs to indexeddb
+            rageshake.flush();
+        });
+
+        rageshake.cleanup();
+    }, (err) => {
+        console.error("Failed to initialise rageshake: " + err);
+    });
+}
+
+initRageshake();
diff --git a/src/vector/url_utils.js b/src/vector/url_utils.js
index cfa8eae1..cbaefa0c 100644
--- a/src/vector/url_utils.js
+++ b/src/vector/url_utils.js
@@ -23,16 +23,16 @@ import qs from 'querystring';
 export function parseQsFromFragment(location) {
     // if we have a fragment, it will start with '#', which we need to drop.
     // (if we don't, this will return '').
-    var fragment = location.hash.substring(1);
+    const fragment = location.hash.substring(1);
 
     // our fragment may contain a query-param-like section. we need to fish
     // this out *before* URI-decoding because the params may contain ? and &
     // characters which are only URI-encoded once.
-    var hashparts = fragment.split('?');
+    const hashparts = fragment.split('?');
 
-    var result = {
+    const result = {
         location: decodeURIComponent(hashparts[0]),
-        params: {}
+        params: {},
     };
 
     if (hashparts.length > 1) {
diff --git a/test/all-tests.js b/test/all-tests.js
index 2ed16932..156b8542 100644
--- a/test/all-tests.js
+++ b/test/all-tests.js
@@ -6,8 +6,8 @@
 // ideally these unit tests could be run under nodejs rather than in a browser
 // via karma, but having two separate test frameworks in the same project
 // seems confusing
-var unit_tests = require.context('./unit-tests', true, /\.js$/);
+const unit_tests = require.context('./unit-tests', true, /\.js$/);
 unit_tests.keys().forEach(unit_tests);
 
-var app_tests = require.context('./app-tests', true, /\.jsx?$/);
+const app_tests = require.context('./app-tests', true, /\.jsx?$/);
 app_tests.keys().forEach(app_tests);
diff --git a/test/app-tests/joining.js b/test/app-tests/joining.js
index fc380e7d..60bf3fd3 100644
--- a/test/app-tests/joining.js
+++ b/test/app-tests/joining.js
@@ -21,36 +21,36 @@ import Platform from '../../src/vector/platform';
 
 require('skin-sdk');
 
-var jssdk = require('matrix-js-sdk');
+const jssdk = require('matrix-js-sdk');
 
-var sdk = require('matrix-react-sdk');
-var peg = require('matrix-react-sdk/lib/MatrixClientPeg');
-var dis = require('matrix-react-sdk/lib/dispatcher');
-var PageTypes = require('matrix-react-sdk/lib/PageTypes');
-var MatrixChat = sdk.getComponent('structures.MatrixChat');
-var RoomDirectory = sdk.getComponent('structures.RoomDirectory');
-var RoomPreviewBar = sdk.getComponent('rooms.RoomPreviewBar');
-var RoomView = sdk.getComponent('structures.RoomView');
+const sdk = require('matrix-react-sdk');
+const peg = require('matrix-react-sdk/lib/MatrixClientPeg');
+const dis = require('matrix-react-sdk/lib/dispatcher');
+const PageTypes = require('matrix-react-sdk/lib/PageTypes');
+const MatrixChat = sdk.getComponent('structures.MatrixChat');
+const RoomDirectory = sdk.getComponent('structures.RoomDirectory');
+const RoomPreviewBar = sdk.getComponent('rooms.RoomPreviewBar');
+const RoomView = sdk.getComponent('structures.RoomView');
 
-var React = require('react');
-var ReactDOM = require('react-dom');
-var ReactTestUtils = require('react-addons-test-utils');
-var expect = require('expect');
+const React = require('react');
+const ReactDOM = require('react-dom');
+const ReactTestUtils = require('react-addons-test-utils');
+const expect = require('expect');
 import Promise from 'bluebird';
 
-var test_utils = require('../test-utils');
-var MockHttpBackend = require('matrix-mock-request');
+const test_utils = require('../test-utils');
+const MockHttpBackend = require('matrix-mock-request');
 
-var HS_URL='http://localhost';
-var IS_URL='http://localhost';
-var USER_ID='@me:localhost';
-var ACCESS_TOKEN='access_token';
+const HS_URL='http://localhost';
+const IS_URL='http://localhost';
+const USER_ID='@me:localhost';
+const ACCESS_TOKEN='access_token';
 
-describe('joining a room', function () {
-    describe('over federation', function () {
-        var parentDiv;
-        var httpBackend;
-        var matrixChat;
+describe('joining a room', function() {
+    describe('over federation', function() {
+        let parentDiv;
+        let httpBackend;
+        let matrixChat;
 
         beforeEach(function() {
             test_utils.beforeEach(this);
@@ -72,8 +72,8 @@ describe('joining a room', function () {
         });
 
         it('should not get stuck at a spinner', function() {
-            var ROOM_ALIAS = '#alias:localhost';
-            var ROOM_ID = '!id:localhost';
+            const ROOM_ALIAS = '#alias:localhost';
+            const ROOM_ID = '!id:localhost';
 
             httpBackend.when('GET', '/pushrules').respond(200, {});
             httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
@@ -90,7 +90,7 @@ describe('joining a room', function () {
 
             PlatformPeg.set(new Platform());
 
-            var mc = (
+            const mc = (
                 <MatrixChat config={{}}
                     makeRegistrationUrl={()=>{throw new Error("unimplemented");}}
                     initialScreenAfterLogin={{
@@ -100,7 +100,7 @@ describe('joining a room', function () {
             );
             matrixChat = ReactDOM.render(mc, parentDiv);
 
-            var roomView;
+            let roomView;
 
             // wait for /sync to happen. This may take some time, as the client
             // has to initialise indexeddb.
@@ -118,11 +118,11 @@ describe('joining a room', function () {
             }).then(() => {
                 console.log(`${Date.now()} App made requests for directory view; switching to a room.`);
 
-                var roomDir = ReactTestUtils.findRenderedComponentWithType(
+                const roomDir = ReactTestUtils.findRenderedComponentWithType(
                     matrixChat, RoomDirectory);
 
                 // enter an alias in the input, and simulate enter
-                var input = ReactTestUtils.findRenderedDOMComponentWithTag(
+                const input = ReactTestUtils.findRenderedDOMComponentWithTag(
                     roomDir, 'input');
                 input.value = ROOM_ALIAS;
                 ReactTestUtils.Simulate.change(input);
diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js
index dab61657..676475b6 100644
--- a/test/app-tests/loading.js
+++ b/test/app-tests/loading.js
@@ -40,10 +40,10 @@ import * as test_utils from '../test-utils';
 import MockHttpBackend from 'matrix-mock-request';
 import {parseQs, parseQsFromFragment} from '../../src/vector/url_utils';
 
-var DEFAULT_HS_URL='http://my_server';
-var DEFAULT_IS_URL='http://my_is';
+const DEFAULT_HS_URL='http://my_server';
+const DEFAULT_IS_URL='http://my_is';
 
-describe('loading:', function () {
+describe('loading:', function() {
     let parentDiv;
     let httpBackend;
 
@@ -74,7 +74,7 @@ describe('loading:', function () {
         });
     });
 
-    afterEach(async function () {
+    afterEach(async function() {
         console.log(`${Date.now()}: loading: afterEach`);
         if (parentDiv) {
             ReactDOM.unmountComponentAtNode(parentDiv);
@@ -112,12 +112,12 @@ describe('loading:', function () {
             toString: function() { return this.search + this.hash; },
         };
 
-        let tokenLoginCompleteDefer = Promise.defer();
+        const tokenLoginCompleteDefer = Promise.defer();
         tokenLoginCompletePromise = tokenLoginCompleteDefer.promise;
 
         function onNewScreen(screen) {
             console.log(Date.now() + " newscreen "+screen);
-            var hash = '#/' + screen;
+            const hash = '#/' + screen;
             windowLocation.hash = hash;
             console.log(Date.now() + " browser URI now "+ windowLocation);
         }
@@ -129,7 +129,7 @@ describe('loading:', function () {
             return {
                 screen: fragparts.location.substring(1),
                 params: fragparts.params,
-            }
+            };
         }
 
         const MatrixChat = sdk.getComponent('structures.MatrixChat');
@@ -142,7 +142,7 @@ describe('loading:', function () {
 
         PlatformPeg.set(new Platform());
 
-        var params = parseQs(windowLocation);
+        const params = parseQs(windowLocation);
         matrixChat = ReactDOM.render(
             <MatrixChat
                 onNewScreen={onNewScreen}
@@ -153,7 +153,7 @@ describe('loading:', function () {
                 onTokenLoginCompleted={() => tokenLoginCompleteDefer.resolve()}
                 initialScreenAfterLogin={getScreenFromLocation(windowLocation)}
                 makeRegistrationUrl={() => {throw new Error('Not implemented');}}
-            />, parentDiv
+            />, parentDiv,
         );
     }
 
@@ -179,7 +179,7 @@ describe('loading:', function () {
     }
 
     describe("Clean load with no stored credentials:", function() {
-        it('gives a login panel by default', function (done) {
+        it('gives a login panel by default', function(done) {
             loadApp();
 
             Promise.delay(1).then(() => {
@@ -257,7 +257,6 @@ describe('loading:', function () {
                 }
                 return completeLogin(matrixChat);
             }).then(() => {
-
                 // once the sync completes, we should have a room view
                 ReactTestUtils.findRenderedComponentWithType(
                     matrixChat, sdk.getComponent('structures.HomePage'));
@@ -356,7 +355,7 @@ describe('loading:', function () {
                 });
                 return httpBackend.flush();
             }).then(() => {
-                return awaitSyncingSpinner(matrixChat)
+                return awaitSyncingSpinner(matrixChat);
             }).then(() => {
                 // we got a sync spinner - let the sync complete
                 return expectAndAwaitSync();
@@ -380,7 +379,7 @@ describe('loading:', function () {
             it('shows a login view', function() {
                 // we expect a single <Login> component
                 ReactTestUtils.findRenderedComponentWithType(
-                    matrixChat, sdk.getComponent('structures.login.Login')
+                    matrixChat, sdk.getComponent('structures.login.Login'),
                 );
 
                 // the only outstanding request should be a GET /login
@@ -408,7 +407,7 @@ describe('loading:', function () {
     });
 
     describe('Guest auto-registration:', function() {
-        it('shows a home page by default', function (done) {
+        it('shows a home page by default', function(done) {
             loadApp();
 
             Promise.delay(1).then(() => {
@@ -438,7 +437,7 @@ describe('loading:', function () {
             }).done(done, done);
         });
 
-        it('uses the last known homeserver to register with', function (done) {
+        it('uses the last known homeserver to register with', function(done) {
             localStorage.setItem("mx_hs_url", "https://homeserver" );
             localStorage.setItem("mx_is_url", "https://idserver" );
 
@@ -477,7 +476,7 @@ describe('loading:', function () {
 
         it('shows a room view if we followed a room link', function(done) {
             loadApp({
-                uriFragment: "#/room/!room:id"
+                uriFragment: "#/room/!room:id",
             });
             Promise.delay(1).then(() => {
                 // at this point, we're trying to do a guest registration;
@@ -547,7 +546,7 @@ describe('loading:', function () {
 
                 // we expect a single <Login> component
                 ReactTestUtils.findRenderedComponentWithType(
-                    matrixChat, sdk.getComponent('structures.login.Login')
+                    matrixChat, sdk.getComponent('structures.login.Login'),
                 );
             });
 
@@ -580,7 +579,7 @@ describe('loading:', function () {
     });
 
     describe('Token login:', function() {
-        it('logs in successfully', function (done) {
+        it('logs in successfully', function(done) {
             loadApp({
                 queryString: "?loginToken=secretToken&homeserver=https%3A%2F%2Fhomeserver&identityServer=https%3A%2F%2Fidserver",
             });
@@ -658,7 +657,7 @@ describe('loading:', function () {
 
 // assert that we are on the loading page
 function assertAtLoadingSpinner(matrixChat) {
-    var domComponent = ReactDOM.findDOMNode(matrixChat);
+    const domComponent = ReactDOM.findDOMNode(matrixChat);
     expect(domComponent.className).toEqual("mx_MatrixChat_splash");
 
     // just the spinner
@@ -697,12 +696,12 @@ function awaitSyncingSpinner(matrixChat, retryLimit, retryCount) {
 }
 
 function assertAtSyncingSpinner(matrixChat) {
-    var domComponent = ReactDOM.findDOMNode(matrixChat);
+    const domComponent = ReactDOM.findDOMNode(matrixChat);
     expect(domComponent.className).toEqual("mx_MatrixChat_splash");
 
     ReactTestUtils.findRenderedComponentWithType(
         matrixChat, sdk.getComponent('elements.Spinner'));
-    var logoutLink = ReactTestUtils.findRenderedDOMComponentWithTag(
+    const logoutLink = ReactTestUtils.findRenderedDOMComponentWithTag(
         matrixChat, 'a');
     expect(logoutLink.text).toEqual("Logout");
 }
diff --git a/test/skin-sdk.js b/test/skin-sdk.js
index 3421d5d0..b839df8f 100644
--- a/test/skin-sdk.js
+++ b/test/skin-sdk.js
@@ -4,5 +4,5 @@
  * Skins the react-sdk with the vector components
  */
 
-var sdk = require('matrix-react-sdk');
+const sdk = require('matrix-react-sdk');
 sdk.loadSkin(require('../src/component-index'));
diff --git a/test/test-utils.js b/test/test-utils.js
index a5b22feb..4e07be14 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -8,7 +8,7 @@ import Promise from 'bluebird';
  * @param {Mocha.Context} context  The test context
  */
 export function beforeEach(context) {
-    var desc = context.currentTest.fullTitle();
+    const desc = context.currentTest.fullTitle();
     console.log();
     console.log(desc);
     console.log(new Array(1 + desc.length).join("="));
@@ -22,7 +22,7 @@ export function beforeEach(context) {
  * returns true if the current environment supports webrtc
  */
 export function browserSupportsWebRTC() {
-    var n = global.window.navigator;
+    const n = global.window.navigator;
     return n.getUserMedia || n.webkitGetUserMedia ||
         n.mozGetUserMedia;
 }