Skip to content

Instantly share code, notes, and snippets.

@BiosBoy
Created March 22, 2020 06:13
Show Gist options
  • Select an option

  • Save BiosBoy/d242b85c02550d28aeb450a81a40fb6b to your computer and use it in GitHub Desktop.

Select an option

Save BiosBoy/d242b85c02550d28aeb450a81a40fb6b to your computer and use it in GitHub Desktop.
const webpack = require('webpack')
const path = require('path')
// CSS Optimization Plugins
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
// JS Optimization Plugins
const TerserPlugin = require('terser-webpack-plugin')
// HTML Optimization Plugins
const HtmlWebpackPlugin = require('html-webpack-plugin')
// Helpers
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const debug = require('debug')('app:webpack::config')
const globals = require('./globals/js/environments')
const options = require('./config/processor')
// ------------------------------------
// Rules
// ------------------------------------
const fileLoadersRules = [
// JAVSCRIPT|TYPESCRIPT
{
test: /\.(js|jsx|ts|tsx)?$/,
loader: 'ts-loader',
options: {
compilerOptions: {
target: __DEV__ ? 'esnext' : 'es5'
}
},
exclude: [/node_modules/]
},
// JSON
{
type: 'javascript/auto',
test: /\.json$/,
loader: 'json-loader'
},
// CSS
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: true,
reloadAll: true
}
},
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
{
loader: 'postcss-loader'
}
]
},
// SCSS
{
test: /\.scss$/,
exclude: /\.cssmodule\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: true,
reloadAll: true
}
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
mode: 'global'
}
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
data: '@import "index.scss";',
includePaths: [path.resolve(__dirname, './globals/styles')]
}
}
]
},
// CSSMODULE.SCSS
{
test: /(\.cssmodule|\.cssmodule\.scss)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: true,
reloadAll: true
}
},
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: {
localIdentName: '[local]___[hash:base64:5]'
}
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
data: '@import "index.scss";',
includePaths: [path.resolve(__dirname, './globals/styles')]
}
}
]
},
// FONTS
{
test: /\.woff(\?.*)?$/,
loader: 'url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff'
},
{
test: /\.woff2(\?.*)?$/,
loader: 'url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff2'
},
{
test: /\.otf(\?.*)?$/,
loader: 'file-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=font/opentype'
},
{
test: /\.ttf(\?.*)?$/,
loader: 'url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/octet-stream'
},
{
test: /\.eot(\?.*)?$/,
loader: 'file-loader?prefix=fonts/&name=[path][name].[ext]'
},
// IMAGES
{
test: /\.svg(\?.*)?$/,
loader: 'url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=image/svg+xml'
},
{
test: /\.(png|jpg|webp)$/,
loader: 'url-loader?limit=8192'
}
]
// ------------------------------------
// Optimization
// ------------------------------------
const compOptimization = {
splitChunks: {
chunks: 'all',
minChunks: 2
},
minimizer: [
new TerserPlugin({
test: /\.(js|jsx|ts|tsx)?$/i,
parallel: true,
sourceMap: true,
extractComments: false,
terserOptions: {
module: true,
output: {
ecma: '5',
comments: false,
beautify: false
},
compress: {
ecma: '5',
toplevel: true,
dead_code: true
}
}
}),
new OptimizeCSSAssetsPlugin({})
]
}
// ------------------------------------
// Entry Points
// ------------------------------------
const appEntry = {
test: [options.app_entry],
development: [options.app_entry].concat('webpack-hot-middleware/client?path=/__webpack_hmr'),
production: ['whatwg-fetch', options.app_entry] // whatwg-fetch - fetch support for IE11
}
// ------------------------------------
// Bundle externals
// ------------------------------------
const externalBundles = {
react: 'React',
'react-dom': 'ReactDOM',
'react-dom/server': 'ReactDOMServer'
}
// ------------------------------------
// Bundle Output
// ------------------------------------
const outputBundles = {
filename: '[name].[hash].js',
chunkFilename: '[name].[hash].js',
path: options.app_public,
publicPath: __DEV__ ? options.app_local : options.app_remote
}
// ------------------------------------
// Plugins
// ------------------------------------
const plugins = [
new webpack.DefinePlugin(globals),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[name].[hash].css'
}),
new webpack.SourceMapDevToolPlugin({
test: /\.(js|jsx|ts|tsx|json|css|scss)$/,
filename: '[file].map[query]',
exclude: ['vendor.js']
})
]
// ------------------------------------
// Extra Plugins By Running Mode
// ------------------------------------
const extraPluginsByModes = {
test: [new BundleAnalyzerPlugin()],
development: [
new HtmlWebpackPlugin({
template: options.app_index,
filename: options.index,
minify: false,
inject: false,
chunksSortMode: __CT_CHUNK_FIX__ ? 'none' : 'auto' // temporary fix for CT app
}),
new webpack.HotModuleReplacementPlugin()
],
production: [
new HtmlWebpackPlugin({
template: options.template_local_path,
filename: options.template_local_name,
minify: false,
inject: false
})
]
}
const createConfig = () => {
debug('\x1b[36m', '=== Prepearing Webpack to work... ===')
debug('\x1b[35m', `✔ mode: ${__NODE_ENV__}`)
const webpackConfig = {
mode: __WEBPACK_MODE__,
name: 'client',
target: 'web',
stats: {}, // stats is overridden by webpack-dev-middleware! No need to duplicate them here.
optimization: compOptimization,
devtool: false,
entry: {
app: appEntry[__NODE_ENV__]
},
externals: externalBundles,
output: outputBundles,
module: {
rules: fileLoadersRules
},
plugins: [...plugins, ...extraPluginsByModes[__NODE_ENV__]],
performance: {
hints: false
},
resolve: {
modules: [options.app_client, 'node_modules'],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
}
}
debug('\x1b[36m', '=== Webpack is configured successfuly! ===')
return webpackConfig
}
module.exports = createConfig()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment