1'use strict';
2
3// Modules
4var webpack = require('webpack');
5var autoprefixer = require('autoprefixer');
6var HtmlWebpackPlugin = require('html-webpack-plugin');
7var ExtractTextPlugin = require('extract-text-webpack-plugin');
8var CopyWebpackPlugin = require('copy-webpack-plugin');
9var CompressionPlugin = require('compression-webpack-plugin');
10var AssetsPlugin = require('assets-webpack-plugin');
11var CopyWebpackPlugin = require('copy-webpack-plugin');
12var path = require('path');
13var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
14
15/**
16 * Env
17 * Get npm lifecycle event to identify the environment
18 */
19var ENV = process.env.npm_lifecycle_event;
20var isTest = ENV === 'test' || ENV === 'test-watch';
21var isProd = ENV === 'build';
22
23module.exports = [function makeWebpackConfig() {
24  /**
25   * Config
26   * Reference: http://webpack.github.io/docs/configuration.html
27   * This is the object where all configuration gets set
28   */
29  var config = {};
30
31  /**
32   * Entry
33   * Reference: http://webpack.github.io/docs/configuration.html#entry
34   * Should be an empty object if it's generating a test build
35   * Karma will set this when it's a test build
36   */
37  config.entry = isTest ? void 0 : {
38    app: './app/index.js'
39
40  };
41
42  /**
43   * Output
44   * Reference: http://webpack.github.io/docs/configuration.html#output
45   * Should be an empty object if it's generating a test build
46   * Karma will handle setting it up for you when it's a test build
47   */
48  config.output = isTest ? {} : {
49    // Absolute output directory
50    path: __dirname + '/dist',
51
52    // Output path from the view of the page
53    // Uses webpack-dev-server in development
54    publicPath: '/',
55
56    // Filename for entry points
57    // Only adds hash in build mode
58    filename: isProd ? '[name].[hash].js' : '[name].bundle.js',
59
60    // Filename for non-entry points
61    // Only adds hash in build mode
62    chunkFilename: isProd ? '[name].[hash].js' : '[name].bundle.js'
63  };
64
65  /**
66   * Devtool
67   * Reference: http://webpack.github.io/docs/configuration.html#devtool
68   * Type of sourcemap to use per build type
69   */
70  if (isTest) {
71    https:
72        // unix.stackexchange.com/questions/144208/find-files-without-extension
73        config.devtool = 'inline-source-map';
74  } else if (isProd) {
75    config.devtool = 'source-map';
76  } else {
77    config.devtool = 'eval-source-map';
78  }
79
80  /**
81   * Loaders
82   * Reference:
83   * http://webpack.github.io/docs/configuration.html#module-loaders
84   * List: http://webpack.github.io/docs/list-of-loaders.html
85   * This handles most of the magic responsible for converting modules
86   */
87
88  // Initialize module
89  config.module = {
90    rules: [
91      {
92        // JS LOADER
93        // Reference: https://github.com/babel/babel-loader
94        // Transpile .js files using babel-loader
95        // Compiles ES6 and ES7 into ES5 code
96        test: /\.js$/,
97        use: 'babel-loader',
98        exclude: /node_modules/
99      },
100      {
101        // CSS LOADER
102        // Reference: https://github.com/webpack/css-loader
103        // Allow loading css through js
104        //
105        // Reference: https://github.com/postcss/postcss-loader
106        // Postprocess your css with PostCSS plugins
107        test: /\.css$/,
108        // Reference: https://github.com/webpack/extract-text-webpack-plugin
109        // Extract css files in production builds
110        //
111        // Reference: https://github.com/webpack/style-loader
112        // Use style-loader in development.
113
114        loader: isTest ? 'null-loader' : ExtractTextPlugin.extract({
115          fallback: 'style-loader',
116          use: [
117            {loader: 'css-loader', query: {sourceMap: true}},
118            {loader: 'postcss-loader'}
119          ],
120        })
121      },
122      {
123        // ASSET LOADER
124        // Reference: https://github.com/webpack/file-loader
125        // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to
126        // output
127        // Rename the file using the asset hash
128        // Pass along the updated reference to your code
129        // You can add here any file extension you want to get copied to your
130        // output
131        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/,
132        loader: 'file-loader',
133        options: {
134          name(file) {
135            if (!isProd) {
136              return '[path][name].[ext]';
137            }
138
139            return '[hash].[ext]';
140          }
141        }
142      },
143      {
144        // HTML LOADER
145        // Reference: https://github.com/webpack/raw-loader
146        // Allow loading html through js
147        test: /\.html$/,
148        use: {loader: 'html-loader'}
149      },
150      // JSON LOADER
151      {test: /\.json$/, loader: 'json-loader'}, {
152        test: /\.scss$/,
153        use: [
154          {
155            loader: 'style-loader'  // creates style nodes from JS strings
156          },
157          {
158            loader: 'css-loader'  // translates CSS into CommonJS
159          },
160          {
161            loader: 'sass-loader'  // compiles Sass to CSS
162          }
163        ]
164      }
165    ]
166  };
167
168  // ISTANBUL LOADER
169  // https://github.com/deepsweet/istanbul-instrumenter-loader
170  // Instrument JS files with istanbul-lib-instrument for subsequent code
171  // coverage reporting
172  // Skips node_modules and files that end with .spec.js
173  if (isTest) {
174    config.module.rules.push({
175      enforce: 'pre',
176      test: /\.js$/,
177      exclude: [/node_modules/, /\.spec\.js$/],
178      loader: 'istanbul-instrumenter-loader',
179      query: {esModules: true}
180    });
181  }
182
183  /**
184   * PostCSS
185   * Reference: https://github.com/postcss/autoprefixer-core
186   * Add vendor prefixes to your css
187   */
188  // NOTE: This is now handled in the `postcss.config.js`
189  //       webpack2 has some issues, making the config file necessary
190
191  /**
192   * Plugins
193   * Reference: http://webpack.github.io/docs/configuration.html#plugins
194   * List: http://webpack.github.io/docs/list-of-plugins.html
195   */
196  config.plugins = [new webpack.LoaderOptionsPlugin({
197    test: /\.scss$/i,
198    options: {postcss: {plugins: [autoprefixer]}},
199    debug: !isProd
200  })];
201
202  // Skip rendering index.html in test mode
203  if (!isTest) {
204    // Reference: https://github.com/ampedandwired/html-webpack-plugin
205    // Render index.html
206    config.plugins.push(
207        new HtmlWebpackPlugin({
208          template: './app/index.html',
209          inject: 'body',
210          favicon: './app/assets/images/favicon.ico'
211        }),
212
213        // Reference: https://github.com/webpack/extract-text-webpack-plugin
214        // Extract css files
215        // Disabled when in test mode or not in build mode
216        new ExtractTextPlugin(
217            {filename: 'css/[name].css', disable: !isProd, allChunks: true}));
218  }
219
220  // Add build specific plugins
221  if (isProd) {
222    config.plugins.push(
223        // Reference:
224        // http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
225        // Minify all javascript, switch loaders to minimizing mode
226        new UglifyJsPlugin(),
227
228        // Copy assets from the public folder
229        // Reference: https://github.com/kevlened/copy-webpack-plugin
230        new CopyWebpackPlugin([{from: __dirname + '/app/assets'}]),
231        new CompressionPlugin({deleteOriginalAssets: true}));
232  }
233
234  /**
235   * Dev server configuration
236   * Reference: http://webpack.github.io/docs/configuration.html#devserver
237   * Reference: http://webpack.github.io/docs/webpack-dev-server.html
238   */
239  config.devServer = {contentBase: './src/public', stats: 'minimal'};
240
241  return config;
242}()];
243