Skip to content

Instantly share code, notes, and snippets.

@adrianorsouza
Created August 28, 2019 05:20
Show Gist options
  • Save adrianorsouza/d95889cbca82511788f7bda7b22a1f66 to your computer and use it in GitHub Desktop.
Save adrianorsouza/d95889cbca82511788f7bda7b22a1f66 to your computer and use it in GitHub Desktop.
Full Webpack configuration for Laravel, ReactJS and Bootstrap + LiveServer.
const fs = require('fs');
const os = require('os');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const postcssNormalize = require('postcss-normalize');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const env = process.env.NODE_ENV;
const dev = env !== "production";
const isEnvDevelopment = env === 'development';
const isEnvProduction = env === 'production';
const hmr = process.argv.includes('--hot') === true;
const publicPath = 'public/assets';
const hotFile = `${publicPath}/hot`;
console.log(dev, env);
module.exports = {
devtool: dev ? "inline-sourcemap" : false,
// externals : ['jquery', 'react'],
mode: `${env}`,
entry: {
page1: ['./resources/js/page1.js', './resources/sass/page1.scss'],
page2: ['./resources/js/page2.js', './resources/sass/page2.scss'],
},
output: {
path: path.resolve(__dirname, 'public/assets'),
// filename: 'page1.bundle.js',
// chunkFilename: '[name].bundle.js',
filename: dev ? 'js/[name].bundle.js' : 'js/[name].[contenthash:8].js',
// chunkFilename: dev ? '[name].chunk.js' : '[name].chunk.js',//'[name].[contenthash:8].bundle.js'
// publicPath: path.resolve(__dirname, 'public/assets/js'),
},
// resolve: {
// alias: {
// jquery: 'jquery/src/jquery'
// },
// },
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader'
// @babel/plugin-proposal-class-properties
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: './css',
hmr: isEnvDevelopment,
},
},
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
// Adds PostCSS Normalize as the reset css with default options,
// so that it honors browserslist config in package.json
// which in turn let's users customize the target behavior as per their needs.
postcssNormalize(),
],
sourceMap: isEnvProduction,
},
},
{
loader: 'sass-loader' // compiles Sass to CSS
}
],
},
],
},
plugins: [
// new webpack.ProvidePlugin({
// $: 'jquery',
// jQuery: 'jquery'
// }),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: dev ? 'css/[name].css' : 'css/[name].[hash].css',
chunkFilename: dev ? 'css/[name].css' : 'css/[name].[hash].css',
}),
!hmr && new CleanWebpackPlugin({
dry: false,
verbose: true,
cleanOnceBeforeBuildPatterns: ['**/*.js', '**/*.css', '!fonts*'],
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
new ManifestPlugin({
basePath: '',
fileName: '../../asset-manifest.json',
publicPath: '/assets/',
generate: (seed, files) => {
const manifestFiles = files.reduce(function(manifest, file) {
manifest[file.name] = file.path;
return manifest;
}, seed);
return {
files: manifestFiles,
};
},
}),
].filter(Boolean),
optimization: {
minimize: !dev,
minimizer: [
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
parser: safePostCssParser,
map: false,
},
// cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: false } }],
},
}),
// This is only used in production mode
new TerserPlugin({
terserOptions: {
parse: {
// We want terser to parse ecma 8 code. However, we don't want it
// to apply any minification steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebook/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false,
// Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250
// Pending further investigation:
// https://github.com/terser-js/terser/issues/120
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
// Disabled on WSL (Windows Subsystem for Linux) due to an issue with Terser
// https://github.com/webpack-contrib/terser-webpack-plugin/issues/21
parallel: true,
// Enable file caching
cache: true,
sourceMap: false,
})
],
splitChunks: {
// // chunks: 'async',
// 15k will make account split chunks within dev and prod builds
minSize: 15000,
// // maxSize: 300000,
cacheGroups: {
// react: {
// test: /[\\/]node_modules[\\/](react(.+)|redux(.+))[\\/]/,
// name: 'react',
// chunks: 'all',
// },
// jquery: {
// test: /[\\/]node_modules[\\/](jquery(.+))[\\/]/,
// name: 'jquery',
// chunks: 'all',
// },
// vendors: {
// test: /[\\/]node_modules[\\/]/,
// // name: 'vendors',
// name(module, chunks, cacheGroupKey) {
// const moduleFileName = module.identifier().split('/').reduceRight(item => item);
// const allChunksNames = chunks.map((item) => item.name).join('~');
// console.log(allChunksNames);
// return `${cacheGroupKey}-${allChunksNames}`;
// },
// chunks: 'all',
// },
commons: {
name: 'commons',
chunks: 'all',
minChunks: 2
},
},
chunks: 'all',
name: true,
},
// runtimeChunk: false,
},
devServer: {
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 3000,
publicPath: '/assets/',
sockPath: '',
https: {
key: fs.readFileSync(path.join('server', 'localhost.key')),
cert: fs.readFileSync(path.join('server', 'localhost.crt')),
// ca: fs.readFileSync('/path/to/ca.pem'),
},
disableHostCheck: true,
clientLogLevel: 'none',
watchContentBase: true,
quiet: true,
overlay: false,
}
};
if (hmr) {
const url = `https://localhost:3000`;
fs.writeFileSync(hotFile, url + os.EOL);
['SIGINT', 'SIGTERM'].forEach(function(sig) {
process.on(sig, function() {
if (fs.existsSync(hotFile)) {
fs.unlinkSync(hotFile);
}
process.exit();
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment