Project

General

Profile

1
// Helper: root() is defined at the bottom
2
var path = require('path');
3
var webpack = require('webpack');
4

    
5
// Webpack Plugins
6
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
7
var autoprefixer = require('autoprefixer');
8
var HtmlWebpackPlugin = require('html-webpack-plugin');
9
var ExtractTextPlugin = require('extract-text-webpack-plugin');
10
var CopyWebpackPlugin = require('copy-webpack-plugin');
11

    
12
/**
13
 * Env
14
 * Get npm lifecycle event to identify the environment
15
 */
16
var ENV = process.env.npm_lifecycle_event;
17
var isTestWatch = ENV === 'test-watch';
18
var isTest = ENV === 'test' || isTestWatch;
19
var isProd = ENV === 'build';
20

    
21
module.exports = function makeWebpackConfig() {
22
  /**
23
   * Config
24
   * Reference: http://webpack.github.io/docs/configuration.html
25
   * This is the object where all configuration gets set
26
   */
27
  var config = {};
28

    
29
  /**
30
   * Devtool
31
   * Reference: http://webpack.github.io/docs/configuration.html#devtool
32
   * Type of sourcemap to use per build type
33
   */
34
  if (isProd) {
35
    config.devtool = 'source-map';
36
  }
37
  else if (isTest) {
38
    config.devtool = 'inline-source-map';
39
  }
40
  else {
41
    config.devtool = 'eval-source-map';
42
  }
43

    
44
  if (!isTest) {
45
    /**
46
     * Entry
47
     * Reference: http://webpack.github.io/docs/configuration.html#entry
48
     */
49
    config.entry = {
50
      'polyfills': './src/polyfills.ts',
51
      'vendor': './src/vendor.ts',
52
      'app': './src/main.ts' // our angular app
53
    };
54
  }
55

    
56
  /**
57
   * Output
58
   * Reference: http://webpack.github.io/docs/configuration.html#output
59
   */
60
  config.output = isTest ? {} : {
61
    path: root('dist'),
62
    publicPath: isProd ? '/' : 'http://localhost:8080/',
63
    filename: isProd ? 'js/[name].[hash].js' : 'js/[name].js',
64
    chunkFilename: isProd ? '[id].[hash].chunk.js' : '[id].chunk.js'
65
  };
66

    
67
  /**
68
   * Resolve
69
   * Reference: http://webpack.github.io/docs/configuration.html#resolve
70
   */
71
  config.resolve = {
72
    // only discover files that have those extensions
73
    extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html'],
74
  };
75

    
76
  var atlOptions = '';
77
  if (isTest && !isTestWatch) {
78
    // awesome-typescript-loader needs to output inlineSourceMap for code coverage to work with source maps.
79
    atlOptions = 'inlineSourceMap=true&sourceMap=false';
80
  }
81

    
82
  /**
83
   * Loaders
84
   * Reference: http://webpack.github.io/docs/configuration.html#module-loaders
85
   * List: http://webpack.github.io/docs/list-of-loaders.html
86
   * This handles most of the magic responsible for converting modules
87
   */
88
  config.module = {
89
    rules: [
90
      // Support for .ts files.
91
      {
92
        test: /\.ts$/,
93
        loaders: ['awesome-typescript-loader?' + atlOptions, 'angular2-template-loader', '@angularclass/hmr-loader'],
94
        exclude: [isTest ? /\.(e2e)\.ts$/ : /\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
95
      },
96

    
97
      // copy those assets to output
98
      {
99
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
100
        loader: 'file-loader?name=fonts/[name].[hash].[ext]?'
101
      },
102

    
103
      // Support for *.json files.
104
      {test: /\.json$/, loader: 'json-loader'},
105

    
106
      // Support for CSS as raw text
107
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
108
      // all css in src/style will be bundled in an external css file
109
      {
110
        test: /\.css$/,
111
        exclude: root('src', 'app'),
112
        loader: isTest ? 'null-loader' : ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'postcss-loader']})
113
      },
114
      // all css required in src/app files will be merged in js files
115
      {test: /\.css$/, include: root('src', 'app'), loader: 'raw-loader!postcss-loader'},
116

    
117
      // support for .scss files
118
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
119
      // all css in src/style will be bundled in an external css file
120
      {
121
        test: /\.(scss|sass)$/,
122
        exclude: root('src', 'app'),
123
        loader: isTest ? 'null-loader' : ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'postcss-loader', 'sass-loader']})
124
      },
125
      // all css required in src/app files will be merged in js files
126
      {test: /\.(scss|sass)$/, exclude: root('src', 'style'), loader: 'raw-loader!postcss-loader!sass-loader'},
127

    
128
      // support for .html as raw text
129
      // todo: change the loader to something that adds a hash to images
130
      {test: /\.html$/, loader: 'raw-loader',  exclude: root('src', 'public')}
131
    ]
132
  };
