beavyHQ/beavy

View on GitHub
.infrastructure/webpack/make-webpack-config.js

Summary

Maintainability
C
1 day
Test Coverage
var path = require('path')
var fs = require('fs')
var merge = require('lodash/object/merge')
var transform = require('lodash/object/transform')
var partial = require('lodash/function/partial')
var isBoolean = require('lodash/lang/isBoolean')
var isObject = require('lodash/lang/isObject')
var yaml = require('js-yaml')
var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var ManifestPlugin = require('webpack-manifest-plugin')
var StatsPlugin = require('stats-webpack-plugin')
var loadersByExtension = require('./helpers/loadersByExtension')
var ROOT = path.join(__dirname, '..', '..')
var JS_ROOT = path.join(ROOT, 'beavy', 'jsbeavy')
var BEAVY_ENV = process.env.BEAVY_ENV || 'DEVELOPMENT'

var appConfig = merge({},
    yaml.safeLoad(fs.readFileSync('beavy/config.yml'))[BEAVY_ENV],
    yaml.safeLoad(fs.readFileSync('config.yml'))
)

function deepTransform (prefix, result, value, key) {
  if (isObject(value)) {
    transform(value,
              partial(deepTransform, prefix + '_' + key),
              result)
  }
  if (!isBoolean(value)) {
    value = JSON.stringify(value)
  }
  result[prefix + '_' + key] = value
}

