webpack-contrib/expose-loader

Problem with react-phoenix, webpack 3

elmarsto opened this issue · 1 comments

I believe this is just the expose-loader-is-silently-broken-under-Webpack-3 issue we've been seeing crop up elsewhere in Issues, but just in case it isn't;

I have a Phoenix/Elixir app that uses a React/ES6 frontend. Currently we're using Brunch and it sucks. I got everything configured for webpack, however, but now there's trouble.

The module react-phoenix, which we depend on to inject react into phoenix .eex templates, works by rendering react components attached to window. In this case, the app name is Spark, so under brunch we attached window.Spark.Foo, where Foo is the component to be rendered on, say, foo.html.eex, and we were off to the races.

With Webpack, though, it appears that I need to attached Spark to window with expose-loader. Why isn't expose-loader working given the webpack.config below?

Our webpack looks like this:

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')


module.exports = (env) => {
  const isDev = !(env && env.prod)
  const devtool = isDev ? 'eval' : 'source-map'

  return {
    devtool,

    context: __dirname,

    entry: {
      app: [
        'babel-polyfill',
        'react-hot-loader/patch',
        'js/spark.js',
        'react-phoenix',
        'stylus/app.styl',
      ],
    },

    output: {
      path: path.resolve(__dirname, '../priv/static'),
      filename: 'js/[name].js',
      publicPath: 'http://localhost:8080/',
    },

    devServer: {
      headers: {
        'Access-Control-Allow-Origin': '*',
      },
    },

    module: {
      rules: [
        {
          test: /\.(jsx?)$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
        },

        {
          test: /\.(gif|png|jpe?g|svg)$/i,
          exclude: /node_modules/,
          loaders: [
            'file-loader?name=images/[name].[ext]',
            {
              loader: 'image-webpack-loader',
              options: {
                query: {
                  mozjpeg: {
                    progressive: true,
                  },
                  gifsicle: {
                    interlaced: true,
                  },
                  optipng: {
                    optimizationLevel: 7,
                  },
                  pngquant: {
                    quality: '65-90',
                    speed: 4,
                  },
                },
              },
            },
          ],
        },
        {
          test: /js\/spark.js$/,
          use: [{
            loader: 'expose-loader',
            options: 'Spark',
          }],
        },
        {
          test: /\.(css|styl)$/,
          exclude: /node_modules/,
          use: isDev ? [
            'style-loader',
            'css-loader',
            'postcss-loader',
            'stylus-loader',
          ] : ExtractTextPlugin.extract({
            fallback: 'style-loader',
            use: ['css-loader', 'postcss-loader', 'stylus-loader'],
          }),
        },
      ],
    },

    resolve: {
      modules: ['node_modules', __dirname],
      extensions: ['.js', '.json', '.jsx', '.css', '.styl'],
    },

    plugins: isDev ? [
      new CopyWebpackPlugin([{
        from: './static',
        to: path.resolve(__dirname, '../priv/static'),
      }]),
    ] : [
      new CopyWebpackPlugin([{
        from: './static',
        to: path.resolve(__dirname, '../priv/static'),
      }]),

      new ExtractTextPlugin({
        filename: 'css/[name].css',
        allChunks: true,
      }),

      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        beautify: false,
        comments: false,
        extractComments: false,
        compress: {
          warnings: false,
          drop_console: true,
        },
        mangle: {
          except: ['$'],
          screw_ie8 : true, // eslint-disable-line
          keep_fnames: true,
        },
      }),
    ],
  }
}

And spark.js looks like:

import page from './registry'
import { isProd } from './util'
import { client } from './apollo'

export default { page, client, isProd } // eslint-disable-line

Fixed in the master