Production bundle optimizations

Fixed production check in webpack config, removed moment locales and reduced lodash and fontawesome inclusion
This commit is contained in:
Mark van Renswoude 2018-04-29 22:33:27 +02:00
parent 0ebca23587
commit 4db1b2f23d
16 changed files with 232 additions and 131 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ node_modules
data
custom/*.js
public/dist/*.js
public/dist/*.map
public/dist/index.html
config.js
*.sublime-workspace

View File

@ -4,7 +4,6 @@ const config = require('./config');
const Repository = require('./lib/repository');
const NotificationWorker = require('./lib/workers/notification');
const _ = require('lodash');
const fs = require('fs');
const express = require('express');
const bodyParser = require('body-parser');
@ -17,7 +16,7 @@ const cookieParser = require('cookie-parser');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackConfig = require('./webpack.config.js');
const webpackConfigFactory = require('./webpack.config.js');
(async () =>
{
@ -52,6 +51,7 @@ const webpackConfig = require('./webpack.config.js');
// Frontend
if (isDevelopment)
{
const webpackConfig = webpackConfigFactory(process.env, { mode: 'development' });
const compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler, {

View File

@ -1,4 +1,4 @@
const _ = require('lodash');
const map = require('lodash/map');
const retry = require('async-retry');
const generate = require('nanoid/generate');
const markdown = require('markdown').markdown;
@ -137,7 +137,7 @@ class CodeRepository
return;
}
resolve(_.map(docs, (doc) => new Code(doc)));
resolve(map(docs, (doc) => new Code(doc)));
});
});
}

View File

@ -1,5 +1,3 @@
//const debug = require('debug')('recv:users');
const _ = require('lodash');
const path = require('path');
const mkdirp = require('mkdirp');
const Datastore = require('nedb');

View File

@ -1,4 +1,4 @@
const _ = require('lodash');
const map = require('lodash/map');
class Notification
@ -38,7 +38,7 @@ class NotificationRepository
return;
}
resolve(_.map(docs, (doc) => new Notification(doc)));
resolve(map(docs, (doc) => new Notification(doc)));
});
});
}

View File

@ -1,4 +1,5 @@
const _ = require('lodash');
const map = require('lodash/map');
const filter = require('lodash/filter');
class Upload
@ -61,9 +62,9 @@ class UploadRepository
userId: userId,
code: code,
expiration: expiration,
files: _.map(_.filter(files,
(file) => file.hasOwnProperty('id') && file.hasOwnProperty('name')),
(file) => { return { id: file.id, name: file.name, size: file.size } })
files: map(filter(files,
(file) => file.hasOwnProperty('id') && file.hasOwnProperty('name')),
(file) => { return { id: file.id, name: file.name, size: file.size } })
};
if (upload.files.length)

View File

@ -1,4 +1,4 @@
const _ = require('lodash');
const map = require('lodash/map');
const AuthTokens = require('../authtokens');
const bcrypt = require('bcrypt');
@ -121,7 +121,7 @@ class UserRepository
return;
}
resolve(_.map(docs, (doc) => new User(doc)));
resolve(map(docs, (doc) => new User(doc)));
});
});
}

83
package-lock.json generated
View File

@ -1520,6 +1520,17 @@
"callsite": "1.0.0"
}
},
"bfj-node4": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/bfj-node4/-/bfj-node4-5.3.1.tgz",
"integrity": "sha512-SOmOsowQWfXc7ybFARsK3C4MCOWzERaOMV/Fl3Tgjs+5dJWyzo3oa127jL44eMbQiAN17J7SvAs2TRxEScTUmg==",
"dev": true,
"requires": {
"bluebird": "3.5.1",
"check-types": "7.3.0",
"tryer": "1.0.0"
}
},
"big.js": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
@ -2138,6 +2149,12 @@
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
"dev": true
},
"check-types": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-7.3.0.tgz",
"integrity": "sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=",
"dev": true
},
"cheerio": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
@ -3245,6 +3262,12 @@
"run-parallel": "1.1.8"
}
},
"duplexer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
"dev": true
},
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@ -3977,6 +4000,12 @@
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
"dev": true
},
"filesize": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
"integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
"dev": true
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@ -5486,6 +5515,16 @@
"lodash": "4.17.5"
}
},
"gzip-size": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz",
"integrity": "sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw=",
"dev": true,
"requires": {
"duplexer": "0.1.1",
"pify": "3.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -12631,6 +12670,12 @@
"mimic-fn": "1.2.0"
}
},
"opener": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz",
"integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=",
"dev": true
},
"opn": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
@ -15746,6 +15791,12 @@
}
}
},
"tryer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.0.tgz",
"integrity": "sha1-Antp+oIyJeVRys4+8DsR9qs3wdc=",
"dev": true
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
@ -18615,6 +18666,38 @@
}
}
},
"webpack-bundle-analyzer": {
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.11.1.tgz",
"integrity": "sha512-VKUVkVMc6TWVXmF1OxsBXoiRjYiDRA4XT0KqtbLMDK+891VX7FCuklYwzldND8J2upUcHHnuXYNTP+4mSFi4Kg==",
"dev": true,
"requires": {
"acorn": "5.5.3",
"bfj-node4": "5.3.1",
"chalk": "2.3.2",
"commander": "2.15.1",
"ejs": "2.5.9",
"express": "4.16.3",
"filesize": "3.6.1",
"gzip-size": "4.1.0",
"lodash": "4.17.5",
"mkdirp": "0.5.1",
"opener": "1.4.3",
"ws": "4.1.0"
},
"dependencies": {
"ws": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
"dev": true,
"requires": {
"async-limiter": "1.0.0",
"safe-buffer": "5.1.1"
}
}
}
},
"webpack-cli": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.13.tgz",

View File

@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"dev": "supervisor -w index.js,lib index.js",
"devbuild": "webpack --mode development",
"build": "webpack --mode production",
"test": "echo \"Error: no test specified\" && exit 1"
},
@ -64,6 +65,7 @@
"vue-style-loader": "^4.1.0",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.2.0",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-cli": "^2.0.13",
"webpack-dev-middleware": "^3.0.1",
"webpack-hot-middleware": "^2.21.2"

View File

@ -13,7 +13,6 @@
</template>
<script>
import _ from 'lodash';
import shared from './shared';

View File

@ -6,25 +6,32 @@ import messages from './lang';
import shared from './shared';
import fontawesome from '@fortawesome/fontawesome';
import FontAwesomeIcon from '@fortawesome/vue-fontawesome';
import solid from '@fortawesome/fontawesome-free-solid';
import moment from 'moment'
import merge from 'lodash/merge';
// Implicitly import the icons used, saves a lot of space in the bundle.
// Perhaps vue-fontawesome will make this easier in the upcoming release?
// See: https://github.com/FortAwesome/vue-fontawesome/issues/46
import faSpinner from '@fortawesome/fontawesome-free-solid/faSpinner';
import faBan from '@fortawesome/fontawesome-free-solid/faBan';
import faTrashAlt from '@fortawesome/fontawesome-free-solid/faTrashAlt';
if (typeof customMessages !== 'undefined')
{
_.merge(messages, customMessages);
merge(messages, customMessages);
if (customMessages.hasOwnProperty('allLocales'))
{
for (var key in messages)
{
if (key !== 'allLocales' && messages.hasOwnProperty(key))
_.merge(messages[key], customMessages.allLocales);
merge(messages[key], customMessages.allLocales);
}
}
}
fontawesome.library.add(solid);
fontawesome.library.add(faSpinner, faBan, faTrashAlt);
Vue.component('fa', FontAwesomeIcon);
Vue.use(VueI18n);

View File

@ -14,7 +14,7 @@
</template>
<script>
import _ from 'lodash';
import map from 'lodash/map';
import shared from '../shared';
import Uppy from 'uppy/lib/core';
import Dashboard from 'uppy/lib/plugins/Dashboard';
@ -88,7 +88,7 @@ export default {
self.uppy.on('complete', (result) =>
{
axios.post('/complete', {
files: _.map(result.successful, (file) =>
files: map(result.successful, (file) =>
{
return {
id: file.tus.uploadUrl.substr(file.tus.uploadUrl.lastIndexOf('/') + 1),

View File

@ -41,6 +41,8 @@
<script>
import axios from 'axios';
import shared from '../../shared';
import orderBy from 'lodash/orderBy';
import findIndex from 'lodash/findIndex';
export default {
data()
@ -62,7 +64,7 @@ export default {
})
.then((response) =>
{
self.codes = _.orderBy(response.data, ['created'], ['desc']);
self.codes = orderBy(response.data, ['created'], ['desc']);
})
.catch((error) => { shared.$emit('apiError', error, this.$router) });
},
@ -89,7 +91,7 @@ export default {
}})
.then((response) =>
{
var index = _.findIndex(self.codes, (item) => { return item.id == codeId; });
var index = findIndex(self.codes, (item) => { return item.id == codeId; });
if (index > -1)
self.codes.splice(index, 1);
})

View File

@ -43,7 +43,8 @@
</template>
<script>
import _ from 'lodash';
import orderBy from 'lodash/orderBy';
import findIndex from 'lodash/findIndex';
import axios from 'axios';
import shared from '../../shared';
@ -74,7 +75,7 @@ export default {
})
.then((response) =>
{
self.uploads = _.orderBy(response.data, ['created'], ['desc']);
self.uploads = orderBy(response.data, ['created'], ['desc']);
})
.catch((error) => { shared.$emit('apiError', error, this.$router) });
},
@ -123,7 +124,7 @@ export default {
}})
.then((response) =>
{
var index = _.findIndex(self.uploads, (item) => { return item.id == uploadId; });
var index = findIndex(self.uploads, (item) => { return item.id == uploadId; });
if (index > -1)
self.uploads.splice(index, 1);
})

View File

@ -37,6 +37,8 @@
<script>
import axios from 'axios';
import shared from '../../shared';
import orderBy from 'lodash/orderBy';
import findIndex from 'lodash/findIndex';
export default {
data()
@ -58,7 +60,7 @@ export default {
})
.then((response) =>
{
self.users = _.orderBy(response.data, ['active', 'username'], ['desc', 'asc']);
self.users = orderBy(response.data, ['active', 'username'], ['desc', 'asc']);
})
.catch((error) => { shared.$emit('apiError', error, this.$router) });
},
@ -79,7 +81,7 @@ export default {
}})
.then((response) =>
{
var index = _.findIndex(self.users, (item) => { return item.id == userId; });
var index = findIndex(self.users, (item) => { return item.id == userId; });
if (index > -1)
self.users.splice(index, 1);
})

View File

@ -1,117 +1,122 @@
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
mode: 'development',
entry: './public/src/app.js',
output: {
path: path.resolve(__dirname, './public/dist'),
publicPath: '/',
filename: 'build.js'
},
module.exports = (env, options) => {
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
]
let config = {
mode: options.mode,
entry: './public/src/app.js',
output: {
path: path.resolve(__dirname, './public/dist'),
publicPath: '/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
]
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/src/index.html')
})
],
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
]
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/src/index.html')
})
],
performance: {
hints: false
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devtool: '#eval-source-map'
}
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
if (process.env.NODE_ENV === 'production')
{
module.exports.devtool = '#source-map'
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
]);
}
else
{
module.exports.entry = [
module.exports.entry,
'webpack-hot-middleware/client'
];
performance: {
hints: false
},
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]);
}
devtool: '#eval-source-map'
};
if (options.mode === 'production')
{
config.devtool = '#source-map'
config.plugins = (config.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// To see what's using the space in the bundle, uncomment this
//new BundleAnalyzerPlugin()
]);
}
else
{
config.entry = [
config.entry,
'webpack-hot-middleware/client'
];
config.plugins = (config.plugins || []).concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]);
}
return config;
};