1'use strict';
2
3// Modules
4var webpack = require('webpack');
5var autoprefixer = require('autoprefixer');
6var HtmlWebpackInlineSourcePlugin =
7    require('html-webpack-inline-source-plugin');
8var CSPWebpackPlugin = require('csp-html-webpack-plugin');
9var HtmlWebpackPlugin = require('html-webpack-plugin');
10var CopyWebpackPlugin = require('copy-webpack-plugin');
11var CompressionPlugin = require('compression-webpack-plugin');
12var path = require('path');
13var FilterChunkWebpackPlugin = require('filter-chunk-webpack-plugin');
14var MiniCssExtractPlugin = require('mini-css-extract-plugin');
15
16const isPathInside = require('is-path-inside')
17const pkgDir = require('pkg-dir')
18const coreJsDir = pkgDir.sync(require.resolve('core-js'))
19
20module.exports = (env, options) => {
21  var isProd = options.mode === 'production';
22
23  /**
24   * Config
25   * Reference: http://webpack.github.io/docs/configuration.html
26   * This is the object where all configuration gets set
27   */
28  var config = {};
29
30  /**
31   * Entry
32   * Reference: http://webpack.github.io/docs/configuration.html#entry
33   * Should be an empty object if it's generating a test build
34   * Karma will set this when it's a test build
35   */
36  config.entry = {app: './app/index.js'};
37
38  /**
39   * Output
40   * Reference: http://webpack.github.io/docs/configuration.html#output
41   * Should be an empty object if it's generating a test build
42   * Karma will handle setting it up for you when it's a test build
43   */
44  config.output = {
45    // Absolute output directory
46    path: __dirname + '/dist',
47
48    // Output path from the view of the page
49    // Uses webpack-dev-server in development
50    publicPath: '/',
51
52    // Filename for entry points
53    // Only adds hash in build mode
54    filename: '[name].bundle.js',
55
56    // Filename for non-entry points
57    // Only adds hash in build mode
58    chunkFilename: '[name].bundle.js'
59  };
60
61  /**
62   * Loaders
63   * Reference:
64   * http://webpack.github.io/docs/configuration.html#module-loaders
65   * List: http://webpack.github.io/docs/list-of-loaders.html
66   * This handles most of the magic responsible for converting modules
67   */
68
69  // Initialize module
70  config.module = {
71    rules: [
72      {
73        // JS LOADER
74        // Reference: https://github.com/babel/babel-loader
75        // Transpile .js files using babel-loader
76        // Compiles ES6 and ES7 into ES5 code
77        test: /\.js$/,
78        exclude: (input) => isPathInside(input, coreJsDir),
79        use: {
80          loader: 'babel-loader',
81          options: {
82            presets: [['@babel/preset-env', {useBuiltIns: 'entry', corejs: 3}]]
83          }
84        }
85      },
86      {
87        // ASSET LOADER
88        // Reference: https://github.com/webpack/file-loader
89        // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to
90        // output
91        // Rename the file using the asset hash
92        // Pass along the updated reference to your code
93        // You can add here any file extension you want to get copied
94        // to your output
95        // Excludes .svg files in icons directory
96        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/,
97        exclude: /icons\/.*\.svg$/,
98        loader: 'file-loader',
99        options: {name: '[path][name].[ext]'}
100      },
101      {
102        // INLINE SVG LOADER
103        // Inlines .svg assets in icons directory
104        // needed specifically for icon-provider.js directive
105        test: /icons\/.*\.svg$/,
106        loader: 'svg-inline-loader'
107      },
108      {
109        // HTML LOADER
110        // Reference: https://github.com/webpack/raw-loader
111        // Allow loading html through js
112        test: /\.html$/,
113        loader: 'html-loader'
114      },
115      {
116        test: /\.css$/,
117        use: [MiniCssExtractPlugin.loader, 'css-loader'],
118      },
119      {
120        test: /\.scss$/,
121        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
122      }
123    ]
124  };
125
126  config.plugins = [
127    new HtmlWebpackPlugin({
128      template: './app/index.html',
129      inject: 'body',
130      favicon: './app/assets/images/favicon.ico',
131      minify: {removeComments: true, collapseWhitespace: true},
132
133    }),
134    new CSPWebpackPlugin({
135      'base-uri': '\'self\'',
136      'object-src': '\'none\'',
137      'script-src': ['\'self\''],
138      'style-src': ['\'self\''],
139      'connect-src': ['\'self\'', 'wss:'],
140      // KVM requires image buffers from data: payloads, so allow that in
141      // img-src
142      // https://stackoverflow.com/questions/18447970/content-security-policy-data-not-working-for-base64-images-in-chrome-28
143      'img-src': ['\'self\'', 'data:'],
144    }),
145    new MiniCssExtractPlugin(),
146
147    new FilterChunkWebpackPlugin({
148      patterns: [
149        '*glyphicons-halflings-regular*.ttf',
150        '*glyphicons-halflings-regular*.svg',
151        '*glyphicons-halflings-regular*.eot',
152        '*glyphicons-halflings-regular*.woff2',
153      ]
154    })
155  ];
156
157  // Add build specific plugins
158  if (isProd) {
159    config.plugins.push(new CompressionPlugin({deleteOriginalAssets: true}));
160  }
161
162  /**
163   * Dev server configuration
164   * Reference: http://webpack.github.io/docs/configuration.html#devserver
165   * Reference: http://webpack.github.io/docs/webpack-dev-server.html
166   */
167  config.devServer = {contentBase: './src/public', stats: 'minimal'};
168
169  return config;
170};
171