133

    
134
  if (isTest && !isTestWatch) {
135
    // instrument only testing sources with Istanbul, covers ts files
136
    config.module.rules.push({
137
      test: /\.ts$/,
138
      enforce: 'post',
139
      include: path.resolve('src'),
140
      loader: 'istanbul-instrumenter-loader',
141
      exclude: [/\.spec\.ts$/, /\.e2e\.ts$/, /node_modules/]
142
    });
143
  }
144

    
145
  if (!isTest || !isTestWatch) {
146
    // tslint support
147
    config.module.rules.push({
148
      test: /\.ts$/,
149
      enforce: 'pre',
150
      loader: 'tslint-loader'
151
    });
152
  }
153

    
154
  /**
155
   * Plugins
156
   * Reference: http://webpack.github.io/docs/configuration.html#plugins
157
   * List: http://webpack.github.io/docs/list-of-plugins.html
158
   */
159
  config.plugins = [
160
    // Define env variables to help with builds
161
    // Reference: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
162
    new webpack.DefinePlugin({
163
      // Environment helpers
164
      'process.env': {
165
        ENV: JSON.stringify(ENV)
166
      }
167
    }),
168

    
169
    // Workaround needed for angular 2 angular/angular#11580
170
    new webpack.ContextReplacementPlugin(
171
      // The (\\|\/) piece accounts for path separators in *nix and Windows
172
      /angular(\\|\/)core(\\|\/)@angular/,
173
      root('./src') // location of your src
174
    ),
175

    
176
    // Tslint configuration for webpack 2
177
    new webpack.LoaderOptionsPlugin({
178
      options: {
179
        /**
180
         * Apply the tslint loader as pre/postLoader
181
         * Reference: https://github.com/wbuchwalter/tslint-loader
182
         */
183
        tslint: {
184
          emitErrors: false,
185
          failOnHint: false
186
        },
187
        /**
188
         * Sass
189
         * Reference: https://github.com/jtangelder/sass-loader
190
         * Transforms .scss files to .css
191
         */
192
        sassLoader: {
193
          //includePaths: [path.resolve(__dirname, "node_modules/foundation-sites/scss")]
194
        },
195
        /**
196
         * PostCSS
197
         * Reference: https://github.com/postcss/autoprefixer-core
198
         * Add vendor prefixes to your css
199
         */
200
        postcss: [
201
          autoprefixer({
202
            browsers: ['last 2 version']
203
          })
204
        ]
205
      }
206
    })
207
  ];
208

    
209
  if (!isTest && !isTestWatch) {
210
    config.plugins.push(
211
      // Generate common chunks if necessary
212
      // Reference: https://webpack.github.io/docs/code-splitting.html
213
      // Reference: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
214
      new CommonsChunkPlugin({
215
        name: ['vendor', 'polyfills']
216
      }),
217

    
218
      // Inject script and link tags into html files
219
      // Reference: https://github.com/ampedandwired/html-webpack-plugin
220
      new HtmlWebpackPlugin({
221
        template: './src/public/index.html',
222
        chunksSortMode: 'dependency'
223
      }),
224

    
225
      // Extract css files
226
      // Reference: https://github.com/webpack/extract-text-webpack-plugin
227
      // Disabled when in test mode or not in build mode
228
      new ExtractTextPlugin({filename: 'css/[name].[hash].css', disable: !isProd})
229
    );
230
  }
231

    
232
  // Add build specific plugins
233
  if (isProd) {
234
    config.plugins.push(
235
      // Reference: http://webpack.github.io/docs/list-of-plugins.html#noerrorsplugin
236
      // Only emit files when there are no errors
237
      new webpack.NoEmitOnErrorsPlugin(),
238

    
239
      // // Reference: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
240
      // // Dedupe modules in the output
241
      // new webpack.optimize.DedupePlugin(),
242

    
243
      // Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
244
      // Minify all javascript, switch loaders to minimizing mode
245
      new webpack.optimize.UglifyJsPlugin({sourceMap: true, mangle: { keep_fnames: true }}),
246

    
247
      // Copy assets from the public folder
248
      // Reference: https://github.com/kevlened/copy-webpack-plugin
249
      new CopyWebpackPlugin([{
250
        from: root('src/public')
251
      }])
252
    );
253
  }
254

    
255
  /**
256
   * Dev server configuration
257
   * Reference: http://webpack.github.io/docs/configuration.html#devserver
258
   * Reference: http://webpack.github.io/docs/webpack-dev-server.html
259
   */
260
  config.devServer = {
261
    contentBase: './src/public',
262
    historyApiFallback: true,
263
    quiet: true,
264
    stats: 'minimal' // none (or false), errors-only, minimal, normal (or true) and verbose
265
  };
266

    
267
  return config;
268
}();
269

    
270
// Helper functions
271
function root(args) {
272
  args = Array.prototype.slice.call(arguments, 0);
273
  return path.join.apply(path, [__dirname].concat(args));
274
}
(10-10/10)