title: Java/Spring-Boot Webapp not Serving Assets from Public Resources Directory
body: <p>I'm working on an AngularJS application that's being served by Spring-Boot. I'm in the process of upgrading our build pipeline to include Webpack. Webpack is bundling all of the source code into a <code>/src/main/resources/static</code> directory, which I'm told SHOULD be served automatically by Spring-Boot. However, when I try to test this out by navigating to <code>http://localhost:8080</code>, the <code>index.html</code> page is being served, but the various JS bundles are not. Below are some of the relevant files to configure this:</p>
  
  <p>webpack.config.js</p>
  
  <pre><code>/*global process, module, __dirname*/
  
  const path = require('path');
  const proxyMiddleware = require('proxy-middleware');
  const url = require('url');
  const webpack = require('webpack');
  const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
  const ExtractTextPlugin = require('extract-text-webpack-plugin');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
  
  const PATHS = {
      app: path.join(__dirname, './src/main/webapp'),
      dist: path.join(__dirname, './src/main/resources/static'),
      test: path.join(__dirname, './src/test/webapp')
  };
  
  const isDevelopment = process.env.NODE_ENV === 'develop';
  const isE2E = process.env.NODE_ENV === 'e2e';
  const isTest = process.env.NODE_ENV === 'test';
  const isProd = process.env.NODE_ENV === 'production';
  
  // Webpack Loaders
  const fontRule = {
      test: /\.(eot|svg|ttf|woff|woff2)$/,
      loader: 'file-loader',
      options: {
          name: '[name].[sha1:hash:base64:32].[ext]'
      }
  };
  
  const htmlRule = {
      test: /\.html$/,
      loader: 'html-loader',
      query: {
          minimize: isProd
      }
  };
  
  const imageRule = {
      test: /\.png$/i,
      loader: 'url-loader',
      options: {
          limit: 8192,
          mimetype: 'image/png'
      }
  };
  
  const javasscriptPreRule = {
      test: /\.js$/,
      exclude: /node_modules/,
      enforce: 'pre',
      loader: 'eslint-loader'
  };
  
  const javascriptRule = {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
  };
  
  const sassRule = {
      test : /\.scss$/,
      use: ExtractTextPlugin.extract({
          use: [ 'css-loader', 'resolve-url-loader', 'sass-loader?sourceMap' ]
      })
  };
  
  const entry = {
      app: (() =&gt; {
          let app = [ path.join(PATHS.app, 'app.js') ];
  
          if (isProd || isE2E) {
              app.push(path.join(PATHS.app, 'app.prod.js'));
          } else {
              app.push(path.join(PATHS.app, 'app.mock.js'));
          }
  
          return app;
      })()
  };
  
  const output = {
      path: PATHS.dist,
      filename: isProd ? '[name].[chunkhash].js' : '[name].js'
  };
  
  const plugins = (() =&gt; {
      let plugins = [
          new webpack.optimize.CommonsChunkPlugin({
              name: 'vendor',
              minChunks(module) {
                  return module.context
                      &amp;&amp; module.context.indexOf('node_modules') !== -1;
              }
          }),
  
          new webpack.optimize.CommonsChunkPlugin({ name: 'manifest' }),
  
          new ExtractTextPlugin(isProd ? 'styles.[contenthash].css' : 'styles.css'),
  
          new HtmlWebpackPlugin({ template: path.join(PATHS.app, 'index.html') }),
  
          new webpack.DefinePlugin({
              'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
          })
      ];
  
      if (isProd) {
          plugins = plugins.concat([
              new webpack.optimize.UglifyJsPlugin({
                  beautify: false,
                  comments: false,
                  compress: {
                      warnings: false
                  }
              }),
  
              new webpack.optimize.OccurrenceOrderPlugin(),
  
              new OptimizeCssAssetsWebpackPlugin({
                  cssProcessorOptions: {
                      discardComments: { removeAll: true }
                  }
              })
          ]);
      } else {
          const server = (() =&gt; {
              let server = {
                  baseDir: PATHS.dist
              };
  
              // Internal testing server configurations...
  
              return server;
          })();
  
          plugins.push(
              new BrowserSyncPlugin({
                  host: 'localhost',
                  port: 3000,
                  server
              })
          )
      }
  
      return plugins;
  })();
  
  function proxy(target) {
      let options = url.parse(target);
      options.route = '/api';
  
      return proxyMiddleware(options);
  }
  
  module.exports = {
      entry,
      output,
      plugins,
      module: {
          rules: [ fontRule, htmlRule, imageRule, javasscriptPreRule, javascriptRule, sassRule ]
      }
  };
  </code></pre>
  
  <p>WebSecurityConfig.java</p>
  
  <pre><code>@Configuration
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements InitializingBean {
  
      @Override
      protected void configure(HttpSecurity httpSecurity) throws Exception {
          httpSecurity
                  // Internal security configurations
                  .and()
                  .authorizeRequests()
                      .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                      .anyRequest().permitAll();
      }
  
  }
  </code></pre>
  
  <p>Here are the static files stored in <code>/src/target/classes/static</code>:</p>
  
  <p><a href="https://i.stack.imgur.com/yohCJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/yohCJ.png" alt="Built files"></a></p>
  
  <p>And here is proof that the JS files aren't showing up when opening the browser:</p>
  
  <p><a href="https://i.stack.imgur.com/e6luo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/e6luo.png" alt="Firefox Output"></a></p>