Preact: Failed to render with preact-compat, react-router and UglifyJS

Created on 22 Dec 2017  路  3Comments  路  Source: preactjs/preact

I use uglifyjs-webpack-plugin on production.

On production only with react-router and preact, routing action is failed to render routed component in <Switch/>.

Codes

Routes.js

import React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Header from './Header'
import Home from './Home'
import NotFound from './NotFound'

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <Header /> 
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/*" component={NotFound} />
        </Switch>
      </div>
    </BrowserRouter>
  )
}

my webpack.config.js

const path = require('path')
const webpack = require('webpack')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin')

const pkg = require('./package')
const ENV = process.env.NODE_ENV || 'development'
const DEV_PORT = 4444

const hmrEntries = [
  'react-hot-loader/patch',
  `webpack-dev-server/client?http://localhost:${DEV_PORT}`,
  'webpack/hot/only-dev-server'
]

const deps = Object.keys(pkg.dependencies)

module.exports = {
  entry: {
    vendor: (ENV !== 'production' ? hmrEntries : []).concat(deps),
    app: ['./src/index.js']
  },
  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].bundle.js',
    path: __dirname + '/public',
    publicPath: '/'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    alias: {
      react: 'preact-compat',
      'react-dom': 'preact-compat',
      'preact-compat': 'preact-compat/dist/preact-compat'
    }
  },
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'vendor.bundle.js'
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(ENV)
    }),
  ].concat(
    ENV === 'production'
      ? [new UglifyJSPlugin({}), new CompressionPlugin()]
      : []
  )
}

versions

    "preact": "^8.2.7",
    "preact-compat": "^3.17.0",
    "react-router-dom": "^4.2.2",
    "uglifyjs-webpack-plugin": "1.1.4",

When I turn off resolve.alias, it works correctly with react.

Full code is here. https://github.com/mizchi-sandbox/pwa-base

Most helpful comment

This seems to be caused by the UglifyJS settings compress.reduce_vars causing VNode to be inlined into the definition of h, resulting in a new instance of the VNode-constructor for each call to h. preact-compat uses the constructor of a node to compare to other nodes to determine if the other nodes are valid vdom nodes in preact-compat.isValidElement. With VNode inlined this comparison will always be false. Switch uses preact-compat.isValidElement to filter out nulls, resulting in nothing rendered when minified with compress.reduce_vars=true.

A quick fix would be to set compress.reduce_vars to false.

All 3 comments

This seems to be caused by the UglifyJS settings compress.reduce_vars causing VNode to be inlined into the definition of h, resulting in a new instance of the VNode-constructor for each call to h. preact-compat uses the constructor of a node to compare to other nodes to determine if the other nodes are valid vdom nodes in preact-compat.isValidElement. With VNode inlined this comparison will always be false. Switch uses preact-compat.isValidElement to filter out nulls, resulting in nothing rendered when minified with compress.reduce_vars=true.

A quick fix would be to set compress.reduce_vars to false.

Same error here, but I don't use react-router. The error appeared when I switched to WebPack 4. compress.reduce_vars fixed it.

The uglify issue is tracked in https://github.com/developit/preact/issues/1065 馃帀

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adriaanwm picture adriaanwm  路  3Comments

skaraman picture skaraman  路  3Comments

youngwind picture youngwind  路  3Comments

marcosguti picture marcosguti  路  3Comments

nopantsmonkey picture nopantsmonkey  路  3Comments