Skip to content

Instantly share code, notes, and snippets.

@KeenthemesHub
Created March 17, 2023 03:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KeenthemesHub/1e9198d6cde413797f2285ac8bea6184 to your computer and use it in GitHub Desktop.
Save KeenthemesHub/1e9198d6cde413797f2285ac8bea6184 to your computer and use it in GitHub Desktop.
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
const del = require('del');
const glob = require('glob');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const WebpackMessages = require('webpack-messages');
const ExcludeAssetsPlugin = require('webpack-exclude-assets-plugin');
const MergeIntoSingle = require('webpack-merge-and-include-globally/index');
const RtlCssPlugin = require('rtlcss-webpack-plugin');
// paths
let rootPath = path.resolve(__dirname, '../..');
// arguments/params from the line command
const args = getParameters();
// get theme name
let theme = getTheme();
// get selected demo
let demo = getDemo();
// under theme/demo path
let themePath = '';
if (theme) {
themePath += '/' + theme;
}
if (demo) {
themePath += '/' + demo;
}
// under demo paths
const srcPath = rootPath + '/_keenthemes/src' + themePath;
const assetDistPath = rootPath + '/wwwroot/assets';
const extraPlugins = [];
const exclude = [];
const js = args.indexOf('js') !== -1;
const css = args.indexOf('css') !== -1 || args.indexOf('scss') !== -1;
removeExistingAssets();
additionalSettings();
importExtraPlugins();
function additionalSettings() {
if (args.indexOf('rtl') !== -1) {
// enable rtl for css
extraPlugins.push(new RtlCssPlugin({
filename: '[name].rtl.css',
}));
}
if (!js && css) {
// exclude js files
exclude.push('\.js$');
}
if (js && !css) {
// exclude css files
exclude.push('\.s?css$');
}
if (exclude.length) {
// add plugin for exclude assets (js/css)
extraPlugins.push(new ExcludeAssetsPlugin({
path: exclude,
}));
}
}
function getEntryFiles() {
const entries = {
// 3rd party plugins css/js
'plugins/global/plugins.bundle': ['./webpack/plugins/plugins.js', './webpack/plugins/plugins.scss'],
// Theme css/js
'css/style.bundle': ['./' + path.relative('./', srcPath) + '/sass/style.scss', './' + path.relative('./', srcPath) + '/sass/plugins.scss'],
'js/scripts.bundle': './webpack/scripts' + (demo ? '.' + demo : '') + '.js',
};
// Custom 3rd party plugins
(glob.sync('./webpack/{plugins,js}/custom/**/*.+(js)') || []).forEach(file => {
let loc = file.replace('webpack/', '').replace('./', '');
loc = loc.replace('.js', '.bundle');
entries[loc] = file;
});
// Custom JS files from src folder
(glob.sync(path.relative('./', srcPath) + '/js/custom/**/!(_)*.js') || [])
.filter(f => {
// exclude folder with bundle
return /\/bundle\/.*?\.js/.test(f) === false;
})
.forEach(file => {
entries[file.replace(/.*js\/(.*?)\.js$/ig, 'js/$1')] = './' + file;
});
// Widgets js
entries['js/widgets.bundle'] = (glob.sync(path.relative('./', srcPath) + '/js/widgets/**/!(_)*.js') || []);
return entries;
}
function mainConfig() {
return {
// enabled/disable optimizations
mode: args.indexOf('production') !== -1 ? 'production' : 'development',
// console logs output, https://webpack.js.org/configuration/stats/
stats: 'errors-warnings',
performance: {
// disable warnings hint
hints: false,
},
optimization: {
minimize: args.indexOf('production') !== -1,
// js and css minimizer
minimizer: [new TerserJSPlugin(), new CssMinimizerPlugin()],
},
entry: getEntryFiles(),
output: {
// main output path in assets folder
path: assetDistPath,
// output path based on the entries' filename
filename: '[name].js',
},
resolve: {
alias: {
jquery: path.join(__dirname, 'node_modules/jquery/src/jquery'),
$: path.join(__dirname, 'node_modules/jquery/src/jquery'),
'@': [srcPath],
'handlebars': 'handlebars/dist/handlebars.js',
},
extensions: ['.js', '.scss'],
fallback: {
util: false,
},
},
devtool: 'source-map',
plugins: [
new WebpackMessages({
name: theme,
logger: str => console.log(`>> ${str}`),
}),
// create css file
new MiniCssExtractPlugin({
filename: '[name].css',
}),
new CopyWebpackPlugin({
patterns: copyFolders(),
}),
].concat(extraPlugins),
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
// Prefer `dart-sass`
implementation: require("sass"),
sourceMap: false,
sassOptions: {
includePaths: [
srcPath,
path.resolve(__dirname, 'node_modules'),
],
},
},
},
],
},
{
test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
use: [
{
loader: 'file-loader',
options: {
// prevent name become hash
name: '[name].[ext]',
// move files
outputPath: 'plugins/global/fonts',
// rewrite path in css
publicPath: 'fonts',
esModule: false,
},
},
],
},
{
test: /\.(gif|png|jpe?g)$/,
include: [
path.resolve(__dirname, 'node_modules'),
],
use: [
{
loader: 'file-loader',
options: {
// emitFile: false,
name: '[path][name].[ext]',
publicPath: (url, resourcePath, context) => {
return path.basename(url);
},
outputPath: (url, resourcePath, context) => {
var plugin = url.match(/node_modules\/(.*?)\//i);
if (plugin) {
return `plugins/custom/${plugin[1]}/${path.basename(url)}`;
}
return url;
},
},
},
],
},
{
// for demo8 image in scss
test: /\.(gif|png|jpe?g)$/,
use: [
{
loader: 'url-loader',
options: {
emitFile: false,
name: '[path][name].[ext]',
publicPath: (url, resourcePath, context) => {
return '../';
},
},
},
],
},
],
},
};
}
function copyFolders() {
let options = [
{
// copy media
from: srcPath + '/media',
to: assetDistPath + '/media',
},
{
// copy tinymce skins
from: path.resolve(__dirname, 'node_modules') + '/tinymce/skins',
to: assetDistPath + '/plugins/custom/tinymce/skins',
},
{
// copy tinymce plugins
from: path.resolve(__dirname, 'node_modules') + '/tinymce/plugins',
to: assetDistPath + '/plugins/custom/tinymce/plugins',
}
];
if (fs.existsSync(srcPath + '/media/plugins/jstree')) {
options.push({
// copy jstree image
from: srcPath + '/media/plugins/jstree',
to: assetDistPath + '/plugins/custom/jstree',
force: true
});
}
return options;
}
function getParameters() {
var possibleArgs = [
'js', 'css', 'scss',
'alldemos', 'rtl', 'prod', 'production', 'localhost',
];
for (var i = 0; i <= 25; i++) {
possibleArgs.push('demo' + i);
}
var args = [];
possibleArgs.forEach(function (key) {
if (process.env['npm_config_' + key]) {
args.push(key);
}
});
if ('production' === process.env['NODE_ENV']) {
args.push('production');
}
return args;
}
function importExtraPlugins() {
// Optional: Import datatables.net
extraPlugins.push(new MergeIntoSingle({
files: {
'plugins/custom/datatables/datatables.bundle.js': [
"node_modules/datatables.net/js/jquery.dataTables.js",
"node_modules/datatables.net-bs5/js/dataTables.bootstrap5.js",
"../src/js/vendors/plugins/datatables.init.js",
"node_modules/jszip/dist/jszip.min.js",
"node_modules/pdfmake/build/pdfmake.min.js",
"node_modules/pdfmake/build/vfs_fonts.js",
"node_modules/datatables.net-buttons/js/dataTables.buttons.min.js",
"node_modules/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js",
"node_modules/datatables.net-buttons/js/buttons.colVis.js",
"node_modules/datatables.net-buttons/js/buttons.flash.js",
"node_modules/datatables.net-buttons/js/buttons.html5.js",
"node_modules/datatables.net-buttons/js/buttons.print.js",
"node_modules/datatables.net-colreorder/js/dataTables.colReorder.min.js",
"node_modules/datatables.net-colreorder-bs5/js/colReorder.bootstrap5.js",
"node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.min.js",
"node_modules/datatables.net-fixedcolumns-bs5/js/fixedColumns.bootstrap5.js",
"node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.min.js",
"node_modules/datatables.net-fixedheader-bs5/js/fixedHeader.bootstrap5.js",
"node_modules/datatables.net-responsive/js/dataTables.responsive.min.js",
"node_modules/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js",
"node_modules/datatables.net-rowgroup/js/dataTables.rowGroup.min.js",
"node_modules/datatables.net-rowgroup-bs5/js/rowGroup.bootstrap5.js",
"node_modules/datatables.net-rowreorder/js/dataTables.rowReorder.min.js",
"node_modules/datatables.net-rowreorder-bs5/js/rowReorder.bootstrap5.js",
"node_modules/datatables.net-scroller/js/dataTables.scroller.min.js",
"node_modules/datatables.net-scroller-bs5/js/dataTables.bootstrap5.js",
"node_modules/datatables.net-select/js/dataTables.select.min.js",
"node_modules/datatables.net-select-bs5/js/dataTables.bootstrap5.js",
"node_modules/datatables.net-datetime/dist/dataTables.dateTime.min.js",
],
'plugins/custom/datatables/pdfmake.min.js.map': [
'node_modules/pdfmake/build/pdfmake.min.js.map',
],
'plugins/custom/datatables/datatables.bundle.css': [
"node_modules/datatables.net-bs5/css/dataTables.bootstrap5.css",
"node_modules/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css",
"node_modules/datatables.net-colreorder-bs5/css/colReorder.bootstrap5.min.css",
"node_modules/datatables.net-fixedcolumns-bs5/css/fixedColumns.bootstrap5.min.css",
"node_modules/datatables.net-fixedheader-bs5/css/fixedHeader.bootstrap5.min.css",
"node_modules/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css",
"node_modules/datatables.net-rowreorder-bs5/css/rowReorder.bootstrap5.min.css",
"node_modules/datatables.net-scroller-bs5/css/scroller.bootstrap5.min.css",
"node_modules/datatables.net-select-bs5/css/select.bootstrap5.min.css",
"node_modules/datatables.net-datetime/dist/dataTables.dateTime.min.css",
],
// fullcalendar
'plugins/custom/fullcalendar/fullcalendar.bundle.js': [
'node_modules/fullcalendar/main.js',
'node_modules/fullcalendar/locales-all.min.js',
],
'plugins/custom/fullcalendar/fullcalendar.bundle.css': [
'node_modules/fullcalendar/main.min.css',
],
},
}));
}
function getTheme() {
const excludedKeys = [
'npm_config_cache',
'npm_config_globalconfig',
'npm_config_global_prefix',
'npm_config_init_module',
'npm_config_local_prefix',
'npm_config_metrics_registry',
'npm_config_node_gyp',
'npm_config_noproxy',
'npm_config_prefix',
'npm_config_userconfig',
'npm_config_user_agent',
'npm_config_rtl',
];
const key = Object.keys(process.env)
.filter(element => !element.match(/npm_config_(demo\d+)$/))
.filter(key => !excludedKeys.includes(key))
.find(element => element.match(/npm_config_.*?/));
if (key) {
return key.replace('npm_config_', '');
}
return null;
}
function getDemo() {
const key = Object.keys(process.env).find(element => element.match(/npm_config_(demo\d+)$/));
if (key) {
return key.replace('npm_config_', '');
}
return null;
}
function removeExistingAssets() {
if (typeof args.localhost === 'undefined') {
del(assetDistPath, {force: true});
}
}
module.exports = () => {
return [mainConfig()];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment