diff --git a/package.json b/package.json index b0b27e0..dcdfa8c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,13 @@ "start:dev": "webpack-dev-server --config webpack.config.dev.js --port 3000", "prestart:api": "node tools/createMockDb.js", "start:api": "node tools/apiServer.js", - "test": "jest --watch" + "test": "jest --watch", + "test:ci": "jest", + "clean:build": "rimraf ./build && mkdir build", + "prebuild": "run-p clean:build test:ci", + "build": "webpack --config webpack.config.prod.js", + "postbuild": "run-p start:api serve:build", + "serve:build": "http-server ./build" }, "jest": { "setupFiles": [ diff --git a/src/redux/configureStore.dev.js b/src/redux/configureStore.dev.js new file mode 100644 index 0000000..59f0345 --- /dev/null +++ b/src/redux/configureStore.dev.js @@ -0,0 +1,15 @@ +import { createStore, applyMiddleware, compose } from "redux"; +import rootReducer from "./reducers"; +import reduxImmutableStateInvariant from "redux-immutable-state-invariant"; +import thunk from "redux-thunk"; + +export default function configureStore(initialState) { + const composeEnhancers = + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; //add support for Redux dev tools + + return createStore( + rootReducer, + initialState, + composeEnhancers(applyMiddleware(thunk, reduxImmutableStateInvariant())) + ); +} diff --git a/src/redux/configureStore.js b/src/redux/configureStore.js index 59f0345..ea938bf 100644 --- a/src/redux/configureStore.js +++ b/src/redux/configureStore.js @@ -1,15 +1,6 @@ -import { createStore, applyMiddleware, compose } from "redux"; -import rootReducer from "./reducers"; -import reduxImmutableStateInvariant from "redux-immutable-state-invariant"; -import thunk from "redux-thunk"; - -export default function configureStore(initialState) { - const composeEnhancers = - window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; //add support for Redux dev tools - - return createStore( - rootReducer, - initialState, - composeEnhancers(applyMiddleware(thunk, reduxImmutableStateInvariant())) - ); +// Use CommonJS require below so we can dynamically import during build-time. +if (process.env.NODE_ENV === "production") { + module.exports = require("./configureStore.prod"); +} else { + module.exports = require("./configureStore.dev"); } diff --git a/src/redux/configureStore.prod.js b/src/redux/configureStore.prod.js new file mode 100644 index 0000000..fe88e67 --- /dev/null +++ b/src/redux/configureStore.prod.js @@ -0,0 +1,7 @@ +import { createStore, applyMiddleware } from "redux"; +import rootReducer from "./reducers"; +import thunk from "redux-thunk"; + +export default function configureStore(initialState) { + return createStore(rootReducer, initialState, applyMiddleware(thunk)); +} diff --git a/webpack.config.prod.js b/webpack.config.prod.js new file mode 100644 index 0000000..354a83c --- /dev/null +++ b/webpack.config.prod.js @@ -0,0 +1,78 @@ +const webpack = require("webpack"); +const path = require("path"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const webpackBundleAnalyzer = require("webpack-bundle-analyzer"); + +process.env.NODE_ENV = "production"; + +module.exports = { + mode: "production", + target: "web", + devtool: "source-map", + entry: "./src/index", + output: { + path: path.resolve(__dirname, "build"), + publicPath: "/", + filename: "bundle.js" + }, + plugins: [ + // Display bundle stats + new webpackBundleAnalyzer.BundleAnalyzerPlugin({ analyzerMode: "static" }), + + new MiniCssExtractPlugin({ + filename: "[name].[contenthash].css" + }), + + new webpack.DefinePlugin({ + // This global makes sure React is built in prod mode. + "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), + "process.env.API_URL": JSON.stringify("http://localhost:3001") + }), + new HtmlWebpackPlugin({ + template: "src/index.html", + favicon: "src/favicon.ico", + minify: { + // see https://github.com/kangax/html-minifier#options-quick-reference + removeComments: true, + collapseWhitespace: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeStyleLinkTypeAttributes: true, + keepClosingSlash: true, + minifyJS: true, + minifyCSS: true, + minifyURLs: true + } + }) + ], + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + use: ["babel-loader", "eslint-loader"] + }, + { + test: /(\.css)$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: "css-loader", + options: { + sourceMap: true + } + }, + { + loader: "postcss-loader", + options: { + plugins: () => [require("cssnano")], + sourceMap: true + } + } + ] + } + ] + } +};