///////////////////////////////////////////////////////////// // // pgAdmin 4 - PostgreSQL Tools // // Copyright (C) 2013 - 2019, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////// /* eslint-env node */ // Import file, libraries and plugins const path = require('path'); const webpack = require('webpack'); const fs = require('fs'); const sourceDir = __dirname + '/pgadmin/static'; // webpack.shim.js contains path references for resolve > alias configuration // and other util function used in CommonsChunksPlugin. const webpackShimConfig = require('./webpack.shim'); const PRODUCTION = process.env.NODE_ENV === 'production'; const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const extractStyle = new MiniCssExtractPlugin({ filename: '[name].css', allChunks: true, }); const WebpackRequireFromPlugin = require('webpack-require-from'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const envType = PRODUCTION ? 'production': 'development'; const devToolVal = PRODUCTION ? false : 'eval'; const analyzerMode = process.env.ANALYZE=='true' ? 'static' : 'disabled'; // Expose libraries in app context so they need not to // require('libname') when used in a module const providePlugin = new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', _: 'underscore', Backbone: 'backbone', Backgrid: 'backgrid', pgAdmin: 'pgadmin', 'moment': 'moment', 'window.moment':'moment', }); // Optimize CSS Assets by removing comments while bundling const optimizeAssetsPlugin = new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), cssProcessorOptions: { discardComments: { removeAll: true, }, }, canPrint: true, }); // Helps in debugging each single file, it extracts the module files // from bundle so that they are accessible by search in Chrome's sources panel. // Reference: https://webpack.js.org/plugins/source-map-dev-tool-plugin/#components/sidebar/sidebar.jsx const sourceMapDevToolPlugin = new webpack.SourceMapDevToolPlugin({ filename: '[name].js.map', exclude: /(vendor|codemirror|slickgrid|pgadmin\.js|style\.js|popper)/, columns: false, }); // Supress errors while compiling as the getChunkURL method will be available // on runtime. window.getChunkURL is defined in base.html const webpackRequireFrom = new WebpackRequireFromPlugin({ methodName: 'getChunkURL', supressErrors: true, }); // can be enabled using bundle:analyze const bundleAnalyzer = new BundleAnalyzerPlugin({ analyzerMode: analyzerMode, reportFilename: 'analyze_report.html', }); function cssToBeSkiped(curr_path) { /** Skip all templates **/ if(curr_path.indexOf('template') > -1) { return true; } for(let i=0; i< webpackShimConfig.css_bundle_skip.length; i++) { if(path.join(__dirname, webpackShimConfig.css_bundle_skip[i]) === curr_path){ return true; } } return false; } /* Get all the style files recursively and store in array to * give input to webpack. */ function pushModulesCss(curr_path, pgadminStyles) { /** Skip Directories */ if(cssToBeSkiped(curr_path)) { return; } fs.readdirSync(curr_path).map(function(curr_file) { /** Skip Files */ if(cssToBeSkiped(path.join(curr_path, curr_file))) { return; } let stats = fs.statSync(path.join(curr_path, curr_file)); /* if directory, dig further */ if(stats.isDirectory()) { pushModulesCss(path.join(curr_path, curr_file), pgadminStyles); } else if(stats.isFile() && (curr_file.endsWith('.scss') || curr_file.endsWith('.css'))) { pgadminStyles.push(path.join(curr_path, curr_file)); } }); } let pgadminStyles = []; /* Include what is given in shim config */ for(let i=0; iwindow', }, }, { test: require.resolve('./node_modules/acitree/js/jquery.aciPlugin.min'), use: { loader: 'imports-loader?this=>window', }, }, { test: require.resolve('./pgadmin/static/bundle/browser'), use: { loader: 'imports-loader?' + 'pgadmin.about' + ',pgadmin.preferences' + ',pgadmin.file_manager' + ',pgadmin.settings' + ',pgadmin.tools.backup' + ',pgadmin.tools.restore' + ',pgadmin.tools.grant_wizard' + ',pgadmin.tools.maintenance' + ',pgadmin.tools.import_export' + ',pgadmin.tools.debugger.controller' + ',pgadmin.tools.debugger.direct' + ',pgadmin.node.pga_job', }, }, { test: require.resolve('snapsvg'), use: { loader: 'imports-loader?this=>window,fix=>module.exports=0', }, }, { test: /\.(jpe?g|png|gif|svg)$/i, loaders: [{ loader: 'url-loader', options: { emitFile: true, name: 'img/[name].[ext]', limit: 4096, }, }, { loader: 'image-webpack-loader', query: { bypassOnDebug: true, mozjpeg: { progressive: true, }, gifsicle: { interlaced: false, }, optipng: { optimizationLevel: 7, }, pngquant: { quality: '75-90', speed: 3, }, }, }], exclude: /vendor/, }, { test: /\.(eot|svg|ttf|woff|woff2)$/, loaders: [{ loader: 'file-loader', options: { name: 'fonts/[name].[ext]', emitFile: true, }, }], include: [ /node_modules/, path.join(sourceDir, '/css/'), path.join(sourceDir, '/scss/'), path.join(sourceDir, '/fonts/'), ], exclude: /vendor/, }, { test: /\.scss$/, use: [ {loader: MiniCssExtractPlugin.loader}, {loader: 'css-loader'}, {loader: 'sass-loader'}, { loader: 'sass-resources-loader', options: { resources: [ './pgadmin/static/scss/resources/pgadmin.resources.scss', ], }, }, ], }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }], // Prevent module from parsing through webpack, helps in reducing build time noParse: [/moment.js/], }, resolve: { alias: webpackShimConfig.resolveAlias, modules: ['node_modules', '.'], extensions: ['.js'], unsafeCache: true, }, // Watch mode Configuration: After initial build, webpack will watch for // changes in files and compiles only files which are changed, // if watch is set to True // Reference: https://webpack.js.org/configuration/watch/#components/sidebar/sidebar.jsx watchOptions: { aggregateTimeout: 300, poll: 1000, ignored: /node_modules/, }, // Webpack 4: uglifyPlugin moved from plugins to optimization optimization: { minimizer: [ new UglifyJsPlugin({ parallel: true, cache: true, uglifyOptions: { compress: true, extractComments: true, output: { comments: false, }, }, }), ], splitChunks: { cacheGroups: { slickgrid: { name: 'slickgrid', filename: 'slickgrid.js', chunks: 'all', reuseExistingChunk: true, priority: 9, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.matchModules(module, 'slickgrid'); }, }, codemirror: { name: 'codemirror', filename: 'codemirror.js', chunks: 'all', reuseExistingChunk: true, priority: 8, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.matchModules(module, 'codemirror'); }, }, vendor_main: { name: 'vendor_main', filename: 'vendor.main.js', chunks: 'all', reuseExistingChunk: true, priority: 7, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.matchModules(module, ['wcdocker', 'backbone', 'jquery', 'bootstrap', 'popper']); }, }, vendor_others: { name: 'vendor_others', filename: 'vendor.others.js', chunks: 'all', reuseExistingChunk: true, priority: 6, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.isExternal(module); }, }, secondary: { name: 'pgadmin_commons', filename: 'pgadmin_commons.js', chunks: 'all', priority: 5, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.isPgAdminLib(module); }, }, browser_nodes: { name: 'browser_nodes', filename: 'browser_nodes.js', chunks: 'all', priority: 4, minChunks: 2, enforce: true, test(module) { return webpackShimConfig.isBrowserNode(module); }, }, }, }, }, // Define list of Plugins used in Production or development mode // Ref:https://webpack.js.org/concepts/plugins/#components/sidebar/sidebar.jsx plugins: PRODUCTION ? [ extractStyle, providePlugin, optimizeAssetsPlugin, sourceMapDevToolPlugin, webpackRequireFrom, bundleAnalyzer, ]: [ extractStyle, providePlugin, sourceMapDevToolPlugin, webpackRequireFrom, ], };