yacd/webpack.config.js
2019-12-20 23:02:10 +08:00

209 lines
5.6 KiB
JavaScript

'use strict';
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ReactRefreshWebpackPlugin = require('@hsjs/react-refresh-webpack-plugin');
// const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const pkg = require('./package.json');
process.env.BABEL_ENV = process.env.NODE_ENV;
const isDev = process.env.NODE_ENV !== 'production';
const resolveDir = dir => path.resolve(__dirname, dir);
const HTMLPlugin = require('html-webpack-plugin');
const html = new HTMLPlugin({
title: 'yacd - Yet Another Clash Dashboard',
template: 'src/index.template.ejs',
inject: false,
filename: 'index.html'
});
const definePlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(isDev),
__VERSION__: JSON.stringify(pkg.version),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
});
const postcssPlugins = () =>
[
require('postcss-import')(),
require('postcss-custom-media')({
importFrom: [
{
customMedia: {
'--breakpoint-not-small': 'screen and (min-width: 30em)',
'--breakpoint-medium':
'screen and (min-width: 30em) and (max-width: 60em)',
'--breakpoint-large': 'screen and (min-width: 60em)'
}
}
]
}),
require('postcss-nested')(),
require('autoprefixer')(),
require('postcss-extend-rule')(),
isDev ? false : require('cssnano')()
].filter(Boolean);
const cssExtractPlugin = new MiniCssExtractPlugin({
filename: isDev ? '[name].css' : '[name].[contenthash].css'
});
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const bundleAnalyzerPlugin = new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'report.html',
openAnalyzer: false
});
const plugins = [
// in webpack 4 namedModules will be enabled by default
html,
definePlugin,
new CopyPlugin([{ from: 'assets/*', flatten: true }]),
new CleanWebpackPlugin(),
// chart.js requires moment
// and we don't need locale stuff in moment
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// https://github.com/pmmmwh/react-refresh-webpack-plugin
isDev ? new ReactRefreshWebpackPlugin({ disableRefreshCheck: true }) : false,
isDev ? false : new webpack.HashedModuleIdsPlugin(),
isDev ? false : cssExtractPlugin,
isDev ? false : bundleAnalyzerPlugin
].filter(Boolean);
module.exports = {
// https://webpack.js.org/configuration/devtool/
devtool: isDev ? 'eval-source-map' : false,
entry: {
// app: ['react-hot-loader/patch', './src/app.js']
app: ['./src/app.js']
},
output: {
path: path.resolve(__dirname, 'public'),
// use contenthash instead of chunkhash to take advantage of caching
filename: isDev ? '[name].bundle.js' : '[name].[contenthash].js',
publicPath: ''
},
mode: isDev ? 'development' : 'production',
resolve: {
alias: {
// 'react-dom': '@hot-loader/react-dom',
a: resolveDir('src/api'),
s: resolveDir('src/svg'),
m: resolveDir('src/misc'),
d: resolveDir('src/ducks'),
c: resolveDir('src/components')
}
},
module: {
rules: [
{
test: /\.svg$/,
use: ['svg-sprite-loader']
},
// js loader
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
},
// file loader
{
test: /\.(ttf|eot|woff|woff2)(\?.+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
]
},
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: [
isDev
? {
loader: 'style-loader'
}
: MiniCssExtractPlugin.loader,
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: {
plugins: postcssPlugins
}
}
].filter(Boolean)
},
{
test: /\.module\.css$/,
use: [
isDev
? {
loader: 'style-loader'
}
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
localIdentName: isDev
? '[path]_[name]_[local]_[hash:base64:5]'
: '[hash:base64:10]'
}
}
},
{
loader: 'postcss-loader',
options: {
plugins: postcssPlugins
}
}
].filter(Boolean)
}
]
},
optimization: {
moduleIds: 'hashed',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
'core-js': {
test(module, chunks) {
return (
module.resource &&
module.resource.indexOf('node_modules/core-js/') >= 0
);
}
},
react: {
test(module, chunks) {
return (
module.resource &&
(module.resource.indexOf('node_modules/@hot-loader/react-dom/') >=
0 ||
module.resource.indexOf('node_modules/react-dom/') >= 0 ||
module.resource.indexOf('node_modules/react/') >= 0)
);
}
}
}
},
minimizer: [new TerserPlugin()]
},
plugins
};