Add HashRouter for downloadable version (#651)

* Update TODO comments & Remove old TODO comments

* Fix undefined bityRate pair

* Add HashRouter

* Update publicPath

* Use HashRouter only if site is downloaded

* Update conditions for router

* Update asset paths & Change publicPath in production

* Remove hoist-non-react-statistics

* Add hoist-non-react-statics as dev depencency

* Lock hoist-non-react-statics version

* Add webpack-include-assets & favicon-webpack plugins

* Add env var BUILD_DOWNLOADABLE

* Make app aware of its serving location

* Remove downloadable plugin
This commit is contained in:
James Prado 2017-12-30 11:22:28 -05:00 committed by Daniel Ternyak
parent 80225b7680
commit 78e3bcd7c1
6 changed files with 60 additions and 78 deletions

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { withRouter, Switch, Redirect, Router, Route } from 'react-router-dom'; import { withRouter, Switch, Redirect, HashRouter, Route, BrowserRouter } from 'react-router-dom';
// Components // Components
import Contracts from 'containers/Tabs/Contracts'; import Contracts from 'containers/Tabs/Contracts';
import ENS from 'containers/Tabs/ENS'; import ENS from 'containers/Tabs/ENS';
@ -15,7 +15,6 @@ import ErrorScreen from 'components/ErrorScreen';
// TODO: fix this // TODO: fix this
interface Props { interface Props {
store: any; store: any;
history: any;
} }
interface State { interface State {
@ -32,7 +31,7 @@ export default class Root extends Component<Props, State> {
} }
public render() { public render() {
const { store, history } = this.props; const { store } = this.props;
const { error } = this.state; const { error } = this.state;
if (error) { if (error) {
@ -40,29 +39,34 @@ export default class Root extends Component<Props, State> {
} }
// key={Math.random()} = hack for HMR from https://github.com/webpack/webpack-dev-server/issues/395 // key={Math.random()} = hack for HMR from https://github.com/webpack/webpack-dev-server/issues/395
const routes = (
<div>
<Route exact={true} path="/" component={GenerateWallet} />
<Route path="/generate" component={GenerateWallet}>
<Route path="keystore" component={GenerateWallet} />
<Route path="mnemonic" component={GenerateWallet} />
</Route>
<Route path="/help" component={Help} />
<Route path="/swap" component={Swap} />
<Route path="/account" component={SendTransaction}>
<Route path="send" component={SendTransaction} />
<Route path="info" component={SendTransaction} />
</Route>
<Route path="/send-transaction" component={SendTransaction} />
<Route path="/contracts" component={Contracts} />
<Route path="/ens" component={ENS} />
<Route path="/sign-and-verify-message" component={SignAndVerifyMessage} />
<Route path="/pushTx" component={BroadcastTx} />
<LegacyRoutes />
</div>
);
return ( return (
<Provider store={store} key={Math.random()}> <Provider store={store} key={Math.random()}>
<Router history={history} key={Math.random()}> {process.env.BUILD_DOWNLOADABLE ? (
<div> <HashRouter key={Math.random()}>{routes}</HashRouter>
<Route exact={true} path="/" component={GenerateWallet} /> ) : (
<Route path="/generate" component={GenerateWallet}> <BrowserRouter key={Math.random()}>{routes}</BrowserRouter>
<Route path="keystore" component={GenerateWallet} /> )}
<Route path="mnemonic" component={GenerateWallet} />
</Route>
<Route path="/help" component={Help} />
<Route path="/swap" component={Swap} />
<Route path="/account" component={SendTransaction}>
<Route path="send" component={SendTransaction} />
<Route path="info" component={SendTransaction} />
</Route>
<Route path="/send-transaction" component={SendTransaction} />
<Route path="/contracts" component={Contracts} />
<Route path="/ens" component={ENS} />
<Route path="/sign-and-verify-message" component={SignAndVerifyMessage} />
<Route path="/pushTx" component={BroadcastTx} />
<LegacyRoutes />
</div>
</Router>
</Provider> </Provider>
); );
} }

View File

@ -8,15 +8,7 @@
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="/dll.vendor.js"></script>
<link rel="manifest" href="/manifest.json"> <link rel="manifest" href="/manifest.json">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/favicon/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicon/favicon-16x16.png" sizes="16x16">
<link rel="mask-icon" href="favicon/safari-pinned-tab.svg" color="#0e97c0">
<meta name="msapplication-config" content="/favicon/browserconfig.xml">
<meta name="theme-color" content="#163151">
</head> </head>
<body> <body>
@ -26,13 +18,11 @@
<div class="NoScript-content"> <div class="NoScript-content">
<h2>You Must Enable Javascript to Continue</h2> <h2>You Must Enable Javascript to Continue</h2>
<p> <p>
MyEtherWallet requires Javascript to run. There are no security MyEtherWallet requires Javascript to run. There are no security vulnerabilities as a result of enabling Javascript on MyEtherWallet,
vulnerabilities as a result of enabling Javascript on MyEtherWallet, as as we do not load any external scripts such as advertisements or trackers.
we do not load any external scripts such as advertisements or trackers.
</p> </p>
<p> <p>
If you are not sure why you are seeing this message, or are unsure of If you are not sure why you are seeing this message, or are unsure of how to enable Javascript, please visit
how to enable Javascript, please visit
<a href="https://www.enable-javascript.com/" rel="noopener" target="_blank">enable-javascript.com</a> <a href="https://www.enable-javascript.com/" rel="noopener" target="_blank">enable-javascript.com</a>
to learn more. to learn more.
</p> </p>
@ -43,43 +33,27 @@
<div class="BadBrowser-content"> <div class="BadBrowser-content">
<h2>Your Browser is Out of Date</h2> <h2>Your Browser is Out of Date</h2>
<p class="is-desktop"> <p class="is-desktop">
MyEtherWallet requires certain features that your browser doesn't offer. MyEtherWallet requires certain features that your browser doesn't offer. Your browser may also be missing security updates
Your browser may also be missing security updates that could open you up that could open you up to vulnerabilities. Please update your browser, or switch to one of the following browsers
to vulnerabilities. Please update your browser, or switch to one of the ones to continue using MyEtherWallet.
following browsers ones to continue using MyEtherWallet.
</p> </p>
<p class="is-mobile"> <p class="is-mobile">
MyEtherWallet requires certain features that your browser doesn't offer. MyEtherWallet requires certain features that your browser doesn't offer. Please use your device's default browser, or switch
Please use your device's default browser, or switch to a laptop or to a laptop or computer to continue using MyEtherWallet.
computer to continue using MyEtherWallet.
</p> </p>
<div class="BadBrowser-content-browsers is-desktop"> <div class="BadBrowser-content-browsers is-desktop">
<a <a class="BadBrowser-content-browsers-browser firefox" href="https://www.mozilla.org/en-US/firefox/new/" rel="noopener" target="_blank">
class="BadBrowser-content-browsers-browser firefox"
href="https://www.mozilla.org/en-US/firefox/new/"
rel="noopener"
target="_blank"
>
<span class="BadBrowser-content-browsers-browser-name"> <span class="BadBrowser-content-browsers-browser-name">
Firefox Firefox
</span> </span>
</a> </a>
<a <a class="BadBrowser-content-browsers-browser chrome" href="https://www.google.com/chrome/browser/desktop/index.html" rel="noopener"
class="BadBrowser-content-browsers-browser chrome" target="_blank">
href="https://www.google.com/chrome/browser/desktop/index.html"
rel="noopener"
target="_blank"
>
<span class="BadBrowser-content-browsers-browser-name"> <span class="BadBrowser-content-browsers-browser-name">
Chrome Chrome
</span> </span>
</a> </a>
<a <a class="BadBrowser-content-browsers-browser opera" href="http://www.opera.com/" rel="noopener" target="_blank">
class="BadBrowser-content-browsers-browser opera"
href="http://www.opera.com/"
rel="noopener"
target="_blank"
>
<span class="BadBrowser-content-browsers-browser-name"> <span class="BadBrowser-content-browsers-browser-name">
Opera Opera
</span> </span>
@ -89,7 +63,7 @@
</div> </div>
<script> <script>
(function() { (function () {
var badBrowser = false; var badBrowser = false;
try { try {
@ -124,4 +98,4 @@
</script> </script>
</body> </body>
</html> </html>

View File

@ -7,21 +7,18 @@ import 'whatwg-fetch';
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
import Root from './Root'; import Root from './Root';
import createHistory from 'history/createBrowserHistory';
import { configuredStore } from './store'; import { configuredStore } from './store';
import consoleAdvertisement from './utils/consoleAdvertisement'; import consoleAdvertisement from './utils/consoleAdvertisement';
const history = createHistory();
const appEl = document.getElementById('app'); const appEl = document.getElementById('app');
render(<Root store={configuredStore} history={history} />, appEl); render(<Root store={configuredStore} />, appEl);
if (module.hot) { if (module.hot) {
module.hot.accept('reducers', () => configuredStore.replaceReducer(require('reducers'))); module.hot.accept('reducers', () => configuredStore.replaceReducer(require('reducers')));
module.hot.accept('./Root', () => { module.hot.accept('./Root', () => {
render(<Root store={configuredStore} history={history} />, appEl); render(<Root store={configuredStore} />, appEl);
}); });
} }

View File

@ -75,9 +75,12 @@
"enzyme-to-json": "3.3.0", "enzyme-to-json": "3.3.0",
"express": "4.16.2", "express": "4.16.2",
"extract-text-webpack-plugin": "3.0.2", "extract-text-webpack-plugin": "3.0.2",
"favicons-webpack-plugin": "0.0.7",
"file-loader": "1.1.6", "file-loader": "1.1.6",
"friendly-errors-webpack-plugin": "1.6.1", "friendly-errors-webpack-plugin": "1.6.1",
"glob": "7.1.2", "glob": "7.1.2",
"hoist-non-react-statics": "2.3.1",
"html-webpack-include-assets-plugin": "1.0.2",
"html-webpack-plugin": "2.30.1", "html-webpack-plugin": "2.30.1",
"husky": "0.14.3", "husky": "0.14.3",
"image-webpack-loader": "3.4.2", "image-webpack-loader": "3.4.2",
@ -118,7 +121,7 @@
"db": "nodemon ./db", "db": "nodemon ./db",
"build": "webpack --config webpack_config/webpack.prod.js", "build": "webpack --config webpack_config/webpack.prod.js",
"prebuild": "check-node-version --package", "prebuild": "check-node-version --package",
"build:demo": "BUILD_GH_PAGES=true webpack --config webpack_config/webpack.prod.js", "build:downloadable": "BUILD_DOWNLOADABLE=true webpack --config webpack_config/webpack.prod.js",
"prebuild:demo": "check-node-version --package", "prebuild:demo": "check-node-version --package",
"test:coverage": "jest --config=jest_config/jest.config.json --coverage", "test:coverage": "jest --config=jest_config/jest.config.json --coverage",
"test": "jest --config=jest_config/jest.config.json", "test": "jest --config=jest_config/jest.config.json",
@ -135,7 +138,8 @@
"postinstall": "webpack --config=./webpack_config/webpack.dll.js", "postinstall": "webpack --config=./webpack_config/webpack.dll.js",
"start": "npm run dev", "start": "npm run dev",
"precommit": "lint-staged", "precommit": "lint-staged",
"formatAll": "find ./common/ -name '*.ts*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override", "formatAll":
"find ./common/ -name '*.ts*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override",
"prepush": "npm run tslint && npm run tscheck" "prepush": "npm run tslint && npm run tscheck"
}, },
"lint-staged": { "lint-staged": {

View File

@ -4,7 +4,7 @@ const path = require('path');
module.exports = { module.exports = {
port: process.env.HTTPS ? 3443 : 3000, port: process.env.HTTPS ? 3443 : 3000,
title: 'MEW', title: 'MEW',
publicPath: process.env.BUILD_GH_PAGES ? '/react-semantic.ui-starter/' : '/', publicPath: process.env.BUILD_DOWNLOADABLE ? './' : '/',
srcPath: path.join(__dirname, './../common'), srcPath: path.join(__dirname, './../common'),
// add these dependencies to a standalone vendor bundle // add these dependencies to a standalone vendor bundle
vendor: [ vendor: [
@ -28,11 +28,7 @@ module.exports = {
quality: 80 quality: 80
}, },
svgo: { svgo: {
plugins: [ plugins: [{ removeViewBox: true }, { removeEmptyAttrs: false }, { sortAttrs: true }]
{ removeViewBox: true },
{ removeEmptyAttrs: false },
{ sortAttrs: true }
]
} }
} }
}; };

View File

@ -3,6 +3,8 @@ const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const HtmlWebpackIncludeAssetsPlugin = require('html-webpack-include-assets-plugin');
const config = require('./config'); const config = require('./config');
const _ = require('./utils'); const _ = require('./utils');
const { CheckerPlugin } = require('awesome-typescript-loader'); const { CheckerPlugin } = require('awesome-typescript-loader');
@ -64,13 +66,18 @@ module.exports = {
}, },
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env.BUILD_GH_PAGES': JSON.stringify(!!process.env.BUILD_GH_PAGES) 'process.env.BUILD_DOWNLOADABLE': JSON.stringify(!!process.env.BUILD_DOWNLOADABLE)
}), }),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
title: config.title, title: config.title,
template: path.resolve(__dirname, '../common/index.html'), template: path.resolve(__dirname, '../common/index.html'),
filename: _.outputIndexPath filename: _.outputIndexPath
}), }),
new HtmlWebpackIncludeAssetsPlugin({ assets: ['dll.vendor.js'], append: false }),
new FaviconsWebpackPlugin({
logo: path.resolve(__dirname, '../static/favicon/android-chrome-384x384.png'),
background: '#163151'
}),
new webpack.LoaderOptionsPlugin(_.loadersOptions()), new webpack.LoaderOptionsPlugin(_.loadersOptions()),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
{ {