react-static
Version:
A progressive static site generator for React
193 lines (182 loc) • 5.58 kB
JavaScript
import webpack from 'webpack'
import path from 'path'
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import TerserPlugin from 'terser-webpack-plugin'
import nodeExternals from 'webpack-node-externals'
import ExtractCssChunks from 'extract-css-chunks-webpack-plugin'
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin'
import resolveFrom from 'resolve-from'
//
import rules from './rules'
function common(state) {
const { analyze, config, debug } = state
const { ROOT, DIST, NODE_MODULES, SRC, ASSETS } = config.paths
process.env.REACT_STATIC_ENTRY_PATH = config.entry
process.env.REACT_STATIC_SITE_ROOT = config.siteRoot
process.env.REACT_STATIC_BASE_PATH = config.basePath
process.env.REACT_STATIC_PUBLIC_PATH = config.publicPath
process.env.REACT_STATIC_ASSETS_PATH = config.assetsPath
if (!DIST.startsWith(ROOT)) {
// we build outside of project dir, so reset some paths
process.env.REACT_STATIC_ASSETS_PATH = config.assetsPath.replace(DIST, '')
}
const splitChunks = {
chunks: 'all',
minSize: 10000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 5,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'all',
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
}
let extrackCSSChunks = new ExtractCssChunks({
filename: '[name].[contentHash:8].css',
chunkFilename: '[id].[contentHash:8].css',
})
if (!config.extractCssChunks) {
splitChunks.cacheGroups = {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
}
extrackCSSChunks = new ExtractCssChunks({
filename: '[name].[contentHash:8].css',
})
}
return {
mode: 'production',
context: path.resolve(__dirname, '../../../node_modules'),
entry: config.disableRuntime
? config.entry
: [
require.resolve('../../bootstrapPlugins'),
require.resolve('../../bootstrapTemplates'),
require.resolve('../../bootstrapApp'),
],
output: {
filename: '[name].[contentHash:8].js',
chunkFilename: 'templates/[name].[contentHash:8].js',
path: ASSETS,
publicPath: process.env.REACT_STATIC_ASSETS_PATH || '/',
},
optimization: {
sideEffects: true,
minimize: true,
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
exclude: /\.min\.js/,
...config.terser,
sourceMap:
config.productionSourceMaps || config.terser.sourceMap || debug,
terserOptions: {
ie8: false,
...config.terser.terserOptions,
mangle: { safari10: true, ...config.terser.terserOptions.mangle },
parse: { ecma: 8, ...config.terser.terserOptions.parse },
compress: { ecma: 5, ...config.terser.terserOptions.compress },
output: { ecma: 5, ...config.terser.terserOptions.output },
},
}),
new OptimizeCSSAssetsPlugin({}),
],
splitChunks,
},
performance: {
maxEntrypointSize: 300000,
},
module: {
rules: rules({ config, stage: 'prod', isNode: false }),
strictExportPresence: true,
},
resolve: {
modules: [
NODE_MODULES,
SRC,
DIST,
...[NODE_MODULES, SRC, DIST].map(d =>
DIST.startsWith(ROOT) ? path.resolve(__dirname, d) : path.resolve(d)
),
'node_modules',
],
extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx'],
alias: {
react$: resolveFrom(config.paths.NODE_MODULES, 'react'),
'react-dom$': resolveFrom(config.paths.NODE_MODULES, 'react-dom'),
'react-universal-component': resolveFrom(
__dirname,
'react-universal-component'
),
__react_static_root__: config.paths.ROOT,
},
},
externals: [],
target: undefined,
plugins: [
new webpack.EnvironmentPlugin(process.env),
extrackCSSChunks,
new CaseSensitivePathsPlugin(),
analyze && new BundleAnalyzerPlugin(),
].filter(d => d),
devtool: debug || config.productionSourceMaps ? 'source-map' : false,
}
}
export default function(state) {
const {
stage,
config: { paths },
} = state
const result = common(state)
if (stage !== 'node') return result
// Node only!!!
result.output.filename = 'static-app.js'
result.output.path = paths.ARTIFACTS
result.output.libraryTarget = 'umd'
result.optimization.minimize = false
result.optimization.minimizer = []
result.target = 'node'
result.devtool = false
result.externals = [
new RegExp(`${paths.PLUGINS}`),
(context, request, callback) => {
const resolved = path.resolve(context, request)
if (
[/react-static(\\|\/)lib(\\|\/)browser/, /webpack-flush-chunks/].some(
d => d.test(resolved)
)
) {
return callback(null, `commonjs ${resolved}`)
}
callback()
},
nodeExternals({
whitelist: ['react-universal-component'],
}),
]
result.module.rules = rules(state)
result.plugins = [
new webpack.EnvironmentPlugin(process.env),
new CaseSensitivePathsPlugin(),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
]
return result
}