@25sprout/react-starter
Version:
25sprout web starter with React
185 lines (178 loc) • 4.37 kB
JavaScript
import path from 'path';
import webpack from 'webpack';
import atImport from 'postcss-import';
import cssnext from 'postcss-cssnext';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import palette from './config/palette';
import media from './config/media';
import env from './config/env';
const extractText = new ExtractTextPlugin({
filename: '[name].[contenthash].css',
allChunks: true,
});
const extractGlobalText = new ExtractTextPlugin('vendor.[contenthash].css');
const webpackProdConfig = {
devtool: 'source-map',
entry: {
app: './src/index.js',
vendor: ['babel-polyfill', 'whatwg-fetch', 'react', 'react-container-helper', 'react-dom'],
},
output: {
path: path.join(__dirname, '_public'),
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].chunk.js',
publicPath: '',
},
plugins: [
new webpack.DefinePlugin({
'process.env': env,
}),
// Chunk js file for vendor
// See https://webpack.js.org/guides/code-splitting-libraries/#manifest-file
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor', 'manifest'],
minChunks: Infinity,
}),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
removeScriptTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
inject: true,
showErrors: false,
filename: 'index.html',
chunksSortMode: 'dependency',
}),
extractGlobalText,
extractText,
],
module: {
rules: [
{
test: /\.js?$/,
include: [path.join(__dirname, 'src')],
exclude: path.join(__dirname, 'node_modules'),
loader: 'babel-loader',
options: {
presets: [['es2015', { loose: true, modules: false }], 'react', 'stage-3'],
},
},
{
test: /\.css$/,
include: path.join(__dirname, 'src'),
use: extractText.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
camelCase: true,
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
minimize: true,
autoprefixer: false,
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production' ? 'inline' : false,
plugins: () => [
atImport(),
cssnext({
features: {
customProperties: {
variables: palette,
},
customMedia: {
extensions: media,
},
},
}),
],
},
},
],
}),
},
{
test: /\.css$/,
include: path.join(__dirname, 'node_modules'),
use: extractGlobalText.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
minimize: true,
autoprefixer: false,
},
},
],
}),
},
{
test: /\.(jpe?g|png|gif)$/,
include: path.join(__dirname, 'src'),
loader: 'url-loader',
options: {
limit: 10000,
name: './assets/[name]__[hash].[ext]',
},
},
{
test: /\.svg$/,
include: path.join(__dirname, 'src'),
use: [
'babel-loader',
'svg-react-loader',
{
loader: 'svgo-loader',
options: {
plugins: [{ removeTitle: true }, { collapseGroups: false }],
},
},
'svg-css-modules-loader',
{
loader: 'string-replace-loader',
options: {
search: '%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22',
replace: '',
},
},
],
},
],
},
node: {
fs: 'empty',
},
resolve: {
modules: ['node_modules'],
},
};
// Minify and optimize the JavaScript
if (process.env.NODE_ENV === 'production') {
webpackProdConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
}));
webpackProdConfig.plugins.push(new webpack.LoaderOptionsPlugin({
minimize: true,
}));
}
export default webpackProdConfig;