title: Webpack, remove comments from ejected Angular CLI app not working
body: <p>I have an ejected Angular CLI app which produces comments "no matter what" I do to the UglifyJs settings.</p>
  
  <p>I have followed the advice from <a href="https://stackoverflow.com/questions/41939001/unable-to-strip-comments-in-webpack-bundle-js-file">here</a>, <a href="https://github.com/webpack/webpack/issues/1205" rel="nofollow noreferrer">here</a>, and various places, but none of it seems to work.</p>
  
  <p>I'm not sure where in the plugins order I should place UglifyJsPlugin. I've tried at the first position, last position, second position, and simultaneously at every other position.</p>
  
  <p>Are there maybe some settings in the other plugins which interfere?</p>
  
  <p>I run this on Windows with <code>"build:prod": "set NODE_ENV=production&amp;&amp;webpack --define process.env.NODE_ENV=\"'production'\""</code></p>
  
  <pre><code>/* eslint-disable node/no-unpublished-require */
  /* eslint-disable node/no-extraneous-require */
  const path = require('path');
  const ProgressPlugin = require('webpack/lib/ProgressPlugin');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const autoprefixer = require('autoprefixer');
  const postcssUrl = require('postcss-url');
  const cssnano = require('cssnano');
  
  const { NoEmitOnErrorsPlugin } = require('webpack');
  const { GlobCopyWebpackPlugin, BaseHrefWebpackPlugin } = require(
    '@angular/cli/plugins/webpack');
  const { CommonsChunkPlugin, UglifyJsPlugin } = require('webpack').optimize;
  const { AotPlugin } = require('@ngtools/webpack');
  
  const nodeModules = path.join(process.cwd(), 'node_modules');
  const genDirNodeModules = path.join(
    process.cwd(),
    './src',
    '$$_gendir',
    'node_modules');
  const entryPoints = [
    'inline', 'polyfills', 'sw-register', 'scripts', 'styles', 'vendor', 'main'];
  const minimizeCss = false;
  const baseHref = '';
  const deployUrl = '';
  // safe settings based on: https://github.com/ben-eb/cssnano/issues/358#issuecomment-283696193:
  const postcssPlugins = function() {
    // const importantCommentRe =
    //   /@preserve|@license|[@#]\s*source(?:Mapping)?URL|^!/i;
    const minimizeOptions = {
      autoprefixer: false,
      safe: true,
      mergeLonghand: false,
      discardComments: {
        remove: (comment) =&gt; true,
        // !importantCommentRe.test(comment)
      },
    };
    return [
      postcssUrl({
        url: (URL) =&gt; {
          // Only convert root relative URLs, which CSS-Loader won't process
          // into require().
          if (!URL.startsWith('/') || URL.startsWith('//')) {
            return URL;
          }
          if (deployUrl.match(/:\/\//)) {
            // If deployUrl contains a scheme, ignore baseHref use deployUrl
            // as is.
            return `${deployUrl.replace(/\/$/, '')}${URL}`;
          } else if (baseHref.match(/:\/\//)) {
            // If baseHref contains a scheme, include it as is.
            return baseHref.replace(/\/$/, '') +
              `/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
          } else {
            // Join together base-href, deploy-url and the original URL.
            // Also dedupe multiple slashes into single ones.
            return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
          }
        },
      }),
      autoprefixer(),
    ].concat(minimizeCss ? [cssnano(minimizeOptions)] : []);
  };
  
  const isProduction = process.env.NODE_ENV === 'production';
  
  module.exports = {
    'devtool': 'none', // 'source-map',
    'resolve': {
      'extensions': [
        '.ts',
        '.js',
      ],
      'modules': [
        './node_modules',
        './node_modules',
      ],
    },
    'resolveLoader': {
      'modules': [
        './node_modules',
      ],
    },
    'entry': {
      'main': [
        './src\\main.ts',
      ],
      'polyfills': [
        './src\\polyfills.ts',
      ],
      'scripts': [
        'script-loader!./node_modules\\moment\\min\\moment.min.js',
        'script-loader!./node_modules\\pptxgenjs\\dist\\pptxgen.js',
        'script-loader!./node_modules\\pptxgenjs\\dist\\pptxgen.shapes.js',
        'script-loader!./node_modules\\pptxgenjs\\libs\\jszip.min.js',
        'script-loader!./node_modules\\pptxgenjs\\libs\\jquery.min.js',
      ],
      'styles': [
        './src\\styles.scss',
      ],
    },
    'output': {
      'path': path.join(process.cwd(), 'dist'),
      'filename': '[name].bundle.js',
      'chunkFilename': '[id].chunk.js',
    },
    'module': {
      'rules': [
        // {
        //   'enforce': 'pre',
        //   'test': /\.js$/,
        //   'loader': 'source-map-loader',
        //   'exclude': [
        //     /\/node_modules\//,
        //   ],
        // },
        {
          'test': /\.json$/,
          'loader': 'json-loader',
        },
        {
          'test': /\.html$/,
          'loader': 'raw-loader',
        },
        {
          'test': /\.(eot|svg)$/,
          'loader': 'file-loader?name=[name].[hash:20].[ext]',
        },
        {
          'test': /\.(jpg|png|gif|otf|ttf|woff|woff2|cur|ani)$/,
          'loader': 'url-loader?name=[name].[hash:20].[ext]&amp;limit=10000',
        },
        {
          'exclude': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.css$/,
          'use': [
            'exports-loader?module.exports.toString()',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
          ],
        },
        {
          'exclude': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.scss$|\.sass$/,
          'use': [
            'exports-loader?module.exports.toString()',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'sass-loader',
              'options': {
                'sourceMap': false,
                'precision': 8,
                'includePaths': [],
              },
            },
          ],
        },
        {
          'exclude': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.less$/,
          'use': [
            'exports-loader?module.exports.toString()',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'less-loader',
              'options': {
                'sourceMap': false,
              },
            },
          ],
        },
        {
          'exclude': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.styl$/,
          'use': [
            'exports-loader?module.exports.toString()',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'stylus-loader',
              'options': {
                'sourceMap': false,
                'paths': [],
              },
            },
          ],
        },
        {
          'include': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.css$/,
          'use': [
            'style-loader',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
          ],
        },
        {
          'include': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.scss$|\.sass$/,
          'use': [
            'style-loader',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'sass-loader',
              'options': {
                'sourceMap': false,
                'precision': 8,
                'includePaths': [],
              },
            },
          ],
        },
        {
          'include': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.less$/,
          'use': [
            'style-loader',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'less-loader',
              'options': {
                'sourceMap': false,
              },
            },
          ],
        },
        {
          'include': [
            path.join(process.cwd(), 'src\\styles.scss'),
          ],
          'test': /\.styl$/,
          'use': [
            'style-loader',
            {
              'loader': 'css-loader',
              'options': {
                'sourceMap': false,
                'importLoaders': 1,
              },
            },
            {
              'loader': 'postcss-loader',
              'options': {
                'ident': 'postcss',
                'plugins': postcssPlugins,
              },
            },
            {
              'loader': 'stylus-loader',
              'options': {
                'sourceMap': false,
                'paths': [],
              },
            },
          ],
        },
        {
          'test': /\.ts$/,
          'loader': '@ngtools/webpack',
        },
      ],
    },
    'plugins': [
      new NoEmitOnErrorsPlugin(),
      new UglifyJsPlugin({
        comments: false,
        sourceMap: false,
        compress: {
          sequences: true,
          dead_code: true,
          conditionals: true,
          booleans: true,
          unused: true,
          if_return: true,
          join_vars: true,
          drop_console: true,
        },
        // mangle: {
        //   except: ['$super', '$', 'exports', 'require'],
        // },
        output: {
          comments: false,
        },
      }),
      new GlobCopyWebpackPlugin({
        'patterns': [
          'assets',
          'favicon.ico',
        ],
        'globOptions': {
          'cwd': 'c:\\dev\\engage\\js-engage\\src',
          'dot': true,
          'ignore': '**/.gitkeep',
        },
      }),
      new ProgressPlugin(),
      new HtmlWebpackPlugin({
        'template': './src\\index.html',
        'filename': './index.html',
        'hash': false,
        'inject': true,
        'compile': true,
        'favicon': false,
        'minify': false,
        'cache': true,
        'showErrors': true,
        'chunks': 'all',
        'excludeChunks': [],
        'title': 'Webpack App',
        'xhtml': true,
        'chunksSortMode': function sort(left, right) {
          let leftIndex = entryPoints.indexOf(left.names[0]);
          let rightindex = entryPoints.indexOf(right.names[0]);
          if (leftIndex &gt; rightindex) {
            return 1;
          } else if (leftIndex &lt; rightindex) {
            return -1;
          } else {
            return 0;
          }
        },
      }),
      new BaseHrefWebpackPlugin({}),
      new CommonsChunkPlugin({
        'name': 'inline',
        'minChunks': null,
      }),
      new CommonsChunkPlugin({
        'name': 'vendor',
        'minChunks': (module) =&gt; module.resource &amp;&amp;
        (module.resource.startsWith(nodeModules) || module.resource.startsWith(
          genDirNodeModules)),
        'chunks': [
          'main',
        ],
      }),
      new AotPlugin({
        'mainPath': 'main.ts',
        'hostReplacementPaths': {
          'environments\\environment.ts': isProduction
            ? 'environments\\environment.prod.ts'
            : 'environments\\environment.ts',
        },
        'exclude': [],
        'tsConfigPath': 'src\\tsconfig.app.json',
        'skipCodeGeneration': true,
      }),
    ],
    'node': {
      'fs': 'empty',
      'global': true,
      'crypto': 'empty',
      'tls': 'empty',
      'net': 'empty',
      'process': true,
      'module': false,
      'clearImmediate': false,
      'setImmediate': false,
    },
    'devServer': {
      'historyApiFallback': true,
    },
  };
  </code></pre>
  
  <p><em>Update</em>:</p>
  
  <p>Instead of <code>'none'</code>, which is wrong, I <strong>set <code>devtools: false</code></strong>, but it didn't help.</p>
  
  <p>In addition, I tried <a href="https://github.com/yinhaibo01/remove-comments-loader" rel="nofollow noreferrer">remove-comments-loader</a> and <a href="https://github.com/tjenkinson/webpack-comment-remover-loader" rel="nofollow noreferrer">webpack-comment-remover-loader</a>, but neither helped.</p>
  
  <p>Actually I just realized the comments are appearing in <code>main.bundle.js.map</code> — and even if I turned off source maps that file was being kept around. When I manually deleted the preexisting maps and <strong>did a new build with source maps deleted</strong>, they weren't remade, and <strong>no comments were included</strong> in the javascript files.</p>
  
  <p>Tl;dr: User error. Turn off source maps, delete any preexisting sourcemaps, rebuild.</p>