Skip to content

Instantly share code, notes, and snippets.

@blackakula
Created August 5, 2021 19:53
Show Gist options
  • Save blackakula/37c53183b68ba0fbcdcd56ce8ec6d2a9 to your computer and use it in GitHub Desktop.
Save blackakula/37c53183b68ba0fbcdcd56ce8ec6d2a9 to your computer and use it in GitHub Desktop.
Webpack build server side rendering
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack');
const paths = require('../paths');
const resolvers = require('./resolvers');
const loaders = require('./loaders');
const plugins = require('./plugins');
const devMode = process.env.NODE_ENV === 'development';
const publicPath = `${devMode ? '' : `https://${process.env.CDN_S3_BUCKET}`}${paths.publicPath}`;
module.exports = [
{
name: 'client',
target: 'web',
mode: devMode ? 'development' : 'production',
devtool: devMode ? 'cheap-module-inline-source-map' : 'source-map',
entry: {
bundle: [
require.resolve('core-js/stable'),
require.resolve('regenerator-runtime/runtime'),
`${paths.srcClient}/index.tsx`,
],
},
output: {
path: path.join(paths.clientBuild, paths.publicPath),
publicPath,
filename: 'bundle.[hash:8].js',
chunkFilename: '[name].[chunkhash:8].chunk.js',
},
module: {
rules: [
{
oneOf: [loaders.ts, loaders.svg, loaders.woff, loaders.cssClient, loaders.html],
},
],
},
resolve: { ...resolvers },
plugins: [...plugins.shared, ...plugins.client],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
parse: {
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
comparisons: false,
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
},
parallel: true,
cache: true,
sourceMap: true,
}),
],
namedModules: true,
noEmitOnErrors: true,
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
},
stats: {
colors: true,
},
},
{
name: 'server',
target: 'node',
mode: devMode ? 'development' : 'production',
devtool: devMode ? 'cheap-module-inline-source-map' : 'source-map',
entry: {
server: [
require.resolve('core-js/stable'),
require.resolve('regenerator-runtime/runtime'),
path.resolve(paths.srcServer, 'index.ts'),
],
},
externals: [
nodeExternals({
whitelist: /\.css$/,
}),
],
output: {
path: paths.serverBuild,
filename: 'server.js',
publicPath,
library: 'server',
libraryTarget: 'var',
},
resolve: { ...resolvers },
module: {
rules: [
{
oneOf: [loaders.ts, loaders.svg, loaders.woff, loaders.cssServer, loaders.html],
},
],
},
plugins: [...plugins.shared, ...plugins.server],
stats: {
colors: true,
},
},
];
/* eslint-disable no-console */
require('dotenv').config();
const webpack = require('webpack');
const rimraf = require('rimraf');
const webpackConfig = require('../config/webpack');
const paths = require('../config/paths');
const { compilerPromise, webpackHandler } = require('./utils');
const build = async () => {
rimraf.sync(paths.clientBuild);
rimraf.sync(paths.serverBuild);
const [clientConfig, serverConfig] = webpackConfig;
const multiCompiler = webpack([clientConfig, serverConfig]);
const [clientCompiler, serverCompiler] = multiCompiler.compilers;
const clientPromise = compilerPromise(clientCompiler);
const serverPromise = compilerPromise(serverCompiler);
serverCompiler.run((err, stats) => webpackHandler(err, stats, serverConfig.stats));
clientCompiler.run((err, stats) => webpackHandler(err, stats, clientCompiler.stats));
try {
await serverPromise;
await clientPromise;
} catch (error) {
console.error(error);
process.exitCode = 1;
}
};
build();
module.exports = {
build,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment