Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unaccepted module - project with multiple webpack entrypoints works in some but not all #745

Open
grahamb opened this issue Apr 6, 2023 · 1 comment

Comments

@grahamb
Copy link

grahamb commented Apr 6, 2023

Bit of a weird issue here: I have a project using the following:

"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"express": "^4.18.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-refresh": "^0.14.0",
"webpack": "^5.77.0",
"webpack-cli": "^5.0.1",
"webpack-dev-middleware": "^6.0.2",
"webpack-hot-middleware": "^2.25.3",

The project has a webpack config with multiple entry points. My development webpack file is below:

import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import webpack from 'webpack';

// style files regexes
// lifted from react-scripts webpack config
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;

export default {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
  resolve: {
    alias: {
      'regenerator-runtime/runtime': 'regenerator-runtime/runtime.js',
    },
  },
  entry: {
    selfServeApp: [
      'webpack-hot-middleware/client',
      new URL('../../client/selfServeEntrypoint.js', import.meta.url).pathname,
    ],

    adminApp: [
      'webpack-hot-middleware/client',
      new URL('../../client/adminAppEntrypoint.js', import.meta.url).pathname,
    ],

    duoIframeLogin: [
      'webpack-hot-middleware/client',
      new URL('../../client/duoIframeLoginEntrypoint.js', import.meta.url)
        .pathname,
    ],

    duoIframeNagScreen: [
      'webpack-hot-middleware/client',
      new URL('../../client/duoIframeNagScreenEntrypoint.js', import.meta.url)
        .pathname,
    ],

    totpBypass: new URL('../../client/totpBypass/index.js', import.meta.url)
      .pathname,

    totpNotRegistered: new URL(
      '../../client/totpNotRegistered/index.js',
      import.meta.url
    ).pathname,

    totpLockout: new URL('../../client/totpLockout/index.js', import.meta.url)
      .pathname,
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].js',
    path: new URL('../../public/assets', import.meta.url).pathname,
    publicPath: process.env.CLIENT_PUBLIC_PATH || '/assets/',
  },
  optimization: {
    nodeEnv: 'development',
  },
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.(gif|png|jpe?g|svg)$/i,
            type: 'asset',
          },

          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                plugins: [
                  '@babel/plugin-syntax-dynamic-import',
                  'react-refresh/babel',
                ],
                presets: [
                  [
                    '@babel/preset-react',
                    {
                      runtime: 'automatic',
                    },
                  ],
                ],
              },
            },
          },

          // mostly lifted from react-scripts webpack config, with production stuff removed
          {
            test: cssRegex,
            exclude: cssModuleRegex,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  importLoaders: 1,
                  sourceMap: false,
                  // workaround for font data urls not working
                  // https://github.com/webpack-contrib/css-loader/issues/1342#issuecomment-881587038
                  url: {
                    filter: (url) =>
                      !url.startsWith('data:application/x-font-ttf'),
                  },
                },
              },
            ],
            // Don't consider CSS imports dead code even if the
            // containing package claims to have no side effects.
            // Remove this when webpack adds a warning or an error for this.
            // See https://github.com/webpack/webpack/issues/6571
            sideEffects: true,
          },

          // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
          // using the extension .module.css

          {
            test: cssModuleRegex,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  modules: {
                    localIdentName: '[name]__[local]___[hash:base64:5]',
                  },
                  importLoaders: 1,
                  // workaround for font data urls not working
                  // https://github.com/webpack-contrib/css-loader/issues/1342#issuecomment-881587038
                  url: {
                    filter: (url) => {
                      return !url.startsWith('data:application/x-font-ttf');
                    },
                  },
                },
              },
            ],
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new ReactRefreshWebpackPlugin({
      overlay: {
        sockIntegration: 'whm',
      },
    }),
  ],
  experiments: {
    topLevelAwait: true,
  },
};

I'm using Express to serve the app and webpack-dev-middleware in development to build and serve the development webpack bundles. Relevant Express setup for webpack-dev-middleware:

import webpack from 'webpack';
import WebpackDevMiddleware from 'webpack-dev-middleware';
import WebpackHotMiddleware from 'webpack-hot-middleware';
import webpackDevConfig from '../webpack/development/index.js';

  // if not in production mode, pull in development-specific config
  if (!isProduction) {
    const compiler = webpack(webpackDevConfig);
    app.use(
      WebpackDevMiddleware(compiler, {
        publicPath: webpackDevConfig.output.publicPath,
        stats: 'normal',
      })
    );
    app.use(WebpackHotMiddleware(compiler));
    app.set('compiler', compiler);
  }

This setup works in the selfServeApp and adminApp entrypoints, but not in the duoIframeLogin and duoIframeNagScreen entrypoints. In either of those, making a change to a React component causes webpack to build, but the browser does not update; I get warnings in the console about unaccepted updates:

webpack-dev-middleware output:
Screenshot 2023-04-06 at 11 04 07

Console after webpack builds:
Screenshot 2023-04-06 at 11 04 33

The entrypoints where hot refresh is working are far more complex than the ones where it isn't. The ones where is doesn't work are being loaded in iFrames, but hot refresh doesn't work when I load them standalone either, so I don't think the frame is the problem.

This is the entrypoint for one of the non-working bundles:

import * as Sentry from '@sentry/react';
import { inspect } from '@xstate/inspect';
import { createRoot } from 'react-dom/client';
import clientSentryOptions from './clientSentryOptions.js';
import DuoIframeNagScreen from './components/DuoIframeNagScreen/index.js';

if (process.env.SENTRY_DSN) {
  Sentry.init(clientSentryOptions);
  Sentry.configureScope((scope) => {
    scope.setTag('errorSource', 'client');
    scope.setTag('entrypoint', 'duoIframeNagScreenEntrypoint');
  });
}

if (process.env.NODE_ENV !== 'production') {
  inspect({
    url: process.env.XSTATE_VIZ_URL || 'https://statecharts.io/inspect',
    iframe: false,
  });
}

createRoot(document.getElementById('app')).render(<DuoIframeNagScreen />);

Nothing special going on.

I'm stumped, and not sure where to begin trying to understand why it's working in some but not all bundles. Any pointers would be appreciated!

@pmmmwh
Copy link
Owner

pmmmwh commented Apr 12, 2023

I believe there's something with iframe that's causing issues, will try to reproduce.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants