cht8687 / react-hover

React hover --- make hover easy http://cht8687.github.io/react-hover/example/
MIT License
107 stars 25 forks source link

ReactHover elements don't appear in production build? #11

Closed qxh5696 closed 6 years ago

qxh5696 commented 7 years ago

I made use of React-Hover in a small project of mine and when I build a production version of my project, the elements using react-hover don't appear.

Here is the link to my project, feel free to clone, change it, whatever: https://github.com/qxh5696/dummy-react-project

Any help would be appreciated.

cht8687 commented 7 years ago

hm...I checkout that repo and tried to build it and upload here it seems it can't find the bundle js files from the console message...

qhaqq-amplify commented 7 years ago

Hey @cht8687 I'm at work but I can still converse, I was serving a build version locally using the npm package serve.

cht8687 commented 7 years ago

@stevemao do you have any idea of this issue?

stevemao commented 7 years ago

There might be a problem with react-scripts build

dekkofilms commented 7 years ago

I'm having that same issue actually...it's working just fine on localhost but not on production.

dekkofilms commented 7 years ago

Build scripts are fine for me ... no error logging out on the build. When I inspect the element, it is just an empty div where the trigger/hover content should be.

cht8687 commented 7 years ago

@dekkofilms are you using react-scripts like what @qxh5696 did in his project? Could you elaborate more details? 😅

dekkofilms commented 7 years ago

No I'm not using those scripts ... we have our own build file that's running, which is running our webpack config:

import webpack from 'webpack';
import webpackConfig from '../webpack.config.prod';
import colors from 'colors';

console.log("Setting production environment");

process.env.NODE_ENV = 'production';

console.log('Generating minified build for production via Webpack.  This will take a moment...'.blue);

webpack(webpackConfig).run((err, stats) => {
  if (err){
    console.log(err.bold.red);
    return 1;
  }

  const jsonStats = stats.toJson();

  if(jsonStats.hasErrors){
    return jsonStats.errors.map(error => console.log(error.red));
  }

  if(jsonStats.hasWarnings) {
    console.log('Webpack generated the following warnings:'.bold.yellow);
    return jsonStats.warnings.map(warning => console.log(warning.yellow));
  }

  console.log(`Webpack stats:  ${stats}`);

  console.log('Your app has been compiled in production mode and written to /dist.  It\'s ready to roll!'.green);

  return 0;

});

Webpack Config for production:

import webpack from 'webpack';
import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
const ManifestPlugin = require('webpack-manifest-plugin');

export default {
  devtool: 'source-map',
  noInfo: false,
  entry: [
    './src/index'
  ],
  target: 'web',
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {NODE_ENV: '"production"'}
    }),
    // new BundleAnalyzerPlugin(),
    new ManifestPlugin({
      fileName: 'asset-manifest.json'
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    new ExtractTextPlugin('styles.css'),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true,
        drop_console: true
      },
      output: {
        comments: false,
      },
      exclude: [/\.min\.js$/gi]
    }),
    new webpack.optimize.AggressiveMergingPlugin(),
    new CopyWebpackPlugin([
      { from: 'src/robots.txt', to: 'robots.txt' },
      { from: 'src/sitemap.xml', to: 'sitemap.xml' },
      { from: 'src/service-worker.js', to: 'service-worker.js' },
      { from: 'src/manifest.json', to: 'manifest.json' }
    ], {
      copyUnmodified: true
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0
    })
  ],
  module: {
    loaders: [
      {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
      {test: /(\.css)$/, loader: ExtractTextPlugin.extract("css?sourceMap")},
      {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
      {test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000'},
      {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
      {test: /\.(jpe?g|png|gif|svg|webp)$/i, loader: "url?limit=10000"},
      {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
      {
        test: /favicon\.ico$/,
        loader: 'url',
        query: {
          limit: 1,
          name: '[name].[ext]',
        },
      }
    ]
  }
};
cht8687 commented 7 years ago

thanks for this @dekkofilms , I will look into this issue.... meanwhile, if you found any root cause for this issue, don't forget to share with us... 👍

j4mesjung commented 7 years ago

any update on this issue?

j4mesjung commented 7 years ago

@cht8687 after looking into the issue, it might be the production build being uglified.

for (let child of this.props.children) {
      if (child.type) {
        if (child.type.name == 'Trigger') {
          childrenWithProps.push(React.cloneElement(child, {
            setVisibility: this.setVisibility.bind(this),
            getCursorPos: this.getCursorPos.bind(this)
          }));
        } else if (child.type.name == 'Hover') {
          childrenWithProps.push(React.cloneElement(child, {
            styles: hoverComponentStyle
          }));
        }
      }
    }

but in production, the item.type.name is neither Trigger nor Hover.

j4mesjung commented 7 years ago

so I think that was the issue. The children elements name changes in production builds so the conditional will never resolve. I did something really janky as a workaround where i pass a prop called name into the children components and the source code will check child.props.name instead of child.type.name <ReactHover.Trigger name='trigger'>

  for (let child of this.props.children) {
      if (child.type) {
        if (child.props.name == 'trigger') {
          childrenWithProps.push(React.cloneElement(child, {
            setVisibility: this.setVisibility.bind(this),
            getCursorPos: this.getCursorPos.bind(this)
          }));
        } else if (child.props.name == 'hover') {
          childrenWithProps.push(React.cloneElement(child, {
            styles: hoverComponentStyle
          }));
        }
      }
cht8687 commented 7 years ago

@j4mesjung
Thank you for this!!! Good found! 👍 Do you want to summit a PR? 😄 We can add a || check like: if(child.type.name == 'Trigger' || child.props.name == 'trigger') to support those use lower versions.

What do you think? or we can get rid of the child.type.name == 'Trigger' totally.

stevemao commented 7 years ago

I don't know anything about item.type. Could someone link me to any references or docs?

cht8687 commented 7 years ago

Hi @stevemao , check this link:

https://discuss.reactjs.org/t/how-to-determine-what-type-of-component-a-child-is/3951

cht8687 commented 7 years ago

fixed https://github.com/cht8687/react-hover/pull/13

stevemao commented 6 years ago

item.type doesn't look like a public API since i can't find anything on the official docs.

cht8687 commented 6 years ago

@stevemao it's for backwards compatible for those who used older version of this lib.

ghost commented 2 years ago

@cht8687 The website provided is down.

cht8687 commented 2 years ago

@ulnk I can't guarantee a website that is referenced 5 years ago to still running. 😄