///////////////////////////////////////////////////////////// // // 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 ExtractTextPlugin = require('extract-text-webpack-plugin'); const extractStyle = new ExtractTextPlugin({ filename: '[name].css', allChunks: true, }); const envType = PRODUCTION ? 'production': 'development'; const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); // Extract vendor related libraries(node_modules/lib/lib.js) from bundles // specified in `chunks` into vendor.js bundle const vendorChunks = new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', chunks: ['app.bundle', 'sqleditor', 'codemirror', 'debugger_direct'], filename: 'vendor.js', minChunks: function(module) { return webpackShimConfig.isExternal(module); }, }); // Extract pgAdmin common libraries(pgadmin/web/module/filename.js) from bundles // specified in `chunks` into pgadmin_commons.js bundle. // pgLibs holds files that will be moved into this bundle. const pgAdminCommonChunks = new webpack.optimize.CommonsChunkPlugin({ name: 'pgadmin_commons', chunks: ['app.bundle', 'sqleditor', 'codemirror', 'debugger_direct'], filename: 'pgadmin_commons.js', minChunks: function(module) { return webpackShimConfig.isPgAdminLib(module); }, }); // 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', S: 'underscore.string', Backbone: 'backbone', Backgrid: 'backgrid', pgAdmin: 'pgadmin', 'moment': 'moment', 'window.moment':'moment', }); // Minify and omptimize JS/CSS to reduce bundle size. It is used in production const uglifyPlugin = new webpack.optimize.UglifyJsPlugin({ output: {comments: false}, compress: { warnings: false, unused: true, dead_code: true, drop_console: true, }, }); // 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 minimising the `React' production bundle. Bundle only code // requires in production mode. React keeps the code conditional // based on 'NODE_ENV' variable. [used only in production] const definePlugin = new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': JSON.stringify('production'), }, }); // Manages the cache and stores it into 'sources/generated/.cache//' path // where env = dev || prod const hardSourceWebpackPlugin = new HardSourceWebpackPlugin({ cacheDirectory: './.cache/hard-source/' + envType +'/[confighash]', recordsPath: './.cache/hard-source/' + envType +'/[confighash]/records.json', configHash: require('node-object-hash')({sort: false}).hash, environmentHash: { root: process.cwd(), directories: ['node_modules'], files: ['package.json'], }, }); // 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.js', 'codemirror.js'], columns: false, }); 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: extractStyle.extract({ use: [{ loader: 'css-loader', }, { loader: 'sass-loader', // compiles Sass to CSS }, { /* This will @import with below resources to all scss files */ loader: 'sass-resources-loader', options: { resources: [ './pgadmin/static/scss/resources/pgadmin.resources.scss', ], }, }], }), }, { test: /\.css$/, use: extractStyle.extract({ use: [{ 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', '.jsx'], 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/, }, // Define list of Plugins used in Production or development mode // Ref:https://webpack.js.org/concepts/plugins/#components/sidebar/sidebar.jsx plugins: PRODUCTION ? [ extractStyle, vendorChunks, pgAdminCommonChunks, providePlugin, uglifyPlugin, optimizeAssetsPlugin, definePlugin, sourceMapDevToolPlugin, ]: [ extractStyle, vendorChunks, pgAdminCommonChunks, providePlugin, definePlugin, hardSourceWebpackPlugin, sourceMapDevToolPlugin, ], };