airdcpp-webui
Version:
201 lines (179 loc) • 5.75 kB
JavaScript
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
const zopfli = require('@gfx/zopfli');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin2');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const { InjectManifest } = require('workbox-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
// const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
//const ReactRefreshTypeScript = require('react-refresh-typescript');
// Webpack doesn't set the ENV, which causes issues with some plugins: https://github.com/webpack/webpack/issues/2537
if (process.argv.indexOf('-p') !== -1 && !process.env.NODE_ENV) {
process.env.NODE_ENV = 'production';
} else if (!process.env.NODE_ENV) {
process.env.NODE_ENV = 'development';
}
// Service worker must be in the root because of scopes
process.env.SERVICEWORKER = 'sw.js';
const release = process.env.NODE_ENV === 'production';
const chalk = require('chalk');
const parseLocaleRegex = () => {
const locales = fs
.readdirSync(path.join(__dirname, 'resources/locales'))
.filter((f) => !f.endsWith('.js'))
.map((loc) => `${loc}$`);
const ret = `${locales.join('|')}`;
return new RegExp(ret);
};
// PLUGINS
let plugins = [
//new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // Those are about 40 kilobytes
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, parseLocaleRegex()),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.SERVICEWORKER': JSON.stringify(process.env.SERVICEWORKER),
UI_VERSION: JSON.stringify(require('./package.json').version),
UI_BUILD_DATE: JSON.stringify(new Date().getTime()),
}),
new HtmlWebpackPlugin({
template: 'resources/index.ejs',
inject: false,
chunksSortMode: 'none',
}),
new ForkTsCheckerWebpackPlugin(),
];
const releasePlugins = [
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false,
}),
new CompressionPlugin({
filename: '[file].gz',
test: /\.js$/,
threshold: 0,
minRatio: 1,
compressionOptions: {
numiterations: 15,
},
algorithm(input, compressionOptions, callback) {
return zopfli.gzip(input, compressionOptions, callback);
},
}),
new Visualizer({
filename: '../stats.html',
}),
new InjectManifest({
swSrc: path.join(__dirname, 'src/sw.js'),
swDest: process.env.SERVICEWORKER,
include: [/\.(js|html)$/],
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, // Size of the uncompressed entry chunk exceeds the default limit
}),
];
const debugPlugins = [
// new webpack.HotModuleReplacementPlugin(),
// new ReactRefreshWebpackPlugin(),
];
plugins = plugins.concat(release ? releasePlugins : debugPlugins);
// ENTRY
const mainEntries = ['./src/index.tsx'];
console.log(chalk.bold('[webpack] Release: ' + release));
const chunkFilename = release ? 'js/[name].[chunkhash].chunk.js' : 'js/[name].chunk.js';
module.exports = {
entry: {
main: mainEntries,
},
performance: {
// The following asset(s) exceed the recommended size limit (250 kB)
hints: false,
},
devServer: {
historyApiFallback: true,
hot: true,
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[chunkhash].entry.js',
chunkFilename: chunkFilename,
assetModuleFilename: 'assets/[name].[hash][ext]',
},
watchOptions: {
ignored: ['**/*.missing.json', '**/*.test.tsx', '**/*.test.ts', '**/tests'],
},
// cheap-module-source-map doesn't seem to work with Uglify
devtool: release ? 'source-map' : 'cheap-module-source-map',
module: {
rules: [
{
test: /\.(ts|tsx|js|jsx)$/,
include: /src/,
use: [
{
loader: require.resolve('ts-loader'),
options: {
//getCustomTransformers: () => ({
// before: !release ? [ReactRefreshTypeScript()] : [],
//}),
// disable type checker - we will use it in fork plugin
transpileOnly: true,
},
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(jpg|png|ico)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name].[hash][ext]',
},
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024,
},
},
},
],
},
resolve: {
// modules: [path.resolve('./src'), path.resolve('./resources'), 'node_modules'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
enforceExtension: false,
/*alias: {
'@/*': path.resolve(__dirname, 'src/'),
},*/
plugins: [
new TsconfigPathsPlugin({
extensions: ['.ts', '.tsx', '.js', '.jsx'],
/*configFile: "./path/to/tsconfig.json" */
}),
],
},
plugins: plugins,
optimization: {
splitChunks: !release
? false
: {
minChunks: 3,
cacheGroups: {
vendors: false,
},
},
minimize: release,
concatenateModules: true,
},
};