Webpack Upgrade (#665)

* Update TODO comments & Remove old TODO comments

* Fix undefined bityRate pair

* Fix any props in TODO

* Add HashRouter

* Update publicPath

* Revert "Update publicPath"

This reverts commit 1ab9068df4d570cf50bc4f2fcd97bd775e9aa768.

* Use HashRouter only if site is downloaded

* Update conditions for router

* Update asset paths & Change publicPath in production

* Remove hoist-non-react-statistics

* Revert "Remove hoist-non-react-statistics"

This reverts commit abc017a3f3ca1a00bebdd9201f0d18770581d8c5.

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

* Initial tests

* Lock hoist-non-react-statics version

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

* Add env var BUILD_DOWNLOADABLE

* Remove dll from prod build

* Speed up rebuild times

* Change var to const

* lodash tree-shacking finagling

* Make app aware of its serving location

* Fix failing test

* Remove downloadable plugin

* Merge hash-router and get build working

* Add missing package.

* Make app aware of its serving location

* Revert "Make app aware of its serving location"

This reverts commit 8dae3b399e0392272cde25d45443391f6fb6594e.

* Revert "Remove downloadable plugin"

* Move AutoDLLPlugin to be in dev only

* Remove require HtmlWebpackIncludeAssetsPlugin

* Remove extra file added

* Bring config up to date with webpack 2 rules, add multi threading and proper cache busting

* Fix favicons package from freezing build process

* Make exclude rules more simple

* update freezer webpack config

* Move webpack multithreading to full source map dev builds only

* update freezer webpack config (#687)

* Add HtmlWebpackIncludeAssetsPlugin
This commit is contained in:
HenryNguyen5 2017-12-30 15:29:04 -05:00 committed by Daniel Ternyak
parent 170dc64284
commit 616928c085
18 changed files with 162 additions and 134 deletions

View File

@ -11,10 +11,11 @@ import Swap from 'containers/Tabs/Swap';
import SignAndVerifyMessage from 'containers/Tabs/SignAndVerifyMessage';
import BroadcastTx from 'containers/Tabs/BroadcastTx';
import ErrorScreen from 'components/ErrorScreen';
import { Store } from 'redux';
import { AppState } from 'reducers';
// TODO: fix this
interface Props {
store: any;
store: Store<AppState>;
}
interface State {

View File

@ -1,4 +1,4 @@
import { indexOf } from 'lodash';
import indexOf from 'lodash/indexOf';
export const filter = (i: any, arr: any[]) => {
return -1 !== indexOf(arr, i) ? true : false;

View File

@ -7,7 +7,8 @@ import translate from 'translations';
import { combineAndUpper } from 'utils/formatters';
import { Dropdown } from 'components/ui';
import Spinner from 'components/ui/Spinner';
import { without, intersection } from 'lodash';
import intersection from 'lodash/intersection';
import without from 'lodash/without';
import './CurrencySwap.scss';
export interface StateProps {

View File

@ -7,7 +7,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="manifest" href="/manifest.json">
</head>

View File

@ -2,7 +2,7 @@
import BN from 'bn.js';
import { toBuffer, addHexPrefix, bufferToHex } from 'ethereumjs-util';
import { trimStart } from 'lodash';
import trimStart from 'lodash/trimStart';
// When encoding QUANTITIES (integers, numbers): encode as hex, prefix with "0x", the most compact representation (slight exception: zero should be represented as "0x0").
export function hexEncodeQuantity(value: BN | Buffer): string {

View File

@ -2,7 +2,6 @@ import { Wei } from 'libs/units';
import * as eth from './ether';
import { IFullWallet } from 'libs/wallet';
import { ITransaction } from '../typings';
export { signTransaction };
export {
enoughBalanceViaTx,
validateTx,
@ -12,7 +11,7 @@ export {
computeIndexingHash
} from './ether';
export * from './token';
const signTransaction = async (
export const signTransaction = async (
t: ITransaction,
w: IFullWallet,
accountBalance: Wei,

View File

@ -6,7 +6,7 @@ import TrezorConnect from 'vendor/trezor-connect';
import { DeterministicWallet } from './deterministic';
import { getTransactionFields } from 'libs/transaction';
import { mapValues } from 'lodash';
import mapValues from 'lodash/mapValues';
import { IFullWallet } from '../IWallet';

View File

@ -1,24 +0,0 @@
require('ethereumjs-abi');
require('ethereumjs-util');
require('ethereumjs-wallet');
require('hdkey');
require('idna-uts46');
require('lodash');
require('react');
require('react-dom');
require('react-markdown');
require('react-redux');
require('react-router');
require('react-router-redux');
require('redux');
require('redux-logger');
require('redux-saga');
require('wallet-address-validator');
require('store2');
require('whatwg-fetch');
require('moment');
require('prop-types');
require('qrcode');
require('qrcode.react');
require('bn.js');
require('classnames');

View File

@ -19,6 +19,7 @@
"ethereumjs-util": "5.1.2",
"ethereumjs-wallet": "0.6.0",
"font-awesome": "4.7.0",
"hard-source-webpack-plugin": "^0.5.13",
"hdkey": "0.7.1",
"idna-uts46": "1.1.0",
"jsonschema": "1.2.2",
@ -62,6 +63,7 @@
"@types/redux-promise-middleware": "0.0.9",
"@types/uuid": "3.4.3",
"@types/webpack-env": "1.13.3",
"autodll-webpack-plugin": "^0.3.8",
"awesome-typescript-loader": "3.4.1",
"babel-minify-webpack-plugin": "0.2.0",
"bs58": "4.0.1",
@ -80,7 +82,6 @@
"friendly-errors-webpack-plugin": "1.6.1",
"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",
"husky": "0.14.3",
"image-webpack-loader": "3.4.2",
@ -102,7 +103,9 @@
"rimraf": "2.6.2",
"sass-loader": "6.0.6",
"style-loader": "0.19.1",
"thread-loader": "^1.1.2",
"ts-jest": "22.0.0",
"ts-loader": "^3.2.0",
"tslint": "5.8.0",
"tslint-config-prettier": "1.6.0",
"tslint-react": "3.3.3",
@ -135,7 +138,6 @@
"predev:https": "check-node-version --package",
"tslint": "tslint --project . --exclude common/vendor/**/*",
"tscheck": "tsc --noEmit",
"postinstall": "webpack --config=./webpack_config/webpack.dll.js",
"start": "npm run dev",
"precommit": "lint-staged",
"formatAll":

View File

@ -3,9 +3,9 @@
"outDir": "./dist/",
"sourceMap": true,
"strictNullChecks": true,
"module": "esnext",
"module": "es2015",
"jsx": "react",
"target": "es5",
"target": "es2015",
"allowJs": true,
"baseUrl": "./common/",
"lib": [

View File

@ -8,27 +8,38 @@ module.exports = {
srcPath: path.join(__dirname, './../common'),
// add these dependencies to a standalone vendor bundle
vendor: [
'bip39',
'bn.js',
'classnames',
'ethereum-blockies',
'ethereumjs-abi',
'ethereumjs-tx',
'ethereumjs-util',
'ethereumjs-wallet',
'hdkey',
'idna-uts46',
'jsonschema',
'lodash',
'moment',
'normalizr',
'qrcode',
'qrcode.react',
'query-string',
'react',
'react-dom',
'react-router',
'redux',
'react-markdown',
'react-redux',
'react-router-dom',
'react-router-redux',
'react-transition-group',
'redux',
'redux-logger',
'redux-promise-middleware',
'redux-saga',
'scryptsy',
'store2',
'uuid',
'wallet-address-validator',
'whatwg-fetch'
],
// Settings for webpack-image-loader image compression
imageCompressionOptions: {
optipng: {
optimizationLevel: 4
},
gifsicle: {
interlaced: false
},
mozjpeg: {
quality: 80
},
svgo: {
plugins: [{ removeViewBox: true }, { removeEmptyAttrs: false }, { sortAttrs: true }]
}
}
]
};

View File

@ -39,8 +39,7 @@ const devMiddleWare = require('webpack-dev-middleware')(compiler, {
'Access-Control-Allow-Headers': '*'
},
watchOptions: {
aggregateTimeout: 300,
poll: true
aggregateTimeout: 100
}
});
app.use(devMiddleWare);

View File

@ -19,6 +19,7 @@ _.loadersOptions = () => {
return {
minimize: isProd,
debug: !isProd,
options: {
// css-loader relies on context
context: process.cwd()

View File

@ -4,11 +4,10 @@ const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-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 _ = require('./utils');
const { CheckerPlugin } = require('awesome-typescript-loader');
module.exports = {
const webpackConfig = {
entry: {
client: './common/index.tsx'
},
@ -17,9 +16,6 @@ module.exports = {
filename: '[name].js',
publicPath: config.publicPath
},
performance: {
hints: process.env.NODE_ENV === 'production' ? 'warning' : false
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.css', '.json', '.scss', '.less'],
modules: [
@ -30,23 +26,26 @@ module.exports = {
]
},
module: {
loaders: [
rules: [
{
test: /\.(ts|tsx)$/,
loaders: [
{ loader: 'cache-loader' },
{
loader: 'awesome-typescript-loader'
}
],
exclude: [/node_modules/]
include: path.resolve(__dirname, '../common'),
use: [{ loader: 'ts-loader', options: { happyPackMode: true, logLevel: 'info' } }],
exclude: ['assets', 'sass', 'vendor', 'translations/lang']
.map(dir => path.resolve(__dirname, `../common/${dir}`))
.concat([path.resolve(__dirname, '../node_modules')])
},
{
include: [
path.resolve(__dirname, '../common/assets'),
path.resolve(__dirname, '../node_modules')
],
exclude: /node_modules(?!\/font-awesome)/,
test: /\.(gif|png|jpe?g|svg)$/i,
loaders: [
use: [
{
loader: 'file-loader',
query: {
options: {
hash: 'sha512',
digest: 'hex',
name: '[path][name].[ext]?[hash:6]'
@ -54,38 +53,52 @@ module.exports = {
},
{
loader: 'image-webpack-loader',
query: config.imageCompressionOptions
options: {
bypassOnDebug: true,
optipng: {
optimizationLevel: 4
},
gifsicle: {
interlaced: false
},
mozjpeg: {
quality: 80
},
svgo: {
plugins: [{ removeViewBox: true }, { removeEmptyAttrs: false }, { sortAttrs: true }]
}
}
}
]
},
{
include: [
path.resolve(__dirname, '../common/assets'),
path.resolve(__dirname, '../node_modules')
],
exclude: /node_modules(?!\/font-awesome)/,
test: /\.(ico|eot|otf|webp|ttf|woff|woff2)(\?.*)?$/,
loader: 'file-loader?limit=100000'
loader: 'file-loader'
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.BUILD_DOWNLOADABLE': JSON.stringify(!!process.env.BUILD_DOWNLOADABLE)
}),
new HtmlWebpackPlugin({
title: config.title,
template: path.resolve(__dirname, '../common/index.html'),
inject: true,
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 CopyWebpackPlugin([
{
from: _.cwd('./static'),
// to the root of dist path
to: './'
}
])
]),
new webpack.LoaderOptionsPlugin(_.loadersOptions())
],
target: _.target
};
module.exports = webpackConfig;

View File

@ -4,31 +4,78 @@ const path = require('path');
const webpack = require('webpack');
const base = require('./webpack.base');
const FriendlyErrors = require('friendly-errors-webpack-plugin');
const AutoDllPlugin = require('autodll-webpack-plugin');
const config = require('./config');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const threadLoader = require('thread-loader');
base.devtool = process.env.SLOW_BUILD_SPEED
? 'source-map'
: 'cheap-module-eval-source-map';
const fullSourceMap = process.env.SLOW_BUILD_SPEED;
if (fullSourceMap) {
base.devtool = fullSourceMap ? 'source-map' : 'cheap-module-eval-source-map';
base.module.loaders.push(
threadLoader.warmup(
{
// pool options, like passed to loader options
// must match loader options to boot the correct pool
happyPackMode: true,
logLevel: 'info'
},
[
// modules to load
// can be any module, i. e.
'ts-loader'
]
);
base.module.rules[0].use.unshift({
loader: 'thread-loader',
options: {
workers: 4
}
});
}
base.performance = { hints: false };
base.module.rules.push(
{
test: /\.css$/,
loaders: ['style-loader', 'css-loader']
include: path.resolve(__dirname, '../common/vendor'),
use: ['style-loader', 'css-loader']
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
include: ['components', 'containers', 'sass']
.map(dir => path.resolve(__dirname, `../common/${dir}`))
.concat([path.resolve(__dirname, '../node_modules')]),
exclude: /node_modules(?!\/font-awesome)/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.less$/,
loaders: ['style-loader', 'css-loader', 'less-loader']
include: path.resolve(__dirname, '../common/assets/styles'),
use: ['style-loader', 'css-loader', 'less-loader']
}
);
base.plugins.push(
new webpack.DllReferencePlugin({
context: path.join(__dirname, '../common'),
manifest: require('../dll/vendor-manifest.json')
new AutoDllPlugin({
inject: true, // will inject the DLL bundles to index.html
filename: '[name]_[hash].js',
debug: true,
context: path.join(__dirname, '..'),
entry: {
vendor: [...config.vendor, 'babel-polyfill', 'bootstrap-sass', 'font-awesome']
}
}),
new HardSourceWebpackPlugin({
environmentHash: {
root: process.cwd(),
directories: ['webpack_config'],
files: ['package.json']
}
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
}),

View File

@ -1,31 +0,0 @@
const path = require('path');
const webpack = require('webpack');
const config = require('./config');
const _ = require('./utils');
module.exports = {
entry: {
vendor: [path.join(__dirname, '../common', 'vendors.js')]
},
output: {
path: path.join(__dirname, '../static'),
filename: 'dll.[name].js',
library: '[name]'
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '../dll', '[name]-manifest.json'),
name: '[name]',
context: path.resolve(__dirname, '../common')
})
],
resolve: {
modules: [
// places where to search for required modules
'node_modules',
config.srcPath,
_.cwd('node_modules'),
_.cwd('./')
]
}
};

View File

@ -8,8 +8,8 @@ const freezerConfig = Object.assign({}, baseConfig, {
target: undefined,
performance: undefined,
module: {
// Typescript loader
loaders: [baseConfig.module.loaders[0]]
// Typescript loader
loaders: [baseConfig.module.rules[0]]
},
// Point at freezer, make sure it's setup to run in node

View File

@ -1,6 +1,7 @@
'use strict';
process.env.NODE_ENV = 'production';
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
@ -14,8 +15,8 @@ const distFolder = 'dist/';
// Clear out build folder
rimraf.sync(distFolder, { rmdirSync: true });
base.devtool = 'source-map';
base.module.loaders.push(
base.devtool = false;
base.module.rules.push(
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
@ -43,15 +44,24 @@ base.entry.vendor = config.vendor;
// use hash filename to support long-term caching
base.output.filename = '[name].[chunkhash:8].js';
// add webpack plugins
base.plugins.unshift(
new FaviconsWebpackPlugin({
logo: path.resolve(__dirname, '../static/favicon/android-chrome-384x384.png'),
background: '#163151',
inject: true
})
);
base.plugins.push(
new ProgressPlugin(),
new ExtractTextPlugin('[name].[chunkhash:8].css'),
new webpack.DefinePlugin({
'process.env.BUILD_DOWNLOADABLE': JSON.stringify(!!process.env.BUILD_DOWNLOADABLE)
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new BabelMinifyPlugin(undefined, {
comments: false
}),
new BabelMinifyPlugin(),
// extract vendor chunks
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',