renuo/ngx-renuo-upload

View on GitHub
webpack.config.js

Summary

Maintainability
C
1 day
Test Coverage
// Helper: root() is defined at the bottom
var path = require('path');
var webpack = require('webpack');

// Webpack Plugins
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
var autoprefixer = require('autoprefixer');
var ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var DashboardPlugin = require('webpack-dashboard/plugin');
var WebpackShellPlugin = require('webpack-shell-plugin');
var ngcWebpack = require('ngc-webpack');

/**
 * Env
 * Get npm lifecycle event to identify the environment
 */
var npm_lifecycle_event = process.env.npm_lifecycle_event;
var isTestWatch = npm_lifecycle_event === 'test-watch';
var isTest = npm_lifecycle_event === 'test' || isTestWatch;
var isProd = npm_lifecycle_event === 'build';

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

  /**
   * Devtool
   * Reference: http://webpack.github.io/docs/configuration.html#devtool
   * Type of sourcemap to use per build type
   */
  if (isProd) {
    config.devtool = 'source-map';
  } else {
    config.devtool = 'eval-source-map';
  }

  /**
   * Entry
   * Reference: http://webpack.github.io/docs/configuration.html#entry
   */
  config.entry = isTest ? {'app': './src/main.ts'} : {
    'polyfills': './src/polyfills.ts',
    'vendor': './src/vendor.ts',
    'app': isProd ? './src/main.aot.ts' : './src/main.ts'
  };

  /**
   * Output
   * Reference: http://webpack.github.io/docs/configuration.html#output
   */
  config.output = isTest ? {} : {
    path: root('dist'),
    publicPath: isProd ? '/' : 'http://ngx-renuo-upload.dev:3000/',
    filename: isProd ? 'js/[name].[hash].js' : 'js/[name].js',
    sourceMapFilename: isProd ? 'js/[name].[hash].js.map' : 'js/[name].js.map',
    chunkFilename: isProd ? '[id].[hash].chunk.js' : '[id].chunk.js'
  };

  /**
   * Resolve
   * Reference: http://webpack.github.io/docs/configuration.html#resolve
   */
  config.resolve = {
    modules: [root(), "node_modules"],
    // only discover files that have those extensions
    extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html'],
    alias: {
      'app': 'src/app',
      'common': 'src/common'
    }
  };

  /**
   * Loaders
   * Reference: http://webpack.github.io/docs/configuration.html#module-loaders
   * List: http://webpack.github.io/docs/list-of-loaders.html
   * This handles most of the magic responsible for converting modules
   */
  config.module = {
    rules: [
      // Support for .ts files.
      {
        test: /\.ts$/,
        use: [
          {
            loader: "awesome-typescript-loader",
            options: {
              useCache: true,
              configFileName: isTest ? 'tsconfig.test.json' : isProd? 'tsconfig.aot.json' : 'tsconfig.json'
            }
          },
          {
            loader: "angular2-template-loader"
          }
        ],
        exclude: [isTest ? /\.(e2e)\.ts$/ : /\.(spec|e2e)\.ts$/]
      },

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

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

      // support for .scss files
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
      // all css in src/style will be bundled in an external css file
      {
        test: /\.scss$/,
        exclude: root('src', 'app'),
        loader: isTest ? 'null-loader' : ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader?sourceMap', 'postcss-loader', 'sass-loader']
        })
      },
      // all css required in src/app files will be merged in js files
      {test: /\.scss$/, exclude: root('src', 'style'), use: ['raw-loader', 'postcss-loader', 'sass-loader']},

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

  if (isTest) {
    // instrument only testing sources with Istanbul, covers ts files
    config.module.rules.push({
      test: /\.ts$/,
      enforce: 'post',
      include: path.resolve('src'),
      loader: 'istanbul-instrumenter-loader',
      exclude: [/\.spec\.ts$/, /\.mock\.ts$/, /index\.ts$/, /\.e2e\.ts$/, /node_modules/]
    });
  }

  /**
   * Apply the tslint loader as pre/postLoader
   * Reference: https://github.com/wbuchwalter/tslint-loader
   */
  if (!isTest) {
    config.module.rules.push({
      test: /\.ts$/,
      enforce: 'pre',
      loader: "tslint-loader",
      options: {
        emitErrors: false,
        failOnHint: false
      }
    });
  }

  /**
   * Plugins
   * Reference: http://webpack.github.io/docs/configuration.html#plugins
   * List: http://webpack.github.io/docs/list-of-plugins.html
   */
  config.plugins = [
    new WebpackShellPlugin({onBuildStart: ['bin/generate-i18n']}),

    // Define env variables to help with builds
    // Reference: https://webpack.github.io/docs/listofplugins.html#defineplugin
    new webpack.DefinePlugin({
      // Environment helpers
      'process.env': {
        // TODO: We need to rename it, so there is no confusion between ENV (env vars) and ENV (development, test, production).
        'ENV': JSON.stringify(npm_lifecycle_event),
        'RENUO_UPLOAD_SIGNING_URL': JSON.stringify(process.env.RENUO_UPLOAD_SIGNING_URL),
        'RENUO_UPLOAD_API_KEY': JSON.stringify(process.env.RENUO_UPLOAD_API_KEY)
      }
    }),

    // add debug messages and keep compatibility with old loaders
    new webpack.LoaderOptionsPlugin({
      debug: !isProd || !isTest,
      minimize: isProd,
      options: {
        context: __dirname
      }
    })
  ];

  if (!isTest && !isProd) {
    config.plugins.push(new DashboardPlugin());
  }

  if (!isTest) {
    config.plugins.push(
      // Generate common chunks if necessary
      // Reference: https://webpack.github.io/docs/code-splitting.html
      // Reference: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
      new CommonsChunkPlugin({
        name: ['vendor', 'polyfills']
      }),

      // Inject script and link tags into html files
      // Reference: https://github.com/ampedandwired/html-webpack-plugin
      new HtmlWebpackPlugin({
        template: './src/public/index.html',
        chunksSortMode: 'dependency',
        metadata: {
          GOOGLE_ANALYTICS_ID: process.env.GOOGLE_ANALYTICS_ID,
          HOTJAR_ID: process.env.HOTJAR_ID
        }
      }),

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

  config.plugins.push(new ContextReplacementPlugin(
    // The (\\|\/) piece accounts for path separators in *nix and Windows
    /angular(\\|\/)core(\\|\/)@angular/,
    root('src'))
  );

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

      // Copy assets from the public folder
      // Reference: https://github.com/kevlened/copy-webpack-plugin
      new CopyWebpackPlugin([{
        from: root('src/public')
      }]),

      new ngcWebpack.NgcWebpackPlugin({
        disabled: false,
        tsConfig: root('tsconfig.aot.json')
      }),

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

  /**
   * Dev server configuration
   * Reference: http://webpack.github.io/docs/configuration.html#devserver
   * Reference: http://webpack.github.io/docs/webpack-dev-server.html
   */
  config.devServer = {
    contentBase: './src/public',
    historyApiFallback: true,
    quiet: true,
    disableHostCheck: true,
    stats: 'minimal' // none (or false), errors-only, minimal, normal (or true) and verbose
  };

  return config;
}();

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