Next.js: IE11, development, HMR: Object doesn't support property or method 'attachShadow'.

Created on 22 May 2020  路  17Comments  路  Source: vercel/next.js

Bug report

Describe the bug

Basically the nextjs page bugs in IE11 development with the following message.

Object doesn't support property or method 'attachShadow'

It seems related to development hot module reloading. Somehow the /_next/webpack-hmr route is caught by express. I have by the way seen similar bugs when using custom routes in pure nextjs pages previously. Unsure if this is related.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Install the custom-server-express example.
  2. Add this snippet in server.js:
  server.get('/:one/:two', (req, res) => {
    console.log("Parameters", req.params)
    return res.redirect('/a')
  })
  1. Open localhost:3000 in Internet Explorer 11.
  2. The page flashes the actual content before going white.
  3. Open the console (F12) and the attachShadow message flashes indefinitely.
  4. In the command window, read the message Parameters { one: '_next', two: 'webpack-hmr' }

Expected behavior

I expected to see my content. I would have also expected that attachShadow was either added as a built-in polyfill in nextjs, or that the function was avoided. I believe it can be traced to this location: @next\react-dev-overlay\lib\internal\components\ShadowPortal.js. In other locations in the next package you have an if-test to avoid this - it seems to me.

Screenshots

image

System information

  • OS: Windows 10
  • Browser: IE 11
  • Version of Next.js: latest (as per today, using the custom-server-express example)
  • Version of Node.js: 10.16.0

Additional context

I came across this while updating a production package. I wanted to debug the polyfills and find out whether I still need to add polyfills for IE11 after next 9.3. This was a major roadblock.

The real problem here is probably using attachShadow in IE11.

I will try to recreate it without an express server...

good first issue bug

Most helpful comment

@altruisticsoftware in src/polyfills.js, import '@webcomponents/shadydom';

It is configured in next.config.js within the webpack config like so:

const originalEntry = config.entry;
    config.entry = async () => {
      const entries = await originalEntry();

      if (
        entries['main.js'] &&
        !entries['main.js'].includes('./src/polyfills.js')
      ) {
        entries['main.js'].unshift('./src/polyfills.js');
      }

      return entries;
    };

All 17 comments

Small update - I couldn't immediately recreate the error without an express server, but I didn't pour my soul into it. Would it be an easy fix to add an if-test for attachShadow in the specific place I pointed to?

I'm having the same error, also using an express server.

same error error here with [email protected] on IE11 in dev mode. this make IE11 debugging impossible in dev mode

I think this could be solved by using webcomponents polyfill (https://github.com/webcomponents/polyfills) in the packages/react-dev-overlay/lib/internal/components/ShadowPortal.tsx file.

I could try to make a PR if you'd be interested

We fixed this in our application using the @webcomponents/shadydom polyfill, +1 to @tomdohnal

@tomdohnal That did it for me, thank you.

@amigolargo - Could you post where exactly you decided to put the polyfill in your app? The issue for us is coming from <Head /> imported from next/document, and if we omit the <Head /> from _document.js, everything breaks from an error unrelated to this one. Obviously we'd still like to use _document.js

@altruisticsoftware in src/polyfills.js, import '@webcomponents/shadydom';

It is configured in next.config.js within the webpack config like so:

const originalEntry = config.entry;
    config.entry = async () => {
      const entries = await originalEntry();

      if (
        entries['main.js'] &&
        !entries['main.js'].includes('./src/polyfills.js')
      ) {
        entries['main.js'].unshift('./src/polyfills.js');
      }

      return entries;
    };

Would someone be willing to setup an IE 11 development test suite for us?

It'd be great to fix this and prevent future regressions with CI.

do you have a browserstack.com account or another solution to run IE11 tests ?

I believe this has been resolved in https://github.com/vercel/next.js/pull/13704? That PR does fix this issue for me.

I am still getting this error on next 9.5.3 - is there anything else I need to do to fix it? Production mode works. This is my .browserlistrc in root:

# Supported browser list.
# See https://github.com/browserslist/browserslist for more details.

last 2 chrome versions
last 2 ChromeAndroid versions
last 2 edge versions
last 2 firefox versions
last 2 ios_saf versions
last 2 safari versions
ie 11
node 12

I'm getting this error too on old Firefox, using next 9.5.3

TypeError: portalNode.current.attachShadow is not a function

    Portal/< webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/components/ShadowPortal.js:37:30

The above error occurred in the <Portal> component:
    in Portal (created by ReactDevOverlay)

thanks @amigolargo and @tomdohnal ur solution worked

dev-build-watcher.js are checking for attachShadow.
https://github.com/vercel/next.js/blob/8426f13713c6a1ac498562479d864633cf355c6d/packages/next/client/dev/dev-build-watcher.js#L18-L26

If you add @webcomponents/shadydom polyfill, it does not add a value to prefix, so the css name is applied globally.
The website I am maintaining has a problem because it is using #container as its main content wrapper.
#container is a universal class naming, so it could be a problem for others.
(Problem only occurs with old browsers in the development mode)
https://github.com/vercel/next.js/blob/8426f13713c6a1ac498562479d864633cf355c6d/packages/next/client/dev/dev-build-watcher.js#L124-L129

Thank you @amigolargo and @tomdohnal.

I just fixed this problem with your solution in Next.js 9.5.5.

package.json

"@webcomponents/shadydom": "^1.7.4"

next.config.js

module.exports = {
  webpack: function (config) {
    const originalEntry = config.entry;

    config.entry = async () => {
      const entries = await originalEntry();

      if (
        entries["main.js"] &&
        !entries["main.js"].includes("./src/polyfills.js")
      ) {
        entries["main.js"].unshift("./src/polyfills.js");
      }
      return entries;
    };

    return config;
  },
};

./src/polyfills.js

import "@webcomponents/shadydom";

^ Above code fixes for me too, I recommend this further optimization to keep that dependency out of prod:

./src/polyfills.js:

if (process.env.NODE_ENV === 'development') {
    require('@webcomponents/shadydom');
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

formula349 picture formula349  路  3Comments

YarivGilad picture YarivGilad  路  3Comments

kenji4569 picture kenji4569  路  3Comments

rauchg picture rauchg  路  3Comments

timneutkens picture timneutkens  路  3Comments