File: //home/arjun/projects/buyercall/config/webpack.config.js
require('babel-polyfill');
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
// Webpack and third party plugins.
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
// Environment detection.
const node_env = process.env.NODE_ENV || 'development';
// Global server name
const SERVER_NAME = process.env.SERVER_NAME || 'localhost:8000';
const URL_SCHEME = process.env.URL_SCHEME || 'http';
/*
Configuration settings
------------------------------------------------------------------------------
*/
// Where is your project located relative to this config?
const context = path.join(__dirname, '..');
// Where are your source assets located?
const rootAssetPath = './buyercall/assets';
const contextRoot = path.join(context, rootAssetPath);
const nodeModulesPath = path.join(context, './node_modules');
// Which human languages do you want to support? (regex)
const languages = /en|es/;
// Where will the files get built to?
// var buildOutputPath = './build/public';
const buildOutputPath = path.join(context, './build/public');
// How should certain asset types be configured?
const assets = {
fonts: {
path: 'fonts',
filename: '[path][name].[hash].[ext]',
},
images: {
path: 'images',
filename: '[path][name].[hash].[ext]',
},
images_theme: {
path: 'images/theme',
filename: '[path][name].[ext]',
},
scripts: {
path: 'scripts',
filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].js',
},
vuescripts: {
path: 'vue/pages',
filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].js',
},
components: {
path: 'components',
filename: '[name].[chunkhash].[ext]',
chunkFilename: '[id].[chunkhash].[ext]',
},
styles: {
path: 'styles',
filename: '[name].[chunkhash].css',
chunkFilename: '[id].[chunkhash].css',
},
};
// Which top level JS and CSS files should get output?
const chunks = {
app_js: [path.join(contextRoot, assets.scripts.path, 'entry.js')],
app_new_js: [
path.join(nodeModulesPath, 'parsleyjs/dist', 'parsley.min.js'),
path.join(nodeModulesPath, 'select2/dist/js', 'select2.min.js'),
path.join(contextRoot, assets.scripts.path, 'jquery.inputLettering.js'),
path.join(contextRoot, assets.scripts.path, 'main.js'),
],
app_css: [path.join(contextRoot, assets.styles.path, 'default.scss')],
vue_dashboard_js: [
path.join(contextRoot, assets.vuescripts.path, 'dashboard.js'),
],
vue_global_js: [path.join(contextRoot, assets.vuescripts.path, 'global.js')],
vue_toast_js: [path.join(contextRoot, assets.vuescripts.path, 'toast.js')],
vue_notification_js: [
path.join(contextRoot, assets.vuescripts.path, 'notifications.js'),
],
vue_partnership_table_js: [
path.join(contextRoot, assets.vuescripts.path, 'partnershipTable.js'),
],
vue_accounts_table_js: [
path.join(contextRoot, assets.vuescripts.path, 'accountsTable.js'),
],
vue_profile_settings_js: [
path.join(contextRoot, assets.vuescripts.path, 'profileSettings.js'),
],
vue_partner_settings_js: [
path.join(contextRoot, assets.vuescripts.path, 'partnershipSettings.js'),
],
vue_worklist_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'worklist.js'),
],
vue_channels_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'channels.js'),
],
vue_channels_new_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'channelsNew.js'),
],
vue_inbox_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'inbox.js'),
],
vue_email_templates_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'emailTemplates.js'),
],
vue_source_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'source.js'),
],
vue_omniwidget_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'omniWidget.js'),
],
vue_workflow_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'workflow.js'),
],
vue_user_management_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'userManagement.js'),
],
vue_leads_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'contactsManagement.js'),
],
vue_creditReport_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'CreditScore.js'),
],
vue_css: [
path.join(
nodeModulesPath,
'vue-multiselect/dist',
'vue-multiselect.css',
),
path.join(
nodeModulesPath,
'vue-toast-notification/dist',
'theme-sugar.css',
),
path.join(
nodeModulesPath,
'vue-draggable-resizable/dist',
'VueDraggableResizable.css',
),
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/vuecomponents.css',
),
],
vue_css_light: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/vue-light.css',
),
],
vue_css_dark: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/vue-dark.css',
),
],
app_css_theme_dark: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'scss/bootstrap-dark.scss',
),
path.join(contextRoot, assets.styles.path, '2021-theme', 'scss/icons.scss'),
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'scss/app-dark.scss',
),
],
app_css_theme_light: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'scss/bootstrap.scss',
),
path.join(contextRoot, assets.styles.path, '2021-theme', 'scss/icons.scss'),
path.join(contextRoot, assets.styles.path, '2021-theme', 'scss/app.scss'),
],
vendor_css_new: [
path.join(nodeModulesPath, 'select2/dist/css', 'select2.min.css'),
],
app_css_custom: [
path.join(contextRoot, assets.styles.path, '2021-theme', 'css/main.css'),
],
vue_css_email_templates: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/email_templates.css',
),
],
vue_css_channels: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/channels.css',
),
],
vue_css_source: [
path.join(contextRoot, assets.styles.path, '2021-theme', 'css/source.css'),
],
vue_css_omniwidget: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/omni_widget.css',
),
],
vue_css_inbox: [
path.join(contextRoot, assets.styles.path, '2021-theme', 'css/inbox.css'),
],
app_css_custom_dark: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/main-dark.css',
),
],
app_css_custom_light: [
path.join(
contextRoot,
assets.styles.path,
'2021-theme',
'css/main-light.css',
),
],
frontend_js: [path.join(contextRoot, assets.scripts.path, 'frontend.js')],
backend_js: [path.join(contextRoot, assets.scripts.path, 'backend.js')],
widgets_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.components.path, 'widgets.js'),
],
widgets_css: [path.join(contextRoot, assets.styles.path, 'widgets.scss')],
outbound_backend_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'outbound_backend_js.js'),
],
inbound_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.components.path, 'inbound/inbound.js'),
],
call_widget_js: [
path.join(contextRoot, assets.components.path, 'widgets/call_widget.js'),
],
agents_dashboard_js: [
path.join(
contextRoot,
assets.components.path,
'agents/agents_dashboard.js',
),
],
leads_dashboard_js: [
path.join(contextRoot, assets.components.path, 'leads/leads_dashboard.js'),
],
sms_dashboard_js: [
path.join(contextRoot, assets.components.path, 'sms/sms_dashboard.js'),
path.join(contextRoot, assets.components.path, 'lead-sms.js'),
],
contacts_dashboard_js: [
path.join(
contextRoot,
assets.components.path,
'contacts/contacts_dashboard.js',
),
path.join(contextRoot, assets.components.path, 'lead-sms.js'),
],
contacts_edit_js: [
path.join(contextRoot, assets.components.path, 'contacts/contacts_edit.js'),
path.join(contextRoot, assets.components.path, 'lead-sms.js'),
],
leads_backend_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'index.js'),
path.join(contextRoot, assets.scripts.path, 'tables.js'),
],
agent_form_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'agent_form.js'),
],
group_form_js: [path.join(contextRoot, assets.scripts.path, 'group_form.js')],
forms_backend_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'forms_backend.js'),
],
forms_backend_edit_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'forms_backend_edit.js'),
],
form_leads_backend_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'form_leads_backend.js'),
],
form_leads_backend_new_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
],
form_leads_backend_edit_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(contextRoot, assets.scripts.path, 'form_leads_backend_edit.js'),
],
partnership_new_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(
contextRoot,
assets.components.path,
'sysadmin/partnership_new.js',
),
],
account_edit_js: [
path.join(contextRoot, assets.scripts.path, 'backend.js'),
path.join(
contextRoot,
assets.components.path,
'partnership/account_edit.js',
),
],
vendor_js_new: [
path.join(nodeModulesPath, 'jquery-2021theme/dist', 'jquery.min.js'),
path.join(
nodeModulesPath,
'bootstrap-latest/dist/js',
'bootstrap.bundle.min.js',
),
path.join(nodeModulesPath, 'metismenu/dist', 'metisMenu.min.js'),
path.join(nodeModulesPath, 'simplebar/dist', 'simplebar.min.js'),
path.join(nodeModulesPath, 'node-waves/dist', 'waves.min.js'),
],
vendor_js: [
'bootstrap',
'moment',
path.join(contextRoot, assets.scripts.path, 'vendor', 'jquery-ui.min.js'),
path.join(contextRoot, assets.scripts.path, 'vendor', 'material.min.js'),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'perfect-scrollbar.jquery.min.js',
),
path.join(contextRoot, assets.scripts.path, 'vendor', 'chartist.min.js'),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jquery.bootstrap-wizard.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'gsdk-bootstrap-wizard.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jquery.select-bootstrap.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'bootstrap-notify.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'bootstrap-colorpicker.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'bootstrap-datetimepicker.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'fullcalendar.min.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jasny-bootstrap.min.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jquery-jvectormap.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jquery.tagsinput.js',
),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'jquery.auto-complete.js',
),
path.join(contextRoot, assets.scripts.path, 'vendor', 'sweetalert2.js'),
path.join(contextRoot, assets.scripts.path, 'vendor', 'nouislider.min.js'),
path.join(
contextRoot,
assets.scripts.path,
'vendor',
'material-dashboard.js',
),
path.join(contextRoot, assets.scripts.path, 'vendor', 'player.min.js'),
],
vendor_css: [
// Bootstrap configuration settings:
// https://gist.github.com/anonymous/ef4593b01915d647ed88
// http://getbootstrap.com/customize/?id=ef4593b01915d647ed88
path.join(
contextRoot,
assets.styles.path,
'vendor',
'bootstrap.3.3.5.min.css',
),
path.join(
contextRoot,
assets.styles.path,
'vendor',
'font-awesome.4.3.0.css',
),
path.join(
contextRoot,
assets.styles.path,
'vendor',
'material-dashboard.scss',
),
path.join(
contextRoot,
assets.styles.path,
'vendor',
'jquery.auto-complete.css',
),
path.join(contextRoot, assets.styles.path, 'vendor', 'progres-bar.css'),
],
contact_lead_js: [
path.join(contextRoot, assets.scripts.path, 'mobile', 'contact_leads.js'),
],
contact_note_js: [
path.join(contextRoot, assets.scripts.path, 'mobile', 'contact_note.js'),
],
contact_detail_js: [
path.join(contextRoot, assets.scripts.path, 'mobile', 'contact_detail.js'),
],
contact_timeline_js: [
path.join(
contextRoot,
assets.scripts.path,
'mobile',
'contact_timeline.js',
),
],
add_contact_js: [
path.join(contextRoot, assets.scripts.path, 'mobile', 'add_contact.js'),
],
voicemail_js: [
path.join(
contextRoot,
assets.scripts.path,
'mobile',
'mediaelement-and-player.min.js',
),
path.join(contextRoot, assets.scripts.path, 'mobile', 'voicemail.js'),
],
mobile_js: [
'popper.js',
'jquery-mask-plugin',
path.join(
contextRoot,
assets.scripts.path,
'mobile',
'bootstrap-datepicker.js',
),
path.join(contextRoot, assets.scripts.path, 'mobile', 'bootstrap.min.js'),
path.join(contextRoot, assets.scripts.path, 'mobile', 'mobile.js'),
],
mobile_css: [
path.join(contextRoot, assets.styles.path, 'mobile', 'datepicker.css'),
path.join(contextRoot, assets.styles.path, 'mobile', 'bootstrap.min.css'),
path.join(
contextRoot,
assets.styles.path,
'mobile',
'mediaelementplayer.css',
),
path.join(contextRoot, assets.styles.path, 'mobile', 'mobile.css'),
],
};
const noParse = /(scripts\/vendor)/;
// const noParse = /(scripts\/vendor)|(styles\/vendor)/;
// Where will assets get served in development mode? This depends on running
// the webpack dev server.
const publicPath = 'http://localhost:2992/';
/*
Do not edit past this line unless you are tinkering with webpack.
------------------------------------------------------------------------------
*/
const optimization = {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
// Additional terser options go here
},
}),
],
};
// Plugins that will load in all environments.
const plugins = [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: assets.styles.filename,
chunkFilename: assets.styles.chunkFilename,
}),
// http://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, languages),
];
// The location of manifest.json to be used by flask-webpack
// See https://github.com/nickjj/manifest-revision-webpack-plugin
const manifestPath = path.join('build', 'manifest.json');
// Preserve manifest between ManifestRevisionPlugin.format calls
const manifest = {};
/*
* Builds manifest.json for use from flask-webpack. See
* https://github.com/nickjj/manifest-revision-webpack-plugin
*/
// Define global replace strings
const definePlugin = new webpack.DefinePlugin({
SERVER_NAME: JSON.stringify(SERVER_NAME),
URL_SCHEME: JSON.stringify(URL_SCHEME),
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
});
const resources = [
{
mode: node_env,
target: 'web',
context: path.join(__dirname, '../'),
entry: chunks,
output: {
path: buildOutputPath,
publicPath: publicPath,
filename: assets.scripts.filename,
chunkFilename: assets.scripts.chunkFilename,
},
externals: {
jquery: 'jQuery',
},
resolve: {
alias: {
// 'vue': '@vue/runtime-dom',
'vue': 'vue/dist/vue.esm-bundler.js',
process: "process/browser"
},
// Allow requiring files without supplying the extension.
extensions: ['.json', '.js', '.vue', '.min.js', '.scss'],
modules: [
path.join(contextRoot, assets.scripts.path, 'vendor'),
'node_modules',
],
},
optimization,
module: {
// noParse: noParse,
rules: [
{
test: /\.js$|jsx/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
{
test: /.vue$/,
loader: 'vue-loader',
options: {
hotReload: true,
},
},
{
test: /\.s?css$/i,
use: [
'style-loader',
'vue-style-loader',
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['autoprefixer'],
},
},
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: [path.join(contextRoot, assets.styles.path)],
},
},
},
],
},
// {
// test: /\.(jpe?g|png|gif|svg([\?]?.*))$/i,
// use: [
// {
// loader: 'file-loader',
// options: {
// context: rootAssetPath,
// name: assets.images.filename,
// limit: 800192, // Convert images < 8kb to base64 strings
// },
// },
// {
// loader: 'image-webpack-loader',
// options: {
// // bypassOnDebug: true,
// disable: true,
// },
// },
// ],
// },
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: 'asset/resource',
generator: {
filename: assets.images.filename
}
},
{
test: /\.(woff([\?]?.*)|woff2([\?]?.*))$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 100000,
},
},
],
},
{
test: /\.(ttf([\?]?.*)|eot([\?]?.*))$/i,
use: [
{
loader: 'file-loader',
options: {
context: rootAssetPath,
name: assets.fonts.filename,
},
},
],
},
{
test: /\.tpl$/,
use: ['underscore-template-loader'],
},
{
test: /\.po$/,
use: ['json-loader', 'po-loader'],
},
],
},
plugins: plugins.concat([
// manifestRevisionPlugin,
new WebpackManifestPlugin({
fileName: path.join('..', 'manifest.json'),
publicPath: '',
seed: {},
useLegacyEmit: true,
filter: (file) => {
return !/\/(fonts|styles|scripts)\//.test(file.path) && /\.(jpe?g|png|gif|svg)([\?]?.*)$/i.test(file.path);
},
generate: (seed, files, entrypoints) => {
const manifest = seed || {};
// Ensure 'files' and 'entrypoints' are defined before using them
if (files && entrypoints) {
files.forEach((file) => {
const chunkName = file.chunk?.names[0] || file.name;
const chunkWithExtension = chunkName;
// manifest[chunkWithExtension] = path.join('/assets/', file.path);
manifest[chunkWithExtension] = file.path
});
// Iterate over entrypoints
Object.keys(entrypoints).forEach((entrypointName) => {
const entrypoint = entrypoints[entrypointName];
// if (entrypoint.assets) {
// entrypoint.assets.forEach((asset) => {
if (!manifest[entrypointName]) {
manifest[entrypointName] = entrypoint[0];
}
//});
//}
});
}
return {
publicPath: publicPath,
assets: manifest,
};
},
}),
definePlugin,
new webpack.ProvidePlugin({
__: 'localize',
_: 'underscore',
html: 'html_utils',
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
]),
devServer: {
port: 2992,
hot: true,
headers: {
'Cache-Control': 'public; max-age=43200',
'Access-Control-Allow-Origin': '*',
},
static: {
directory: path.resolve(__dirname, '../build/public'),
},
host: '0.0.0.0',
},
watchOptions: {
aggregateTimeout: 300,
poll: 1000,
},
//devtool: 'source-map'
},
];
// Externally-loaded call widget script
resources.push({
mode: node_env,
target: 'web',
context: path.join(__dirname, '../'),
entry: {
call_widget_external: [
path.join(contextRoot, assets.components.path, 'widgets/call_widget.js'),
],
vue_widget_comm_js: [
'babel-polyfill',
path.join(contextRoot, assets.vuescripts.path, 'widgetComm.js'),
],
},
output: {
path: buildOutputPath,
publicPath: publicPath,
filename: '[name].js',
chunkFilename: '[id].js',
},
resolve: {
alias: {
// 'vue': '@vue/runtime-dom',
'vue': 'vue/dist/vue.esm-bundler.js',
process: "process/browser"
},
// Allow requiring files without supplying the extension.
extensions: ['.json', '.js', '.vue', '.min.js', '.scss'],
modules: [
path.join(contextRoot, assets.scripts.path, 'vendor'),
'node_modules',
],
},
module: {
// noParse: noParse,
rules: [
{
test: /\.js$|jsx/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['transform-regenerator'],
},
},
],
},
{
test: /.vue$/,
loader: 'vue-loader',
options: {
hotReload: true,
},
},
{
test: /\.s?css$/i,
use: [
'style-loader',
'vue-style-loader',
//'css-loader',
{
loader: 'css-loader',
options: {
esModule: false,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [['autoprefixer']],
},
},
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: [path.join(contextRoot, assets.styles.path)],
},
},
},
],
},
// {
// test: /\.(jpe?g|png|gif|svg([\?]?.*))$/i,
// use: [
// {
// loader: 'file-loader',
// options: {
// context: rootAssetPath,
// name: assets.images.filename,
//
// },
// },
// {
// loader: 'image-webpack-loader',
// options: {
// // bypassOnDebug: true,
// disable: true,
// },
// },
// ],
// },
{
test: /\.(jpe?g|png|gif|svg)$/i,
type: 'asset/resource',
generator: {
filename: assets.images.filename
}
},
{
test: /\.(woff([\?]?.*)|woff2([\?]?.*))$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 100000,
},
},
],
},
{
test: /\.(ttf([\?]?.*)|eot([\?]?.*))$/i,
use: [
{
loader: 'file-loader',
options: {
context: rootAssetPath,
name: assets.fonts.filename,
},
},
],
},
{
test: /\.tpl$/,
use: ['underscore-template-loader'],
},
{
test: /\.po$/,
use: ['json-loader', 'po-loader'],
},
],
},
plugins: [
new VueLoaderPlugin(),
definePlugin,
new webpack.ProvidePlugin({
_: 'underscore',
$: 'jquery',
jQuery: 'jquery',
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
],
});
module.exports = resources;