Skip to content

options given to react-refresh/runtime is undefined, leaving originalFactory undefined & crashing app #328

@Haraldson

Description

@Haraldson

I’m at my second attempt at upgrading from Webpack 4 to 5, and even though I have double and triple checked my configuration, there’s no way to be sure whether I got it all correct. I’ve finally made webpack-dev-server compile my app, but it crashes runtime.

image
image

In case there are any common and easily identifiable mistakes, I’m pasting in what I think is the relevant bits and pieces:

package.json

"devDependencies": {
    "webpack": "latest",
    "webpack-cli": "^4.5.0",
    "webpack-dev-server": "^3.11.2",
    "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
    "react-refresh": "^0.9.0"
},
"dependencies": {
    "@babel/runtime": "^7.13.10",
    "@babel/runtime-corejs3": "^7.13.10",
    "@hot-loader/react-dom": "17",
    "core-js": "3",
    "react": "^17.0.1",
    "react-dom": "npm:@hot-loader/react-dom",
},
"engines": {
    "node": "14.x",
    "yarn": "2.4.x"
}

webpack.common.js

const { ContextReplacementPlugin, DefinePlugin } = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const excludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const WebpackBar = require('webpackbar')
const { dateFnsLocales, ie11, transpile } = require('./package.json')

module.exports = (env, argv, mode) => ({
    mode,

    entry: [
        ...ie11,
        `${__dirname}/src/index.js`
    ],

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: excludeNodeModulesExcept(transpile),
                use: [
                    'thread-loader',
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: true
                        }
                    }
                ]
            },
            {
                test: /\.(ttf|woff|woff2)$/,
                exclude: /node_modules/,
                loader: 'base64-inline-loader'
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif|ico)$/,
                exclude: /node_modules/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name: '[name].[fullhash].[ext]',
                        outputPath: 'static/gfx/'
                    }
                }]
            },
            {
                test: /\.csvg$/,
                loader: '@svgr/webpack'
            },
            {
                test: /\.ucsvg$/,
                use: [{
                    loader: '@svgr/webpack',
                    options: {
                        svgo: false
                    }
                }]
            },
            {
                test: /\.md$/,
                loader: 'raw-loader'
            },
            {
                test: /\.js.flow$/,
                loader: 'ignore-loader'
            }
        ]
    },

    plugins: [
        new CleanWebpackPlugin(),
        new ContextReplacementPlugin(
            /date-fns[/\\]locale$/,
            new RegExp(`[/\\\\](${dateFnsLocales.join('|')})[/\\\\]`)
        ),
        new WebpackBar(),
        new DefinePlugin({
            process: JSON.stringify({
                env: {
                    NODE_ENV: mode
                }
            })
        })
    ],

    resolve: {
        modules: [`${__dirname}/src`, 'node_modules'],
        extensions: ['*', '.js', '.jsx'],
        alias: {
            'react-dom': '@hot-loader/react-dom',
            package: `${__dirname}/package.json`
        },
        fallback: {
            crypto: require.resolve('crypto-js'),

            // Thinking maybe one of these might have to be polyfilled?
            // Haven’t seen that documented anywhere, though.
            process: false,
            buffer: false,
            stream: false,
            fs: false,
            zlib: false,
            http: false,
            https: false
        }
    },

    output: {
        path: `${__dirname}/dist`,
        filename: '[name].[fullhash].bundle.js',
        chunkFilename: '[name].[fullhash].bundle.js',
        publicPath: '/'
    }
})

webpack.dev.js

module.exports = (env, argv) => merge(common(env, argv, 'development'), {
    devtool: 'inline-source-map',

    plugins: [
        new HotModuleReplacementPlugin(),
        new ReactRefreshWebpackPlugin({
            include: /\.js$/i,
            overlay: false
        }),
        new HtmlPlugin({
            favicon: `${__dirname}/src/static/gfx/favicon.dev.ico`,
            template: `${__dirname}/src/index.html`
        })
    ],

    devServer: {
        contentBase: 'src',
        host: '0.0.0.0',
        port: 7070,
        hot: true,
        disableHostCheck: true,
        historyApiFallback: true,
        clientLogLevel: 'warn',
        stats: 'minimal',

        proxy: {}
    }
})

babel.config.js

const excludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const { transpile } = require('./package.json')

module.exports = api => {
    api.cache.using(() => process.env.NODE_ENV)

    return {
        presets: [
            ['@babel/preset-env', {
                useBuiltIns: 'usage',
                corejs: {
                    version: 3,
                    proposals: true
                },
                targets: {
                    node: 'current',
                    ie: 11
                }
            }],
            '@babel/preset-react'
        ],
        plugins: [
            ['@babel/plugin-transform-runtime', { corejs: 3 }],
            '@babel/plugin-syntax-dynamic-import',
            '@babel/plugin-transform-arrow-functions',
            '@babel/plugin-proposal-class-properties',
            '@babel/plugin-proposal-optional-chaining',
            '@babel/plugin-transform-template-literals',
            '@babel/plugin-proposal-nullish-coalescing-operator',
        ],
        env: {
            development: {
                plugins: [
                    'react-refresh/babel',
                    ['babel-plugin-styled-components', {
                        ssr: false,
                        transpileTemplateLiterals: true,
                        displayName: true
                    }]
                ]
            }
        },

        overrides: [{
            exclude: excludeNodeModulesExcept(transpile),
            plugins: ['@babel/plugin-transform-modules-commonjs']
        }]
    }
}

Any input welcome – so far I’m lost on how to go about debugging this. I’m not sure whether it originates in code outside my control, or that I configured something wrong, but in any case I would need an explanation, in the long term preferrably as a warning from the code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions