preactjs / preact-compat

ATTENTION: The React compatibility layer for Preact has moved to the main preact repo.
http://npm.im/preact-compat
MIT License
949 stars 148 forks source link

React.Children.only doesn't return props in production mode. [Test Repo Included] #479

Closed ajm113 closed 6 years ago

ajm113 commented 6 years ago

Hi, not sure if this is an issue with preact-compat, or I missed a critical detail somewhere, but my assumption is I could use React API hand to hand with Preact and everything would be smooth as butter. However, when trying to use react-grid-layout it appears when it attempts to call React.Children.only it returns a object which is fine, but for some reason, instead of keeping the .props attribute it renames it to .attributes in the response.

let child = React.Children.only(this.props.children);

screenshot from 2018-06-21 08-27-58

What strikes me as very odd is that it ONLY happens in production builds. Debug builds give me the proper VNode, with .props attached to the object and everything is fine. For whatever reason Webpack4 or preact-compat is removing a key element here in production builds.

My resource files:

Webpack Config

//...
module.exports = {
    entry: {
        app: [
            'client/index.js',
            'client/style.scss'
        ]
    },
    context: APP_DIR,
    output: {
        path: BUILD_DIR,
        filename: isProduction ? '[name]-[hash].js' : '[name].js',
        publicPath: '/assets/'
    },
    mode: isProduction ? 'production' : 'development',
    devtool: isProduction ? 'source-map' : 'cheap-module-eval-source-map',
    module : {
        rules : [
            {
                test:  /\.jsx?$/,
                exclude: APP_DIR,
                enforce: 'pre',
                use: 'source-map-loader'
            },
            {
                test :   /\.jsx?$/,
                exclude: /node_modules/,
                use : 'babel-loader'
            },
            {
                test:  /\.(scss|css)$/,
                use: [].concat(isProduction ? [] : ['css-hot-loader'] )
                .concat(ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                modules: false,
                                sourceMap: !isProduction,
                                minimize: true
                            }
                        },
                        {
                            loader: `postcss-loader`,
                            options: {
                                sourceMap: !isProduction,
                                plugins: () => {
                                    autoprefixer({ browsers: [ 'last 4 versions' ] });
                                }
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: { sourceMap: !isProduction }
                        }
                    ]
                }))
            }
        ]
    },

    resolve: {
        extensions: ['.js', '.jsx', '.scss'],
        modules: [
            APP_DIR,
            path.resolve(__dirname, "node_modules"),
            'node_modules'
        ],
        alias: {
            'react': 'preact-compat',
            'react-dom': 'preact-compat',
            components: path.join(APP_DIR, 'client', 'components'),
            style: path.join(APP_DIR, 'client', 'style'),
            utils: path.join(APP_DIR, 'client', 'utils'),
        }
    },
    plugins: [
        new WebpackNotifierPlugin({alwaysNotify: true}),
        new CleanWebpackPlugin([BUILD_DIR], {watch: true}),
        new webpack.DefinePlugin({
              'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
        }),
        new ExtractTextPlugin({
            filename: isProduction ? '[name]-[hash].css' : '[name].css',
            allChunks: true
        }),
        new ManifestPlugin({
            writeToFileEmit: true // Needed for PHP and Webpack Proxy
        })
    ],
    stats: { colors: true },
    node: {
        global: true,
        process: false,
        Buffer: false,
        __filename: false,
        __dirname: false,
        setImmediate: false
    },
};

Babelrc

{
  "sourceMaps": true,
  "presets" : [["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 10"]
      }
    }],
    "stage-0"
   ],
  "plugins": [
    ["transform-decorators-legacy"],
    ["transform-react-jsx", { "pragma": "h" }]
  ]
}

package.json (I removed unnecessary stuff)

