Created
February 19, 2020 10:35
-
-
Save agwells/d2fc78cd0a9fd33be3a32a6d49fe336f to your computer and use it in GitHub Desktop.
Webpack config to compile Create React App code to execute in Node
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path'); | |
const nodeExternals = require('webpack-node-externals'); | |
const NodemonPlugin = require('nodemon-webpack-plugin'); | |
// Directory the compiled SSR server and assets will go in | |
const SSR_BUILD_PATH = './ssr-build' | |
const originalNodeEnv = process.env.NODE_ENV; | |
// This must be "production" for the CRA webpack config to be correct. | |
process.env.NODE_ENV = 'production'; | |
const makeConfig = require('react-scripts/config/webpack.config.js'); | |
const baseConfig = makeConfig('production'); | |
// Now we can change it back (so that if we're running this in watch mode, | |
// it'll use "production" for compiling, but "development" for running the server) | |
process.env.NODE_ENV = originalNodeEnv; | |
// Remove the eslint loader since we do linting elsewhere. | |
// (This greatly speeds up build times) | |
baseConfig.module.rules.splice(1, 1); | |
// Override some parts of the default CRA config. | |
const config = { | |
...baseConfig, | |
bail: true, | |
// We don't need to minimize anything, because this HTML won't be served over the internet directly | |
optimization: { | |
minimize: false, | |
nodeEnv: false, | |
namedModules: true, | |
namedChunks: true, | |
moduleIds: 'named', | |
chunkIds: 'named', | |
}, | |
// We want the compiled code to run in a Node environment | |
target: 'node', | |
// Start the dependency graph from this file (instead of `src/index.tsx`) | |
entry: path.resolve('./src/server/index.ts'), | |
output: { | |
// Name to use for the compiled bundle (executing this will be like | |
// executing `src/server/index.ts`) | |
filename: 'server.js', | |
// Put build products here | |
path: path.resolve(SSR_BUILD_PATH), | |
// The base URL path for the app (so links to static assets will be relative | |
// to this.) | |
publicPath: '/', | |
}, | |
// Don't mock any node libraries (we don't need to mock them because we're | |
// actually running in Node. :-P) | |
node: false, | |
// Don't bundle in `node_modules` (the running app can just load in the files | |
// from `node_modules` itself) | |
externals: [ | |
nodeExternals(), | |
], | |
// Keep only these two plugins. The others are related to features we don't | |
// need when compiling for SSR (like linting, generating the manifest, etc) | |
plugins: [ | |
...baseConfig.plugins.filter((plugin) => | |
['HtmlWebpackPlugin', 'MiniCssExtractPlugin'].includes( | |
plugin.constructor.name | |
) | |
), | |
// Use nodemon for hot-reloading SSR server, when running Webpack in "watch" mode | |
new NodemonPlugin({ script: path.resolve(SSR_BUILD_PATH, 'server.js') }), | |
], | |
}; | |
module.exports = config; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment