blob: d4130f68d3b4bd1a808910a9de0ceee000747285 [file] [log] [blame]
Ed Tanousbbcf6702017-10-06 13:53:06 -07001'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');
Ed Tanousbbcf6702017-10-06 13:53:06 -070011var path = require('path');
Andrew Geisslerba5e3f32018-05-24 10:58:00 -070012var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
Ed Tanousbbcf6702017-10-06 13:53:06 -070013
14/**
15 * Env
16 * Get npm lifecycle event to identify the environment
17 */
18var ENV = process.env.npm_lifecycle_event;
19var isTest = ENV === 'test' || ENV === 'test-watch';
20var isProd = ENV === 'build';
21
Andrew Geisslerd27bb132018-05-24 11:07:27 -070022module.exports = [function makeWebpackConfig() {
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 = {};
Ed Tanousbbcf6702017-10-06 13:53:06 -070029
Andrew Geisslerd27bb132018-05-24 11:07:27 -070030 /**
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 = isTest ? void 0 : {
37 app: './app/index.js'
Ed Tanousbbcf6702017-10-06 13:53:06 -070038
Andrew Geisslerd27bb132018-05-24 11:07:27 -070039 };
Ed Tanousbbcf6702017-10-06 13:53:06 -070040
Andrew Geisslerd27bb132018-05-24 11:07:27 -070041 /**
42 * Output
43 * Reference: http://webpack.github.io/docs/configuration.html#output
44 * Should be an empty object if it's generating a test build
45 * Karma will handle setting it up for you when it's a test build
46 */
47 config.output = isTest ? {} : {
48 // Absolute output directory
49 path: __dirname + '/dist',
Ed Tanousbbcf6702017-10-06 13:53:06 -070050
Andrew Geisslerd27bb132018-05-24 11:07:27 -070051 // Output path from the view of the page
52 // Uses webpack-dev-server in development
53 publicPath: '/',
Ed Tanousbbcf6702017-10-06 13:53:06 -070054
Andrew Geisslerd27bb132018-05-24 11:07:27 -070055 // Filename for entry points
56 // Only adds hash in build mode
57 filename: isProd ? '[name].[hash].js' : '[name].bundle.js',
Ed Tanousbbcf6702017-10-06 13:53:06 -070058
Andrew Geisslerd27bb132018-05-24 11:07:27 -070059 // Filename for non-entry points
60 // Only adds hash in build mode
61 chunkFilename: isProd ? '[name].[hash].js' : '[name].bundle.js'
62 };
Ed Tanousbbcf6702017-10-06 13:53:06 -070063
Andrew Geisslerd27bb132018-05-24 11:07:27 -070064 /**
65 * Devtool
66 * Reference: http://webpack.github.io/docs/configuration.html#devtool
67 * Type of sourcemap to use per build type
68 */
69 if (isTest) {
70 https:
Andrew Geisslerba5e3f32018-05-24 10:58:00 -070071 // unix.stackexchange.com/questions/144208/find-files-without-extension
72 config.devtool = 'inline-source-map';
Andrew Geisslerd27bb132018-05-24 11:07:27 -070073 } else if (isProd) {
74 config.devtool = 'source-map';
75 } else {
76 config.devtool = 'eval-source-map';
77 }
Ed Tanousbbcf6702017-10-06 13:53:06 -070078
Andrew Geisslerd27bb132018-05-24 11:07:27 -070079 /**
80 * Loaders
81 * Reference:
82 * http://webpack.github.io/docs/configuration.html#module-loaders
83 * List: http://webpack.github.io/docs/list-of-loaders.html
84 * This handles most of the magic responsible for converting modules
85 */
Ed Tanousbbcf6702017-10-06 13:53:06 -070086
Andrew Geisslerd27bb132018-05-24 11:07:27 -070087 // Initialize module
88 config.module = {
89 rules: [
90 {
91 // JS LOADER
92 // Reference: https://github.com/babel/babel-loader
93 // Transpile .js files using babel-loader
94 // Compiles ES6 and ES7 into ES5 code
Andrew Geisslerba5e3f32018-05-24 10:58:00 -070095 test: /\.js$/,
Andrew Geisslerd27bb132018-05-24 11:07:27 -070096 use: 'babel-loader',
97 exclude: /node_modules/
98 },
99 {
100 // CSS LOADER
101 // Reference: https://github.com/webpack/css-loader
102 // Allow loading css through js
103 //
104 // Reference: https://github.com/postcss/postcss-loader
105 // Postprocess your css with PostCSS plugins
106 test: /\.css$/,
107 // Reference: https://github.com/webpack/extract-text-webpack-plugin
108 // Extract css files in production builds
109 //
110 // Reference: https://github.com/webpack/style-loader
111 // Use style-loader in development.
Ed Tanousbbcf6702017-10-06 13:53:06 -0700112
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700113 loader: isTest ? 'null-loader' : ExtractTextPlugin.extract({
114 fallback: 'style-loader',
115 use: [
116 {loader: 'css-loader', query: {sourceMap: true}},
117 {loader: 'postcss-loader'}
118 ],
119 })
120 },
121 {
122 // ASSET LOADER
123 // Reference: https://github.com/webpack/file-loader
124 // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to
125 // output
126 // Rename the file using the asset hash
127 // Pass along the updated reference to your code
128 // You can add here any file extension you want to get copied to your
129 // output
130 test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|ico)$/,
131 loader: 'file-loader',
132 options: {
133 name(file) {
134 if (!isProd) {
135 return '[path][name].[ext]';
136 }
Ed Tanousbbcf6702017-10-06 13:53:06 -0700137
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700138 return '[hash].[ext]';
139 }
Andrew Geisslerba5e3f32018-05-24 10:58:00 -0700140 }
141 },
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700142 {
143 // HTML LOADER
144 // Reference: https://github.com/webpack/raw-loader
145 // Allow loading html through js
146 test: /\.html$/,
147 use: {loader: 'html-loader'}
148 },
149 // JSON LOADER
150 {test: /\.json$/, loader: 'json-loader'}, {
151 test: /\.scss$/,
152 use: [
153 {
154 loader: 'style-loader' // creates style nodes from JS strings
155 },
156 {
157 loader: 'css-loader' // translates CSS into CommonJS
158 },
159 {
160 loader: 'sass-loader' // compiles Sass to CSS
161 }
162 ]
163 }
164 ]
165 };
Ed Tanousbbcf6702017-10-06 13:53:06 -0700166
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700167 // ISTANBUL LOADER
168 // https://github.com/deepsweet/istanbul-instrumenter-loader
169 // Instrument JS files with istanbul-lib-instrument for subsequent code
170 // coverage reporting
171 // Skips node_modules and files that end with .spec.js
172 if (isTest) {
173 config.module.rules.push({
174 enforce: 'pre',
175 test: /\.js$/,
176 exclude: [/node_modules/, /\.spec\.js$/],
177 loader: 'istanbul-instrumenter-loader',
178 query: {esModules: true}
179 });
180 }
181
182 /**
183 * PostCSS
184 * Reference: https://github.com/postcss/autoprefixer-core
185 * Add vendor prefixes to your css
186 */
187 // NOTE: This is now handled in the `postcss.config.js`
188 // webpack2 has some issues, making the config file necessary
189
190 /**
191 * Plugins
192 * Reference: http://webpack.github.io/docs/configuration.html#plugins
193 * List: http://webpack.github.io/docs/list-of-plugins.html
194 */
195 config.plugins = [new webpack.LoaderOptionsPlugin({
196 test: /\.scss$/i,
197 options: {postcss: {plugins: [autoprefixer]}},
198 debug: !isProd
199 })];
200
201 // Skip rendering index.html in test mode
202 if (!isTest) {
203 // Reference: https://github.com/ampedandwired/html-webpack-plugin
204 // Render index.html
205 config.plugins.push(
Andrew Geisslerba5e3f32018-05-24 10:58:00 -0700206 new HtmlWebpackPlugin({
207 template: './app/index.html',
208 inject: 'body',
209 favicon: './app/assets/images/favicon.ico'
210 }),
Ed Tanousbbcf6702017-10-06 13:53:06 -0700211
Andrew Geisslerba5e3f32018-05-24 10:58:00 -0700212 // Reference: https://github.com/webpack/extract-text-webpack-plugin
213 // Extract css files
214 // Disabled when in test mode or not in build mode
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700215 new ExtractTextPlugin(
216 {filename: 'css/[name].css', disable: !isProd, allChunks: true}));
217 }
Ed Tanousbbcf6702017-10-06 13:53:06 -0700218
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700219 // Add build specific plugins
220 if (isProd) {
221 config.plugins.push(
Andrew Geisslerba5e3f32018-05-24 10:58:00 -0700222 // Reference:
223 // http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
224 // Minify all javascript, switch loaders to minimizing mode
Ed Tanous26539862018-08-15 16:16:37 -0700225 new UglifyJsPlugin(),
Ed Tanousbbcf6702017-10-06 13:53:06 -0700226
Andrew Geisslerba5e3f32018-05-24 10:58:00 -0700227 // Copy assets from the public folder
228 // Reference: https://github.com/kevlened/copy-webpack-plugin
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700229 new CopyWebpackPlugin([{from: __dirname + '/app/assets'}]),
230 new CompressionPlugin({deleteOriginalAssets: true}));
231 }
Ed Tanousbbcf6702017-10-06 13:53:06 -0700232
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700233 /**
234 * Dev server configuration
235 * Reference: http://webpack.github.io/docs/configuration.html#devserver
236 * Reference: http://webpack.github.io/docs/webpack-dev-server.html
237 */
238 config.devServer = {contentBase: './src/public', stats: 'minimal'};
Ed Tanousbbcf6702017-10-06 13:53:06 -0700239
Andrew Geisslerd27bb132018-05-24 11:07:27 -0700240 return config;
241}()];