1'use strict';
2
3// OpenSSL 3 does not support md4, webpack 4 hardcodes md4 in many places
4// https://github.com/webpack/webpack/issues/13572#issuecomment-923736472
5// As the issue suggests we should update to webpack 5, doing so requires a lot
6// of changes. TODO: Remove after updating to webpack v5.54.0+
7const crypto = require('crypto');
8const crypto_orig_createHash = crypto.createHash;
9crypto.createHash = algorithm =>
10    crypto_orig_createHash(algorithm == 'md4' ? 'sha256' : algorithm);
11
12// Modules
13var webpack = require('webpack');
14var autoprefixer = require('autoprefixer');
15var HtmlWebpackInlineSourcePlugin =
16    require('html-webpack-inline-source-plugin');
17var HtmlWebpackPlugin = require('html-webpack-plugin');
18var CopyWebpackPlugin = require('copy-webpack-plugin');
19var CompressionPlugin = require('compression-webpack-plugin');
20var path = require('path');
21var FilterChunkWebpackPlugin = require('filter-chunk-webpack-plugin');
22var MiniCssExtractPlugin = require('mini-css-extract-plugin');
23
24const isPathInside = require('is-path-inside')
25const pkgDir = require('pkg-dir')
26const coreJsDir = pkgDir.sync(require.resolve('core-js'))
27
28module.exports = (env, options) => {
29  var isProd = options.mode === 'production';
30
31  /**
32   * Config
33   * Reference: http://webpack.github.io/docs/configuration.html
34   * This is the object where all configuration gets set
35   */
36  var config = {};
37
38  /**
39   * Entry
40   * Reference: http://webpack.github.io/docs/configuration.html#entry
41   * Should be an empty object if it's generating a test build
42   * Karma will set this when it's a test build
43   */
44  config.entry = {app: './app/index.js'};
45
46  /**
47   * Output
48   * Reference: http://webpack.github.io/docs/configuration.html#output
49   * Should be an empty object if it's generating a test build
50   * Karma will handle setting it up for you when it's a test build
51   */
52  config.output = {
53    // Absolute output directory
54    path: __dirname + '/dist',
55
56    // Output path from the view of the page
57    // Uses webpack-dev-server in development
58    publicPath: '/',
59
60    // Filename for entry points
61    // Only adds hash in build mode
62    filename: '[name].bundle.js',
63
64    // Filename for non-entry points
65    // Only adds hash in build mode
66    chunkFilename: '[name].bundle.js'
67  };
68
69  /**
70   * Loaders
71   * Reference:
72   * http://webpack.github.io/docs/configuration.html#module-loaders
73   * List: http://webpack.github.io/docs/list-of-loaders.html
74   * This handles most of the magic responsible for converting modules
75   */
76
77  // Initialize module
78  config.module = {
79    rules: [
80      {
81        // JS LOADER
82        // Reference: https://github.com/babel/babel-loader
83        // Transpile .js files using babel-loader
84        // Compiles ES6 and ES7 into ES5 code
85        test: /\.js$/,
86        exclude: (input) => isPathInside(input, coreJsDir),
87        use: {
88          loader: 'babel-loader',
89          options: {
90            presets: [['@babel/preset-env', {useBuiltIns: 'entry', corejs: 3}]]
91          }
92        }
93      },
94      {
95        // ASSET LOADER
96        // Reference: https://github.com/webpack/file-loader
97        // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to
98        // output
99        // Rename the file using the asset hash
100        // Pass along the updated reference to your code
101        // You can add here any file extension you want to get copied
102        // to your output
103        // Excludes .svg files in icons directory
104        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/,
105        exclude: /icons\/.*\.svg$/,
106        loader: 'file-loader',
107        options: {name: '[path][name].[ext]'}
108      },
109      {
110        // INLINE SVG LOADER
111        // Inlines .svg assets in icons directory
112        // needed specifically for icon-provider.js directive
113        test: /icons\/.*\.svg$/,
114        loader: 'svg-inline-loader'
115      },
116      {
117        // HTML LOADER
118        // Reference: https://github.com/webpack/raw-loader
119        // Allow loading html through js
120        test: /\.html$/,
121        loader: 'html-loader'
122      },
123      {
124        test: /\.css$/,
125        use: [MiniCssExtractPlugin.loader, 'css-loader'],
126      },
127      {
128        test: /\.scss$/,
129        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
130      }
131    ]
132  };
133
134  config.plugins = [
135    new HtmlWebpackPlugin({
136      template: './app/index.html',
137      inject: 'body',
138      favicon: './app/assets/images/favicon.ico',
139      minify: {removeComments: true, collapseWhitespace: true},
140
141    }),
142    new MiniCssExtractPlugin(),
143
144    new FilterChunkWebpackPlugin({
145      patterns: [
146        '*glyphicons-halflings-regular*.ttf',
147        '*glyphicons-halflings-regular*.svg',
148        '*glyphicons-halflings-regular*.eot',
149        '*glyphicons-halflings-regular*.woff2',
150      ]
151    })
152  ];
153
154  // Comment in to see per-module js sizes.  This is useful in debugging "why is
155  // my binary so big"
156  /*
157  config.optimization = {
158    runtimeChunk: 'single',
159    splitChunks: {
160      chunks: 'all',
161      maxInitialRequests: Infinity,
162      minSize: 0,
163      cacheGroups: {
164        vendor: {
165          test: /[\\/]node_modules[\\/]/,
166          name(module) {
167            // get the name. E.g. node_modules/packageName/not/this/part.js
168            // or node_modules/packageName
169            const packageName =
170  module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
171
172            // npm package names are URL-safe, but some servers don't like @
173  symbols return `${packageName.replace('@', '')}`;
174          },
175        },
176      },
177    },
178  };
179  */
180
181  // Add build specific plugins
182  if (isProd) {
183    config.plugins.push(new CompressionPlugin({deleteOriginalAssets: true}));
184  }
185
186  /**
187   * Dev server configuration
188   * Reference: http://webpack.github.io/docs/configuration.html#devserver
189   * Reference: http://webpack.github.io/docs/webpack-dev-server.html
190   */
191  config.devServer = {contentBase: './src/public', stats: 'minimal'};
192
193  return config;
194};
195