const path = require('path') const webpack = require('webpack') const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries") const MiniCssExtractPlugin = require('mini-css-extract-plugin') const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const RemoveStrictPlugin = require('remove-strict-webpack-plugin') const WebpackShellPlugin = require('webpack-shell-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const roots = { 'themes/core': { 'css': { 'challenge-board': 'assets/css/challenge-board.scss', 'fonts': 'assets/css/fonts.scss', 'main': 'assets/css/main.scss', 'core': 'assets/css/core.scss', 'codemirror': 'assets/css/codemirror.scss', }, 'js': { 'pages/main': 'assets/js/pages/main.js', 'pages/setup': 'assets/js/pages/setup.js', 'pages/challenges': 'assets/js/pages/challenges.js', 'pages/scoreboard': 'assets/js/pages/scoreboard.js', 'pages/settings': 'assets/js/pages/settings.js', 'pages/stats': 'assets/js/pages/stats.js', 'pages/notifications': 'assets/js/pages/notifications.js', 'pages/teams/private': 'assets/js/pages/teams/private.js', } }, 'themes/admin': { 'css': { 'admin': 'assets/css/admin.scss', 'challenge-board': 'assets/css/challenge-board.scss', 'codemirror': 'assets/css/codemirror.scss', }, 'js': { 'pages/main': 'assets/js/pages/main.js', 'pages/challenge': 'assets/js/pages/challenge.js', 'pages/challenges': 'assets/js/pages/challenges.js', 'pages/configs': 'assets/js/pages/configs.js', 'pages/notifications': 'assets/js/pages/notifications.js', 'pages/editor': 'assets/js/pages/editor.js', 'pages/pages': 'assets/js/pages/pages.js', 'pages/reset': 'assets/js/pages/reset.js', 'pages/scoreboard': 'assets/js/pages/scoreboard.js', 'pages/statistics': 'assets/js/pages/statistics.js', 'pages/submissions': 'assets/js/pages/submissions.js', 'pages/team': 'assets/js/pages/team.js', 'pages/teams': 'assets/js/pages/teams.js', 'pages/user': 'assets/js/pages/user.js', 'pages/users': 'assets/js/pages/users.js', } }, } function getJSConfig(root, type, entries, mode) { const out = {} const ext = mode == 'development' ? 'dev' : 'min' const chunk_file = `[name].${ext}.chunk.js` for (let key in entries) { out[key] = path.resolve(__dirname, 'CTFd', root, entries[key]) } return { entry: out, mode: mode, output: { path: path.resolve(__dirname, 'CTFd', root, 'static', type), publicPath: '/' + root + '/static/' + type, filename: `[name].${ext}.js`, chunkFilename: chunk_file, }, optimization: { splitChunks: { chunks: 'all', cacheGroups: { echarts: { name: 'echarts', filename: `echarts.bundle.${ext}.js`, test: /echarts/, priority: 1, enforce: true, }, vendor: { name: 'vendor', filename: `vendor.bundle.${ext}.js`, test: /node_modules/, // maxSize: 1024 * 256, enforce: true, }, graphs: { name: 'graphs', filename: `graphs.${ext}.js`, test: /graphs/, priority: 1, reuseExistingChunk: true, }, helpers: { name: 'helpers', filename: `helpers.${ext}.js`, test: /helpers/, priority: 1, reuseExistingChunk: true, }, components: { name: 'components', filename: `components.${ext}.js`, test: /components/, priority: 1, reuseExistingChunk: true, }, default: { filename: `core.${ext}.js`, minChunks: 2, priority: -1, reuseExistingChunk: true, }, }, }, minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, uglifyOptions: { compress: { // Remove console.log in production drop_console: mode === 'production' }, }, }), ], }, module: { rules: [ { test: /\.js$/, use: { loader: 'babel-loader', options: { cacheDirectory: true, presets: [ ['@babel/preset-env', { useBuiltIns: 'entry', modules: 'commonjs' }], ], } } }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { css: ['vue-style-loader', { loader: 'css-loader', }], js: [ 'babel-loader', ], }, cacheBusting: true, }, }, // This rule is magically used to load the