{
    "version": "0.10.11",
    "main": "webpack.config.js",
    "scripts": {
        "build": "cross-env NODE_ENV='development' webpack",
        "watch": "cross-env NODE_ENV='development' node --max_old_space_size=2000 webpack --watch",
        "watch:prod": "cross-env NODE_ENV='production' webpack --watch",
        "start": "cross-env NODE_ENV='development' webpack-dev-server --inline --hot --progress",
        "prod": "cross-env NODE_ENV='production' webpack",
    },
    "license": "ISC",
    "devDependencies": {
        "autoprefix": "^1.0.1",
        "babel-cli": "^6.26.0",
        "babel-core": "^6.26.0",
        "babel-eslint": "^7.2.3",
        "babel-jest": "^22.4.3",
        "babel-loader": "^7.1.2",
        "babel-minify-webpack-plugin": "^0.2.0",
        "babel-plugin-syntax-class-properties": "^6.13.0",
        "babel-plugin-transform-decorators-legacy": "^1.3.4",
        "babel-plugin-transform-react-jsx": "^6.24.1",
        "babel-polyfill": "^6.26.0",
        "babel-preset-env": "^1.7.0",
        "babel-preset-react": "^6.24.1",
        "babel-preset-stage-0": "^6.24.1",
        "babel-register": "^6.26.0",
        "babel-runtime": "^6.26.0",
        "clean-webpack-plugin": "^0.1.19",
        "coveralls": "^3.0.1",
        "cross-env": "^5.1.4",
        "css-hot-loader": "^1.3.9",
        "css-loader": "^0.28.7",
        "enzyme": "^3.3.0",
        "eslint": "^3.19.0",
        "eslint-import-resolver-webpack": "^0.10.0",
        "eslint-loader": "^1.9.0",
        "eslint-plugin-import": "^2.12.0",
        "eslint-plugin-jest": "^21.15.0",
        "eslint-plugin-jsx-a11y": "^6.0.3",
        "eslint-plugin-react": "^7.7.0",
        "extract-text-webpack-plugin": "^4.0.0-beta.0",
        "file-loader": "^1.1.6",
        "imports-loader": "^0.7.1",
        "jest": "21.2.1",
        "jest-cli": "^23.1.0",
        "node-sass": "^4.7.2",
        "path": "^0.12.7",
        "postcss-loader": "^2.1.3",
        "rimraf": "^2.6.2",
        "sass-loader": "^6.0.6",
        "source-map-loader": "^0.2.3",
        "style-loader": "^0.19.1",
        "webpack": "^4.12.0",
        "webpack-cli": "^2.1.5",
        "webpack-dev-server": "^3.1.4",
        "webpack-manifest-plugin": "^2.0.0-rc.2",
        "webpack-notifier": "^1.6.0"
    },
    "dependencies": {
        "preact": "^8.2.9",
        "preact-async-route": "^2.1.1",
        "preact-compat": "^3.18.0",
        "preact-router": "^2.6.0",
        "preact-views": "^1.0.0",
        "preact-virtual-list": "^0.3.1",
        "react-dnd": "^2.6.0",
        "react-dnd-html5-backend": "^2.6.0",
        "react-grid-layout": "^0.16.6",
        "react-popper": "^0.10.4",
        "redux-zero": "^4.12.0",
    }
}

EDIT: I've also included a test repo that repoduces this problem. https://github.com/ajm113/preact-grid-layout-test

EDIT 2: After some more digging around, seems like everything works perfectly fine in Webpack3 ... So did I miss something perhaps when configuring with Webpack4? -- I followed the preact-boilerplate code as close as possiable w/ the latest iteration with Webpack 4. So for whatever reason, Webpack 4 doesn't like mixing React/Preact code, and decides to strip things out a little too much. Anyone can confirm? -- Looks like it will be a lot longer before I can safely use Webpack 4 without running into constant headaches. :man_shrugging:

developit commented 6 years ago

This is a duplicate of #487 and #484. An Uglify update broke Preact, and we've released a fix in Preact 8.3.0. Updating should fix your app :)