diff --git a/configs/webpack/common.js b/configs/webpack/common.js
index 508de03..bf8fe48 100644
--- a/configs/webpack/common.js
+++ b/configs/webpack/common.js
@@ -2,59 +2,50 @@
const {resolve} = require("path");
const {CheckerPlugin} = require("awesome-typescript-loader");
const StyleLintPlugin = require("stylelint-webpack-plugin");
-const HtmlWebpackPlugin = require("html-webpack-plugin");
const Dotenv = require("dotenv-webpack");
-module.exports = {
- resolve: {
+module.exports = function (env, argv) {
+ const config = {};
+
+ config.resolve = {
extensions: [".ts", ".tsx", ".js", ".jsx"]
- },
- context: resolve(__dirname, "../../src"),
- module: {
- rules: [
- {
- test: /\.js$/,
- use: ["babel-loader", "source-map-loader"],
- exclude: /node_modules/
- },
- {
- test: /\.tsx?$/,
- use: ["babel-loader", "awesome-typescript-loader"]
- },
- {
- test: /\.css$/,
- use: ["style-loader", {loader: "css-loader", options: {importLoaders: 1}}, "postcss-loader"]
- },
- {
- test: /\.scss$/,
- loaders: [
- "style-loader",
- {loader: "css-loader", options: {importLoaders: 1}},
- "postcss-loader",
- "sass-loader"
- ]
- },
- {
- test: /\.(jpe?g|png|gif|svg)$/i,
- loaders: [
- "file-loader?hash=sha512&digest=hex&name=img/[hash].[ext]",
- "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false"
- ]
- }
+ };
+ config.context = resolve(__dirname, "../../src");
+ config.module = {
+ rules: [],
+ };
+ config.module.rules.push({
+ test: /\.js$/,
+ use: ["babel-loader", "source-map-loader"],
+ exclude: /node_modules/
+ });
+ config.module.rules.push({
+ test: /\.tsx?$/,
+ use: ["babel-loader", "awesome-typescript-loader"]
+ });
+
+ config.module.rules.push({
+ test: /\.(jpe?g|png|gif|svg)$/i,
+ loaders: [
+ "file-loader?hash=sha512&digest=hex&name=assets/img/[hash].[ext]",
+ "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false"
]
- },
- plugins: [
+ });
+
+ config.plugins = [
new CheckerPlugin(),
new StyleLintPlugin(),
- new HtmlWebpackPlugin({template: "index.html.ejs"}),
new Dotenv({
path: "./.env.sample"
}),
new Dotenv({
path: "./.env"
- })
- ],
- performance: {
+ }),
+ ];
+
+ config.performance = {
hints: false
- }
+ };
+
+ return config;
};
diff --git a/configs/webpack/dev.js b/configs/webpack/dev.js
index e9164ed..8c70c3a 100644
--- a/configs/webpack/dev.js
+++ b/configs/webpack/dev.js
@@ -2,18 +2,20 @@
const merge = require("webpack-merge");
const webpack = require("webpack");
const FaviconsWebpackPlugin = require("favicons-webpack-plugin");
+const HtmlWebpackPlugin = require("html-webpack-plugin");
const commonConfig = require("./common.js");
-module.exports = merge(commonConfig, {
- mode: "development",
- entry: [
+module.exports = function (env, argv) {
+ const base = commonConfig(env, argv);
+ base.mode = "development";
+ base.entry = [
"react-hot-loader/patch", // Activate HMR for React
"webpack-dev-server/client?http://0.0.0.0:8080", // Bundle the client for webpack-dev-server and connect to the provided endpoint
"webpack/hot/only-dev-server", // Bundle the client for hot reloading, only- means to only hot reload for successful updates
"./index.tsx" // The entry point of our app
- ],
- devServer: {
+ ];
+ base.devServer = {
hot: true, // Enable HMR on the server
historyApiFallback: true,
host: '0.0.0.0',
@@ -41,9 +43,9 @@ module.exports = merge(commonConfig, {
// watchOptions: {
// ignored: /node_modules/
// }
- },
- devtool: "cheap-module-eval-source-map",
- plugins: [
+ };
+ base.devtool = "cheap-module-eval-source-map";
+ base.plugins = base.plugins.concat([
new FaviconsWebpackPlugin({
logo: "./assets/img/favicon.png",
icons: {
@@ -60,6 +62,23 @@ module.exports = merge(commonConfig, {
}
}),
new webpack.HotModuleReplacementPlugin(), // Enable HMR globally
- new webpack.NamedModulesPlugin() // Prints more readable module names in the browser console on HMR updates
- ]
-});
+ new webpack.NamedModulesPlugin(), // Prints more readable module names in the browser console on HMR updates
+ new HtmlWebpackPlugin({template: "index.html.ejs"}),
+ ]);
+
+ base.module.rules.push({
+ test: /\.css$/,
+ use: ["style-loader", {loader: "css-loader", options: {importLoaders: 1}}, "postcss-loader"]
+ });
+ base.module.rules.push({
+ test: /\.scss$/,
+ loaders: [
+ "style-loader",
+ {loader: "css-loader", options: {importLoaders: 1}},
+ "postcss-loader",
+ "sass-loader"
+ ]
+ });
+
+ return base;
+};
diff --git a/configs/webpack/prod.js b/configs/webpack/prod.js
index 89a7b67..57ab9a3 100644
--- a/configs/webpack/prod.js
+++ b/configs/webpack/prod.js
@@ -3,48 +3,113 @@ const path = require("path");
const merge = require("webpack-merge");
const resolve = path.resolve;
-const DynamicCdnWebpackPlugin = require("dynamic-cdn-webpack-plugin");
-const PrerenderSPAPlugin = require("prerender-spa-plugin");
const FaviconsWebpackPlugin = require("favicons-webpack-plugin");
+const nodeExternals = require('webpack-node-externals');
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+const HtmlWebpackPlugin = require("html-webpack-plugin");
+const WebpackCdnPlugin = require('webpack-cdn-plugin');
+const webpack = require('webpack');
/* NOTE: This is a list of all routes that are prerendered for production use.
Please list all routes that contain search engine accessible content, i.e.,
stuff that you would like to find with a Google Search. */
-const PRERENDERED_ROUTES = ["/", "/404"];
const commonConfig = require("./common");
-module.exports = merge(commonConfig, {
- mode: "production",
- entry: "./index.tsx",
- output: {
- filename: "js/bundle.[hash].min.js",
+module.exports = function (env, argv) {
+ const base = commonConfig(env, argv);
+ base.mode = "production";
+ base.entry = "./index.tsx";
+ base.output = {
path: resolve(__dirname, "../../dist"),
- publicPath: "/"
- },
- devtool: "source-map",
- plugins: [
- new FaviconsWebpackPlugin({
- logo: "./assets/img/favicon.png",
- icons: {
- android: true,
- appleIcon: true,
- appleStartup: true,
- coast: true,
- favicons: true,
- firefox: true,
- opengraph: true,
- twitter: true,
- yandex: true,
- windows: true
- }
+ publicPath: "/",
+ };
+ base.devtool = "source-map";
+ base.plugins.push(
+ new MiniCssExtractPlugin({
+ // Options similar to the same options in webpackOptions.output
+ // both options are optional
+ filename: "assets/styles.css?[hash]",
}),
- new DynamicCdnWebpackPlugin(),
- new PrerenderSPAPlugin({
- // Required - The path to the webpack-outputted app to prerender.
- staticDir: resolve(__dirname, "../../dist"),
- // Required - Routes to render.
- routes: PRERENDERED_ROUTES
- })
- ]
-});
+ );
+
+ if (env.platform === 'server') {
+ base.entry = "./server/index.ts";
+ base.output.filename = 'js/server.js?[hash]';
+ base.target = 'node';
+ base.externals = [nodeExternals()];
+
+ base.module.rules.push({
+ test: /\.css$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ {loader: "css-loader", options: {importLoaders: 1}},
+ "postcss-loader"
+ ],
+ });
+
+ base.module.rules.push({
+ test: /\.scss$/,
+ loaders: [
+ MiniCssExtractPlugin.loader,
+ {loader: "css-loader", options: {importLoaders: 1}},
+ "postcss-loader",
+ "sass-loader"
+ ]
+ });
+ }
+
+ else if (env.platform === 'client') {
+ base.entry = './client/index.ts';
+ base.output.filename = 'js/client.js?[hash]';
+ base.target = 'web';
+
+ base.module.rules.push({
+ test: /\.css$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ {loader: "css-loader", options: {importLoaders: 1}},
+ "postcss-loader"
+ ],
+ });
+
+ base.module.rules.push({
+ test: /\.scss$/,
+ loaders: [
+ MiniCssExtractPlugin.loader,
+ {loader: "css-loader", options: {importLoaders: 1}},
+ "postcss-loader",
+ "sass-loader"
+ ]
+ });
+
+ base.plugins.push(
+ new HtmlWebpackPlugin({
+ template: "index.html.ejs",
+ }),
+ new FaviconsWebpackPlugin({
+ logo: "./assets/img/favicon.png",
+ icons: {
+ android: true,
+ appleIcon: true,
+ appleStartup: true,
+ coast: true,
+ favicons: true,
+ firefox: true,
+ opengraph: true,
+ twitter: true,
+ yandex: true,
+ windows: true
+ }
+ }),
+ new WebpackCdnPlugin({
+ modules: [
+ { name: 'react', var: 'React', path: `umd/react.${process.env.NODE_ENV}.min.js` },
+ { name: 'react-dom', var: 'ReactDOM', path: `umd/react-dom.${process.env.NODE_ENV}.min.js` },
+ ],
+ }),
+ );
+ }
+
+ return base;
+};
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 55bcf98..9d150de 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,27 +20,6 @@
"integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==",
"dev": true
},
- "@prerenderer/prerenderer": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/@prerenderer/prerenderer/-/prerenderer-0.7.1.tgz",
- "integrity": "sha512-BgtsmvSDxEHoR1PSFk3olruz12at68r6Dr4e6FrdwzSJsSvinxCNFsXYMxkOyYTLbhTK9GBS/G0NAYE1BERL4Q==",
- "dev": true,
- "requires": {
- "express": "^4.16.2",
- "http-proxy-middleware": "^0.18.0",
- "portfinder": "^1.0.13"
- }
- },
- "@prerenderer/renderer-puppeteer": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/@prerenderer/renderer-puppeteer/-/renderer-puppeteer-0.1.4.tgz",
- "integrity": "sha512-z5WbndAto2YCjPqNEGt2G9kqa7+6fJMLPSk4i/qpmLwq1N8eRwSYnbnb4JSyg9O3sgs5k5amaP+4Wh2O4bURDQ==",
- "dev": true,
- "requires": {
- "promise-limit": "^2.5.0",
- "puppeteer": "^1.0.0"
- }
- },
"@types/error-stack-parser": {
"version": "1.3.18",
"resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz",
@@ -48,9 +27,9 @@
"dev": true
},
"@types/lodash": {
- "version": "4.14.110",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.110.tgz",
- "integrity": "sha512-iXYLa6olt4tnsCA+ZXeP6eEW3tk1SulWeYyP/yooWfAtXjozqXgtX4+XUtMuOCfYjKGz3F34++qUc3Q+TJuIIw==",
+ "version": "4.14.116",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.116.tgz",
+ "integrity": "sha512-lRnAtKnxMXcYYXqOiotTmJd74uawNWuPnsnPrrO7HiFuE3npE2iQhfABatbYDyxTNqZNuXzcKGhw37R7RjBFLg==",
"dev": true
},
"@types/node": {
@@ -263,6 +242,37 @@
"long": "^3.2.0"
}
},
+ "@webpack-contrib/schema-utils": {
+ "version": "1.0.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz",
+ "integrity": "sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chalk": "^2.3.2",
+ "strip-ansi": "^4.0.0",
+ "text-table": "^0.2.0",
+ "webpack-log": "^1.1.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
"@zeit/schemas": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-1.2.0.tgz",
@@ -300,15 +310,6 @@
"acorn": "^5.0.0"
}
},
- "agent-base": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
- "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
- "dev": true,
- "requires": {
- "es6-promisify": "^5.0.0"
- }
- },
"ajv": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.1.tgz",
@@ -370,6 +371,15 @@
"string-width": "^2.0.0"
}
},
+ "ansi-cyan": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
+ "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
"ansi-escapes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
@@ -391,6 +401,15 @@
"integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
"dev": true
},
+ "ansi-red": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
+ "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
@@ -1025,6 +1044,12 @@
"lodash": "^4.17.4"
}
},
+ "babel-helper-evaluate-path": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.4.3.tgz",
+ "integrity": "sha1-ComvcCwGshcCf6NxkI3UmJ0+Yz8=",
+ "dev": true
+ },
"babel-helper-explode-assignable-expression": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
@@ -1048,6 +1073,12 @@
"babel-types": "^6.24.1"
}
},
+ "babel-helper-flip-expressions": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz",
+ "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=",
+ "dev": true
+ },
"babel-helper-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
@@ -1081,6 +1112,24 @@
"babel-types": "^6.24.1"
}
},
+ "babel-helper-is-nodes-equiv": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz",
+ "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=",
+ "dev": true
+ },
+ "babel-helper-is-void-0": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz",
+ "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=",
+ "dev": true
+ },
+ "babel-helper-mark-eval-scopes": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz",
+ "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=",
+ "dev": true
+ },
"babel-helper-optimise-call-expression": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
@@ -1115,6 +1164,12 @@
"babel-types": "^6.24.1"
}
},
+ "babel-helper-remove-or-void": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz",
+ "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=",
+ "dev": true
+ },
"babel-helper-replace-supers": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
@@ -1129,6 +1184,12 @@
"babel-types": "^6.24.1"
}
},
+ "babel-helper-to-multiple-sequence-expressions": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.4.3.tgz",
+ "integrity": "sha1-W1GLESf0ezA4dzOGoVYaK0jmMrY=",
+ "dev": true
+ },
"babel-helpers": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
@@ -1159,6 +1220,12 @@
"babel-runtime": "^6.22.0"
}
},
+ "babel-plugin-add-module-exports": {
+ "version": "0.2.1",
+ "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
+ },
"babel-plugin-check-es2015-constants": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
@@ -1168,6 +1235,101 @@
"babel-runtime": "^6.22.0"
}
},
+ "babel-plugin-minify-builtins": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.4.3.tgz",
+ "integrity": "sha1-nqPVn0rEp7uVjXEtKVVqH4b3+B4=",
+ "dev": true,
+ "requires": {
+ "babel-helper-evaluate-path": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-constant-folding": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.4.3.tgz",
+ "integrity": "sha1-MA+d6N2ghEoXaxk2U5YOJK0z4ZE=",
+ "dev": true,
+ "requires": {
+ "babel-helper-evaluate-path": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-dead-code-elimination": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.4.3.tgz",
+ "integrity": "sha1-c2KCZYZPkAjQAnUG9Yq+s8HQLZg=",
+ "dev": true,
+ "requires": {
+ "babel-helper-evaluate-path": "^0.4.3",
+ "babel-helper-mark-eval-scopes": "^0.4.3",
+ "babel-helper-remove-or-void": "^0.4.3",
+ "lodash.some": "^4.6.0"
+ }
+ },
+ "babel-plugin-minify-flip-comparisons": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz",
+ "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=",
+ "dev": true,
+ "requires": {
+ "babel-helper-is-void-0": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-guarded-expressions": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.3.tgz",
+ "integrity": "sha1-zHCbRFP9IbHzAod0RMifiEJ845c=",
+ "dev": true,
+ "requires": {
+ "babel-helper-flip-expressions": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-infinity": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz",
+ "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=",
+ "dev": true
+ },
+ "babel-plugin-minify-mangle-names": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.4.3.tgz",
+ "integrity": "sha1-FvG/90t6fJPfwkHngx3V+0sCPvc=",
+ "dev": true,
+ "requires": {
+ "babel-helper-mark-eval-scopes": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-numeric-literals": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz",
+ "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=",
+ "dev": true
+ },
+ "babel-plugin-minify-replace": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.4.3.tgz",
+ "integrity": "sha1-nSifS6FdTmAR6HmfpfG6d+yBIZ0=",
+ "dev": true
+ },
+ "babel-plugin-minify-simplify": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.4.3.tgz",
+ "integrity": "sha1-N3VthcYURktLCSfytOQXGR1Vc4o=",
+ "dev": true,
+ "requires": {
+ "babel-helper-flip-expressions": "^0.4.3",
+ "babel-helper-is-nodes-equiv": "^0.0.1",
+ "babel-helper-to-multiple-sequence-expressions": "^0.4.3"
+ }
+ },
+ "babel-plugin-minify-type-constructors": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz",
+ "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=",
+ "dev": true,
+ "requires": {
+ "babel-helper-is-void-0": "^0.4.3"
+ }
+ },
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
@@ -1530,6 +1692,30 @@
"babel-runtime": "^6.22.0"
}
},
+ "babel-plugin-transform-inline-consecutive-adds": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz",
+ "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=",
+ "dev": true
+ },
+ "babel-plugin-transform-member-expression-literals": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz",
+ "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=",
+ "dev": true
+ },
+ "babel-plugin-transform-merge-sibling-variables": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz",
+ "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=",
+ "dev": true
+ },
+ "babel-plugin-transform-minify-booleans": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz",
+ "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=",
+ "dev": true
+ },
"babel-plugin-transform-object-rest-spread": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
@@ -1540,6 +1726,15 @@
"babel-runtime": "^6.26.0"
}
},
+ "babel-plugin-transform-property-literals": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz",
+ "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
"babel-plugin-transform-react-display-name": {
"version": "6.25.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz",
@@ -1589,6 +1784,33 @@
"regenerator-transform": "^0.10.0"
}
},
+ "babel-plugin-transform-regexp-constructors": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz",
+ "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=",
+ "dev": true
+ },
+ "babel-plugin-transform-remove-console": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz",
+ "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=",
+ "dev": true
+ },
+ "babel-plugin-transform-remove-debugger": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz",
+ "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=",
+ "dev": true
+ },
+ "babel-plugin-transform-remove-undefined": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.4.3.tgz",
+ "integrity": "sha1-1AsNp/kcCMBsxyt2dHTAHEiU3gI=",
+ "dev": true,
+ "requires": {
+ "babel-helper-evaluate-path": "^0.4.3"
+ }
+ },
"babel-plugin-transform-runtime": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
@@ -1598,6 +1820,12 @@
"babel-runtime": "^6.22.0"
}
},
+ "babel-plugin-transform-simplify-comparison-operators": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz",
+ "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=",
+ "dev": true
+ },
"babel-plugin-transform-strict-mode": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
@@ -1608,6 +1836,12 @@
"babel-types": "^6.24.1"
}
},
+ "babel-plugin-transform-undefined-to-void": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz",
+ "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=",
+ "dev": true
+ },
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
@@ -1674,6 +1908,37 @@
"babel-plugin-transform-flow-strip-types": "^6.22.0"
}
},
+ "babel-preset-minify": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.4.3.tgz",
+ "integrity": "sha1-spw91pGJBThFmPCSuVUVLiah/g8=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-minify-builtins": "^0.4.3",
+ "babel-plugin-minify-constant-folding": "^0.4.3",
+ "babel-plugin-minify-dead-code-elimination": "^0.4.3",
+ "babel-plugin-minify-flip-comparisons": "^0.4.3",
+ "babel-plugin-minify-guarded-expressions": "^0.4.3",
+ "babel-plugin-minify-infinity": "^0.4.3",
+ "babel-plugin-minify-mangle-names": "^0.4.3",
+ "babel-plugin-minify-numeric-literals": "^0.4.3",
+ "babel-plugin-minify-replace": "^0.4.3",
+ "babel-plugin-minify-simplify": "^0.4.3",
+ "babel-plugin-minify-type-constructors": "^0.4.3",
+ "babel-plugin-transform-inline-consecutive-adds": "^0.4.3",
+ "babel-plugin-transform-member-expression-literals": "^6.9.4",
+ "babel-plugin-transform-merge-sibling-variables": "^6.9.4",
+ "babel-plugin-transform-minify-booleans": "^6.9.4",
+ "babel-plugin-transform-property-literals": "^6.9.4",
+ "babel-plugin-transform-regexp-constructors": "^0.4.3",
+ "babel-plugin-transform-remove-console": "^6.9.4",
+ "babel-plugin-transform-remove-debugger": "^6.9.4",
+ "babel-plugin-transform-remove-undefined": "^0.4.3",
+ "babel-plugin-transform-simplify-comparison-operators": "^6.9.4",
+ "babel-plugin-transform-undefined-to-void": "^6.9.4",
+ "lodash.isplainobject": "^4.0.6"
+ }
+ },
"babel-preset-react": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz",
@@ -2822,9 +3087,9 @@
"dev": true
},
"chrome-remote-interface": {
- "version": "0.25.6",
- "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.25.6.tgz",
- "integrity": "sha512-YNkw2FqKqb99p7nyxrx0cphAHzjyukd6NwnOuk1bI0KV5lrQ6A7DA8HZAWjhy5qbbetpGky2AKENnkTsFrYw3w==",
+ "version": "0.25.7",
+ "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.25.7.tgz",
+ "integrity": "sha512-6zI6LbR2IiGmduFZededaerEr9hHXabxT/L+fRrdq65a0CfyLMzpq0BKuZiqN0Upqcacsb6q2POj7fmobwBsEA==",
"dev": true,
"requires": {
"commander": "2.11.x",
@@ -2836,17 +3101,6 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
"dev": true
- },
- "ws": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
- "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
- "dev": true,
- "requires": {
- "async-limiter": "~1.0.0",
- "safe-buffer": "~5.1.0",
- "ultron": "~1.1.0"
- }
}
}
},
@@ -4340,30 +4594,6 @@
"stream-shift": "^1.0.0"
}
},
- "dynamic-cdn-webpack-plugin": {
- "version": "4.0.0-rc.1",
- "resolved": "https://registry.npmjs.org/dynamic-cdn-webpack-plugin/-/dynamic-cdn-webpack-plugin-4.0.0-rc.1.tgz",
- "integrity": "sha512-yKfyj9TAeAoir3H6tS5mKVPrja8CKYWKFQYBa2/TEmLZLoSoVVHKdvSN0TNMPC2L5g2e0RoyOTBfNroU64YgYA==",
- "dev": true,
- "requires": {
- "babel-runtime": "^6.26.0",
- "html-webpack-include-assets-plugin": "1.0.3",
- "read-pkg-up": "^3.0.0",
- "resolve-pkg": "^1.0.0"
- },
- "dependencies": {
- "read-pkg-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
- "dev": true,
- "requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^3.0.0"
- }
- }
- }
- },
"each-async": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz",
@@ -4580,15 +4810,6 @@
"integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
"dev": true
},
- "es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
- "dev": true,
- "requires": {
- "es6-promise": "^4.0.3"
- }
- },
"es6-symbol": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
@@ -6785,6 +7006,51 @@
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
"dev": true
},
+ "gulp-clone": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-2.0.1.tgz",
+ "integrity": "sha512-SLg/KsHBbinR/pCX3PF5l1YlR28hLp0X+bcpf77PtMJ6zvAQ5kRjtCPV5Wt1wHXsXWZN0eTUZ15R8ZYpi/CdCA==",
+ "dev": true,
+ "requires": {
+ "plugin-error": "^0.1.2",
+ "through2": "^2.0.3"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ }
+ }
+ }
+ },
+ "gulp-data": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/gulp-data/-/gulp-data-1.3.1.tgz",
+ "integrity": "sha512-fvpQJvgVyhkwRcFP3Y9QUS9sWvIFsAlJDinQjhLuknmHZz52jH0gHmTujYBFjr9aTlTHlrAayY5m1d0tA1HzGQ==",
+ "dev": true,
+ "requires": {
+ "plugin-error": "^0.1.2",
+ "through2": "^2.0.0",
+ "util-extend": "^1.0.1"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ }
+ }
+ }
+ },
"gulp-decompress": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz",
@@ -6803,6 +7069,39 @@
"integrity": "sha512-nEuZB7/9i0IZ8AXORTizl2QLP9tcC9uWc/s329zElBLJw1CfOhmMXBxwVlCRKjDyrWuhVP0uBKl61KeQ32TiCg==",
"dev": true
},
+ "gulp-run-command": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/gulp-run-command/-/gulp-run-command-0.0.9.tgz",
+ "integrity": "sha512-8/Gzh+zfe6CFLqaL+LxwqLPj5fk/N1eCHEr36K5p9Al40iuxpbVnq1aZRGXMj+4DlWBzjjAAxas3EkMNI/6Vcw==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-runtime": "6.15.0",
+ "cross-spawn": "4.0.0",
+ "spawn-args": "0.2.0",
+ "timeout-as-promise": "^1.0.0"
+ },
+ "dependencies": {
+ "babel-plugin-transform-runtime": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.15.0.tgz",
+ "integrity": "sha1-PXW02Umtga8VdXAnOEb7Wa6w1Xw=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.9.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz",
+ "integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "which": "^1.2.9"
+ }
+ }
+ }
+ },
"gulp-sourcemaps": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz",
@@ -7356,17 +7655,6 @@
"integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
"dev": true
},
- "html-webpack-include-assets-plugin": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/html-webpack-include-assets-plugin/-/html-webpack-include-assets-plugin-1.0.3.tgz",
- "integrity": "sha512-P8qqFWyTSBHySuWBZINZw/Xqas7bB5d8BspeJN7GgB2/1CLV/xF3GX2dqy4qlKDySOgXPYBp5z64f8Xvr5prSg==",
- "dev": true,
- "requires": {
- "glob": "^7.1.2",
- "minimatch": "^3.0.4",
- "slash": "^1.0.0"
- }
- },
"html-webpack-plugin": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
@@ -7524,16 +7812,6 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"dev": true
},
- "https-proxy-agent": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
- "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
- "dev": true,
- "requires": {
- "agent-base": "^4.1.0",
- "debug": "^3.1.0"
- }
- },
"husky": {
"version": "1.0.0-rc.9",
"resolved": "https://registry.npmjs.org/husky/-/husky-1.0.0-rc.9.tgz",
@@ -8041,9 +8319,9 @@
"dev": true
},
"ipaddr.js": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
- "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+ "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=",
"dev": true
},
"is-absolute": {
@@ -9215,6 +9493,12 @@
"lodash._objecttypes": "~2.4.1"
}
},
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
+ "dev": true
+ },
"lodash.keys": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
@@ -9244,6 +9528,12 @@
"integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
"dev": true
},
+ "lodash.some": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
+ "dev": true
+ },
"lodash.tail": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
@@ -9766,6 +10056,17 @@
"dom-walk": "^0.1.0"
}
},
+ "mini-css-extract-plugin": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.1.tgz",
+ "integrity": "sha512-XWuB3G61Rtasq/gLe7cp5cuozehE6hN+E4sxCamRR/WDiHTg+f7ZIAS024r8UJQffY+e2gGELXQZgQoFDfNDCg==",
+ "dev": true,
+ "requires": {
+ "@webpack-contrib/schema-utils": "^1.0.0-beta.0",
+ "loader-utils": "^1.1.0",
+ "webpack-sources": "^1.1.0"
+ }
+ },
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@@ -10031,9 +10332,9 @@
}
},
"mustache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz",
- "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz",
+ "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==",
"dev": true
},
"mute-stream": {
@@ -10563,9 +10864,9 @@
"dev": true
},
"node-version": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.1.3.tgz",
- "integrity": "sha512-rEwE51JWn0yN3Wl5BXeGn5d52OGbSXzWiiXRjAQeuyvcGKyvuSILW2rb3G7Xh+nexzLwhTpek6Ehxd6IjvHePg==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz",
+ "integrity": "sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ==",
"dev": true
},
"nopt": {
@@ -11592,6 +11893,58 @@
}
}
},
+ "plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
+ "requires": {
+ "ansi-cyan": "^0.1.1",
+ "ansi-red": "^0.1.1",
+ "arr-diff": "^1.0.1",
+ "arr-union": "^2.0.1",
+ "extend-shallow": "^1.1.2"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.0.1",
+ "array-slice": "^0.2.3"
+ }
+ },
+ "arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true
+ },
+ "array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^1.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true
+ }
+ }
+ },
"pluralize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
@@ -12774,17 +13127,6 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
"dev": true
},
- "prerender-spa-plugin": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/prerender-spa-plugin/-/prerender-spa-plugin-3.2.1.tgz",
- "integrity": "sha512-UHgpVAtnUP/usSnl3AnNjZRw8zEQzT4WmRWA7p2EqucgGYseDg9NAOyXPcUmMWdCx0UMYpetF36zyYtCF3AoBw==",
- "dev": true,
- "requires": {
- "@prerenderer/prerenderer": "^0.7.1",
- "@prerenderer/renderer-puppeteer": "^0.1.4",
- "html-minifier": "^3.5.16"
- }
- },
"preserve": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
@@ -12819,12 +13161,6 @@
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true
},
- "progress": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
- "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
- "dev": true
- },
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
@@ -12840,12 +13176,6 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
- "promise-limit": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.6.0.tgz",
- "integrity": "sha512-ZyUYT6/nrx7oDInu6Go128Ck4N2aXqpV8G0QyU3ugGS0PRPOf5Y7v0IF0yZW2pwZCGtHzBftKievNj8491suJw==",
- "dev": true
- },
"promisify-event": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/promisify-event/-/promisify-event-1.0.0.tgz",
@@ -12871,21 +13201,15 @@
"dev": true
},
"proxy-addr": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
- "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+ "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
"dev": true,
"requires": {
"forwarded": "~0.1.2",
- "ipaddr.js": "1.6.0"
+ "ipaddr.js": "1.8.0"
}
},
- "proxy-from-env": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
- "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=",
- "dev": true
- },
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -12956,30 +13280,6 @@
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
- "puppeteer": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.5.0.tgz",
- "integrity": "sha512-eELwFtFxL+uhmg4jPZOZXzSrPEYy4CaYQNbcchBbfxY+KjMpnv6XGf/aYWaQG49OTpfi2/DMziXtDM8XuJgoUA==",
- "dev": true,
- "requires": {
- "debug": "^3.1.0",
- "extract-zip": "^1.6.6",
- "https-proxy-agent": "^2.2.1",
- "mime": "^2.0.3",
- "progress": "^2.0.0",
- "proxy-from-env": "^1.0.0",
- "rimraf": "^2.6.1",
- "ws": "^5.1.1"
- },
- "dependencies": {
- "mime": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz",
- "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==",
- "dev": true
- }
- }
- },
"q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@@ -13839,23 +14139,6 @@
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz",
"integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg=="
},
- "resolve-pkg": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-1.0.0.tgz",
- "integrity": "sha1-4ZoV54rKLhJEYdySsuOUPvk0lNk=",
- "dev": true,
- "requires": {
- "resolve-from": "^2.0.0"
- },
- "dependencies": {
- "resolve-from": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
- "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
- "dev": true
- }
- }
- },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -14710,6 +14993,12 @@
"integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==",
"dev": true
},
+ "spawn-args": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/spawn-args/-/spawn-args-0.2.0.tgz",
+ "integrity": "sha1-+30L0dcP1DFr2ePew4nmX51jYbs=",
+ "dev": true
+ },
"spdx-correct": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
@@ -15829,9 +16118,9 @@
}
},
"testcafe": {
- "version": "0.20.3",
- "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-0.20.3.tgz",
- "integrity": "sha512-wvxBspl5KSK6eEQdrjOfR4cyhot4XkDFfsGkldUy/yuSfczsc8qkte+TXPt8WWfQF/AnEsmtLVWFKCd4sB/DHg==",
+ "version": "0.20.5",
+ "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-0.20.5.tgz",
+ "integrity": "sha512-clCWZmR6OzsCS2LxkHnk4xaSgH9Lyw7PRgwJ4XJv5k2mchuj1qHQuLHj/lRYkciQlZt78V5/wHV+C3To6od4mw==",
"dev": true,
"requires": {
"async-exit-hook": "^1.1.2",
@@ -15857,6 +16146,7 @@
"error-stack-parser": "^1.3.6",
"globby": "^3.0.1",
"graceful-fs": "^4.1.11",
+ "gulp-data": "^1.3.1",
"indent-string": "^1.2.2",
"is-ci": "^1.0.10",
"is-glob": "^2.0.1",
@@ -15884,8 +16174,8 @@
"sanitize-filename": "^1.6.0",
"source-map-support": "^0.5.5",
"strip-bom": "^2.0.0",
- "testcafe-browser-tools": "1.6.3",
- "testcafe-hammerhead": "14.0.0",
+ "testcafe-browser-tools": "1.6.4",
+ "testcafe-hammerhead": "14.2.2",
"testcafe-legacy-api": "3.1.7",
"testcafe-reporter-json": "^2.1.0",
"testcafe-reporter-list": "^2.1.0",
@@ -16036,9 +16326,9 @@
}
},
"testcafe-browser-tools": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-1.6.3.tgz",
- "integrity": "sha512-nweLblMZEYX2rAJUX2Ju/TgGWZbWVo8I0SW/Pi7whcOPe+tduDBj+Z5NCOmpX6SyCz2iKbev31JLEioAr5q+8A==",
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-1.6.4.tgz",
+ "integrity": "sha512-I0PsEVT39C7MpjIDjJWKc7zPEl5GFAGgl/4eO8NISaJbITL0czeX9ITomMV6m3IZtk6WUWlIkOkl9R04GVa4fw==",
"dev": true,
"requires": {
"array-find": "^1.0.0",
@@ -16078,19 +16368,22 @@
}
},
"testcafe-hammerhead": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-14.0.0.tgz",
- "integrity": "sha512-2MSbTSGWSUFA9lw0J/fl3AceDOgF2Qw3Vfi6IwEXU1wr4ydxyfVEHmJpewnIVNcTBLmCHDnrm3xzvwFt4oOPtw==",
+ "version": "14.2.2",
+ "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-14.2.2.tgz",
+ "integrity": "sha512-n9vM5NeVbpv30L/73vKJe/O0AoBJWMfB9UVNAZOBuc7uleQ9jnHSaTXDOJjNO+5STVe3oPBqvQ7FDTX43m/c3A==",
"dev": true,
"requires": {
"bowser": "1.6.0",
"brotli": "^1.3.1",
"crypto-md5": "^1.0.0",
"css": "2.2.3",
+ "gulp-clone": "^2.0.1",
+ "gulp-run-command": "0.0.9",
"iconv-lite": "0.4.11",
"lodash": "4.17.10",
"lru-cache": "2.6.3",
"match-url-wildcard": "0.0.2",
+ "merge-stream": "^1.0.1",
"mime": "~1.4.1",
"mustache": "^2.1.1",
"nanoid": "^0.2.2",
@@ -16268,6 +16561,12 @@
"integrity": "sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=",
"dev": true
},
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
"throttleit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
@@ -16345,9 +16644,9 @@
"dev": true
},
"time-limit-promise": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/time-limit-promise/-/time-limit-promise-1.0.3.tgz",
- "integrity": "sha512-+0FBZPycPPgHi938ZUWrUo109SoiNm9Q2phunDBaf6Hq3RgALLTkSH5s6kM58+81obl3fNLpBozwvPw+m5MM4A==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/time-limit-promise/-/time-limit-promise-1.0.4.tgz",
+ "integrity": "sha512-FLHDDsIDducw7MBcRWlFtW2Tm50DoKOSFf0Nzx17qwXj8REXCte0eUkHrJl9QU3Bl9arG3XNYX0PcHpZ9xyuLw==",
"dev": true
},
"time-stamp": {
@@ -16362,6 +16661,12 @@
"integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=",
"dev": true
},
+ "timeout-as-promise": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/timeout-as-promise/-/timeout-as-promise-1.0.0.tgz",
+ "integrity": "sha1-c2foEfyZKs/Nzaq/LlDfr4shV28=",
+ "dev": true
+ },
"timers-browserify": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
@@ -17176,6 +17481,12 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
+ "util-extend": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
+ "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=",
+ "dev": true
+ },
"util.promisify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
@@ -17519,6 +17830,17 @@
"webpack-sources": "^1.0.1"
}
},
+ "webpack-cdn-plugin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/webpack-cdn-plugin/-/webpack-cdn-plugin-2.2.0.tgz",
+ "integrity": "sha512-gOhAB+JFD5GvRgYssPcSo+zq1Bcbs1ubNtyoBdhhOqw05djpG3R4vcbKbdy0dlj+iYZANM2NgoUBePII1VldUQ==",
+ "dev": true,
+ "requires": {
+ "babel-cli": "^6.26.0",
+ "babel-plugin-add-module-exports": "^0.2.1",
+ "babel-preset-env": "^1.7.0"
+ }
+ },
"webpack-cli": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.0.8.tgz",
@@ -17852,6 +18174,12 @@
"lodash": "^4.17.5"
}
},
+ "webpack-node-externals": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz",
+ "integrity": "sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg==",
+ "dev": true
+ },
"webpack-sources": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
@@ -18055,12 +18383,14 @@
}
},
"ws": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.0.tgz",
- "integrity": "sha512-c18dMeW+PEQdDFzkhDsnBAlS4Z8KGStBQQUcQ5mf7Nf689jyGk0594L+i9RaQuf4gog6SvWLJorz2NfSaqxZ7w==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"dev": true,
"requires": {
- "async-limiter": "~1.0.0"
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
}
},
"x-is-string": {
diff --git a/package.json b/package.json
index b416f0d..bd62c0e 100644
--- a/package.json
+++ b/package.json
@@ -16,15 +16,16 @@
"license": "MIT",
"homepage": "https://sik.ayy.fi",
"scripts": {
- "build": "npm run clean-dist && webpack -p --config=configs/webpack/prod.js",
- "clean-dist": "rm -f -r -d dist",
+ "build": "NODE_ENV=production npm-run-all build:client build:server",
+ "build:server": "webpack -p --config=configs/webpack/prod.js --env.platform=server",
+ "build:client": "webpack -p --config=configs/webpack/prod.js --env.platform=client",
"lint": "npm run lint:ts && npm run lint:sass",
"lint:ts": "tslint -p tsconfig.json --format stylish --exclude node_modules",
"lint:ts:fix": "tslint -p tsconfig.json --format stylish --exclude node_modules --fix",
"lint:sass": "stylelint ./src/**/**/*.scss ./src/**/*.scss ./src/*.scss",
"start": "npm run start-dev",
"start-dev": "webpack-dev-server --config=configs/webpack/dev.js",
- "serve": "serve -p 3000 dist",
+ "serve": "node dist/js/server.js",
"start-prod": "npm run build && npm run serve",
"mock-backend": "json-server --watch db.json -p 1234",
"test": "npm-run-all lint test:e2e",
@@ -47,10 +48,11 @@
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
+ "babel-preset-minify": "^0.4.3",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.11",
"dotenv-webpack": "^1.5.7",
- "dynamic-cdn-webpack-plugin": "^4.0.0-rc.1",
+ "express": "^4.16.3",
"favicons-webpack-plugin": "0.0.9",
"file-loader": "^1.1.11",
"fs-extra": "^6.0.1",
@@ -58,13 +60,13 @@
"husky": "^1.0.0-rc.9",
"image-webpack-loader": "^4.3.0",
"json-server": "^0.14.0",
+ "mini-css-extract-plugin": "^0.4.1",
"module-to-cdn": "^3.1.2",
+ "morgan": "^1.9.0",
"node-sass": "^4.9.0",
"npm-run-all": "^4.1.3",
"plop": "^2.0.0",
"postcss-loader": "^2.1.5",
- "prerender-spa-plugin": "^3.2.1",
- "puppeteer": "^1.5.0",
"react": "^16.4.0",
"react-addons-test-utils": "^15.6.2",
"react-dom": "^16.4.0",
@@ -75,15 +77,17 @@
"stylelint": "^9.2.1",
"stylelint-config-standard": "^18.2.0",
"stylelint-webpack-plugin": "^0.10.5",
- "testcafe": "^0.20.3",
+ "testcafe": "^0.20.5",
"testcafe-react-selectors": "^2.1.0",
"tslint": "^5.10.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.11.1",
+ "webpack-cdn-plugin": "^2.2.0",
"webpack-cli": "^3.0.3",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.1.4",
- "webpack-merge": "^4.1.2"
+ "webpack-merge": "^4.1.2",
+ "webpack-node-externals": "^1.7.2"
},
"dependencies": {
"axios": "^0.18.0",
diff --git a/src/client/App.tsx b/src/client/App.tsx
new file mode 100644
index 0000000..237bca9
--- /dev/null
+++ b/src/client/App.tsx
@@ -0,0 +1,9 @@
+import * as React from "react";
+import { BrowserRouter } from "react-router-dom";
+import Routes from "../routes";
+
+export default () => (
+
+
+
+);
diff --git a/src/client/index.ts b/src/client/index.ts
new file mode 100644
index 0000000..a985923
--- /dev/null
+++ b/src/client/index.ts
@@ -0,0 +1,7 @@
+import * as React from "react";
+import { hydrate } from "react-dom";
+import App from "./App";
+
+const elem = document.getElementById("root");
+
+hydrate(React.createElement(App), elem);
diff --git a/src/index.scss b/src/index.scss
index 2fc91f6..7f56439 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -1,3 +1,4 @@
+@import "./assets/scss/normalize";
@import "./assets/scss/globals";
html,
@@ -19,7 +20,7 @@ body {
body {
max-width: 1200px;
padding: 0 0.5rem;
- margin: auto;
+ margin: auto !important;
}
h1 {
diff --git a/src/index.tsx b/src/index.tsx
index e24297c..b57b146 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,9 +3,7 @@ import {render} from "react-dom";
import { BrowserRouter } from "react-router-dom";
import {AppContainer} from "react-hot-loader";
import Routes from "./routes";
-import "normalize.css";
import "./index.scss";
-import "./index.d.ts";
const rootEl = document.getElementById("root");
diff --git a/src/routes.tsx b/src/routes.tsx
index 0ff8db0..0ea8ce7 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -3,6 +3,7 @@ import { Switch, Route } from "react-router-dom";
import FrontPage from "./pages/FrontPage";
import NotFoundPage from "./pages/NotFoundPage";
import CommonPage from "./pages/CommonPage";
+import "./index.scss";
const Routes = () => (
diff --git a/src/server/App.tsx b/src/server/App.tsx
new file mode 100644
index 0000000..2a0e05b
--- /dev/null
+++ b/src/server/App.tsx
@@ -0,0 +1,9 @@
+import * as React from "react";
+import { StaticRouter } from "react-router-dom";
+import Routes from "../routes";
+
+export default ({ url }) => (
+
+
+
+);
diff --git a/src/server/index.ts b/src/server/index.ts
new file mode 100644
index 0000000..f5db3aa
--- /dev/null
+++ b/src/server/index.ts
@@ -0,0 +1,27 @@
+import * as React from "react";
+import * as express from "express";
+import { renderToString } from "react-dom/server";
+import * as morgan from "morgan";
+
+import App from "./App";
+import * as fs from "fs";
+import * as path from "path";
+
+const port = 3000;
+const server = express();
+
+const indexHtml = fs.readFileSync(path.resolve("./dist/index.html"), "utf-8");
+const html = body => indexHtml.replace("", `${body}
`);
+
+server.use(morgan("short"));
+server.use("/assets", express.static("dist/assets"));
+server.use("/js", express.static("dist/js"));
+
+server.get("*", (req, res) => {
+ const result = renderToString(React.createElement(App, { url: req.url }));
+ res.send(
+ html(result)
+ );
+});
+
+server.listen(3000, () => console.log("React SSR express server listening on port 3000!"));