module.exports = function (options) {
  var entry = {
    'main': ['./beavy/jsbeavy/main.jsx']
  }
  var loaders = {
    'jsx': 'babel',
    'js': {
      loader: 'babel',
      include: JS_ROOT
    },
    'json': 'json-loader',
    'coffee': 'coffee-redux-loader',
    'json5': 'json5-loader',
    'txt': 'raw-loader',
    'png|jpg|jpeg|gif|svg': 'url-loader?limit=10000',
    'woff|woff2': 'url-loader?limit=100000',
    'ttf|eot': 'file-loader',
    'wav|mp3': 'file-loader',
    'html': 'html-loader',
    'md|markdown': ['html-loader', 'markdown-loader']
  }
  var cssLoader = options.minimize ? 'css-loader?module' : 'css-loader?module&localIdentName=[path][name]---[local]---[hash:base64:5]'
  var stylesheetLoaders = {
    'css': cssLoader,
  // "less": [cssLoader, "less-loader"],
    'styl': [cssLoader, 'stylus-loader'],
    'scss|sass': [cssLoader, 'sass-loader' +
    // highest priority: __CUSTOM/styles
    '?includePaths[]=' + encodeURIComponent(path.resolve(ROOT, '__CUSTOM', 'styles')) +
    // second: App
    '&includePaths[]=' + encodeURIComponent(path.resolve(ROOT, 'beavy_apps', appConfig.APP, 'frontend', 'styles')) +
    // third: defaults
    '&includePaths[]=' + encodeURIComponent(path.resolve(JS_ROOT, 'styles'))]
  }
  var additionalLoaders = [
    // { test: /some-reg-exp$/, loader: "any-loader" }
  ]
  var alias = { }
  var aliasLoader = { }
  var externals = [ ]
  var modulesDirectories = ['web_modules', 'node_modules']
  var extensions = ['', '.web.js', '.js', '.jsx']
  var root = [path.resolve(ROOT, 'beavy_apps', appConfig.APP, 'frontend'), JS_ROOT]
  var publicPath = options.devServer ? 'http://localhost:2992/assets/' : '/assets/'
  var output = {
    path: path.join(ROOT, 'assets'),
    publicPath: publicPath,
    filename: '[name]' + (options.longTermCaching && !options.prerender ? '-[chunkhash]' : '') + '.js',
    chunkFilename: (options.devServer ? '[id]' : '[name]') + (options.longTermCaching && !options.prerender ? '-[chunkhash]' : '') + '.js',
    sourceMapFilename: 'debugging-[file].map',
    libraryTarget: options.prerender ? 'commonjs2' : undefined,
    pathinfo: options.debug || options.prerender
  }
  var excludeFromStats = [
    /node_modules[\\\/]react(-router)?[\\\/]/
  ]
  var plugins = [
    new webpack.PrefetchPlugin('react'),
    new webpack.PrefetchPlugin('react/lib/ReactComponentBrowserEnvironment'),
    new webpack.DefinePlugin(merge({
      __DEBUG__: !!options.debug,
      __REDUX_DEV_TOOLS__: !!options.redux_dev_tools,
      __DEBUG_NW__: !!options.redux_dev_tools
    },
    transform(appConfig, partial(deepTransform, '__CONFIG_'))
  ))
  ]
  if (options.prerender) {
    plugins.push(new StatsPlugin('stats.prerender.json', {
      chunkModules: true,
      exclude: excludeFromStats
    }))
    aliasLoader['react-proxy$'] = 'react-proxy/unavailable'
    aliasLoader['react-proxy-loader$'] = 'react-proxy-loader/unavailable'
    externals.push(
      /^react(\/.*)?$/,
      /^reflux(\/.*)?$/,
      'superagent',
      'async')
    plugins.push(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }))
  } else {
    plugins.push(new StatsPlugin('stats.json', {
      chunkModules: true,
      exclude: excludeFromStats
    }))
  }
  if (options.commonsChunk) {
    plugins.push(new webpack.optimize.CommonsChunkPlugin('commons', 'commons' + (options.longTermCaching && !options.prerender ? '-[chunkhash]' : '') + '.js'))
  }

  plugins.push(new ManifestPlugin())

  plugins.push(new webpack.ProvidePlugin({
    'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
  }))

  Object.keys(stylesheetLoaders).forEach(function (ext) {
    var stylesheetLoader = stylesheetLoaders[ext]
    if (Array.isArray(stylesheetLoader)) {
      stylesheetLoader = stylesheetLoader.join('!')
    }
    if (options.prerender) {
      stylesheetLoaders[ext] = stylesheetLoader.replace(/^css-loader/, 'css-loader/locals')
    } else if (options.separateStylesheet) {
      stylesheetLoaders[ext] = ExtractTextPlugin.extract('style-loader', stylesheetLoader)
    } else {
      stylesheetLoaders[ext] = 'style-loader!' + stylesheetLoader
    }
  })
  if (options.separateStylesheet && !options.prerender) {
    plugins.push(new ExtractTextPlugin('[name]' + (options.longTermCaching ? '-[contenthash]' : '') + '.css'))
  }
  if (options.minimize && !options.prerender) {
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compressor: {
          warnings: false,
          dead_code: true,
          unused: true,
          unsafe: false,
          global_defs: {
            DEBUG: false,
            __DEBUG__: false,
            __REDUX_DEV_TOOLS__: false,
            __DEBUG_NW__: false
          }
        }
      }),
    // new webpack.optimize.OccurenceOrderPlugin(true),
    new webpack.optimize.DedupePlugin()
    )
  }
  if (options.minimize) {
    plugins.push(
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: JSON.stringify('production')
        }
      }),
      new webpack.NoErrorsPlugin()
    )
  }
  return {
    entry: entry,
    output: output,
    target: options.prerender ? 'node' : 'web',
    module: {
      loaders: [
        { // for prosemirror
          include: /prosemirror/,
          test: /\.jsx?$/,
          loader: 'babel'
        }].concat(loadersByExtension(loaders)).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders)
    },
    devtool: options.devtool,
    debug: options.debug,
    resolveLoader: {
      root: path.join(__dirname, 'node_modules'),
      alias: aliasLoader
    },
    externals: externals,
    resolve: {
      root: root,
      modulesDirectories: modulesDirectories,
      extensions: extensions,
      alias: alias
    },
    plugins: plugins,
    devServer: {
      contentBase: '/assets/',
      color: true,
      publicPath: '/assets/',
      proxy: {'*': 'http://127.0.0.1:5000/'},
      stats: {
        cached: false,
        color: true,
        exclude: excludeFromStats
      }
    },
    watchOptions: options.watchOptions
  }
}