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

Hack to fix : "Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry'" #5407

Open
flatmax opened this issue Oct 17, 2018 · 14 comments
Labels

Comments

@flatmax
Copy link

flatmax commented Oct 17, 2018

Quite often when developing polymer elements and more complex polymer apps, the browser reports :
Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry'"

It is caused by polymer modules which are nested in node_modules inside the top level node_modules directory.

EDIT: The following comments are now out of date ... see new approaches in the comment from December 20th 2019 below. There is an in-app dynamic solution and a static out of app solution.

Our workaround removes all nestings of polymer elements ...

In package.json, execute a preinstall script :

  "scripts": {
    "preinstall": "../preinstall.sh"
  }

We find we have to do a scriptless npm install twice to make all elements install with bugs and then do the nested polymer element removal ...
The file preinstall.sh :

#!/bin/bash
# Author: Flatmax developers
# Date : 2018 10 17
# License : free

npm i --ignore-scripts || true
if [ `ls node_modules/ | wc -l` -eq "0" ]; then
  zenity --error --text="ERROR : cb() never called\nrm node_modules and pacakge-lock.json and try again"
fi
npm i --ignore-scripts || true
if [ `ls node_modules/ | wc -l` -eq "0" ]; then
  zenity --error --text="ERROR : cb() never called\nrm node_modules and pacakge-lock.json and try again"
fi
. ../fixNestings.sh

Then the file which removes nestings, fixNestings.sh :

#!/bin/bash
# Author: Flatmax developers
# Date : 2018 10 17
# License : free

# The following function will remove nested directories, where $1 exists like so
# node_modules/.*/node_modules/$1
# @param $1 the module name to remove nestings of
function rmNestedMod(){
  name=$1
  paths=`find -L node_modules -name $1 | sed "s|^node_modules/||;s|/\$name$||" | grep node_modules`
  for p in $paths; do
    echo rm -rf node_modules/$p/$name
    rm -rf node_modules/$p/$name
  done
}

# remove all nested polymer modules in the polymer namespace
namespaces=`ls node_modules/@polymer/`
for n in $namespaces; do
  rmNestedMod "$n"
done

Again, we don't like this approach, any work arounds ?

@hzmsrv
Copy link

hzmsrv commented Oct 18, 2018

I found the same issue when I import 2 custom elements in a page.

Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry
at http://127.0.0.1:8000/lib/element-dropdown-button/node_modules/@polymer/polymer/lib/elements/dom-module.js:147:16

@hzmsrv
Copy link

hzmsrv commented Oct 20, 2018

Did anyone fix this bug?

@btopro
Copy link

btopro commented Nov 9, 2018

https://www.npmjs.com/package/@lrnwebcomponents/deduping-fix we've been using this in our demo pages to get around this issue when it comes to mono-repo / lerna / yarn based development of polymer w/ polymer serve

chrisekelley added a commit to Tangerine-Community/Tangerine that referenced this issue Dec 27, 2018
…2.8.0",

Had to imcrement typescript version to get jasmine tests to run.
preinstall.sh and fixNestings.sh are a solution to a polymer lib issue from here: Polymer/polymer#5407
Note that web component imports are commented out in polyfills.ts.
In tsconfig.json, esModuleInterop is to fix "export 'process' was not found issue
@yveslange
Copy link

I am getting the same issue using npm link.

Any updates on that topic ?

@btopro
Copy link

btopro commented Apr 2, 2019

https://github.com/elmsln/wcfactory bakes in some pre and post install hook hacks in order to avoid this issue. I haven't seen any "do it this way" guidance that doesn't hamper workflow.

you can see the solution we're using in our instance stamped from the tooling --
https://github.com/elmsln/lrnwebcomponents/blob/master/package.json#L27-L28
https://github.com/elmsln/lrnwebcomponents/tree/master/scripts -- pre and post scripts

I'd happily switch off this if there was a better solution but I have yet to run into it. Run these scripts pre and post install, always do installs from the root of the monorepo. I update package.json's manually per element, then run yarn install from the root.

Weakness of this approach:

  • bash based
  • can get you out of sync w/ dependencies since any project adding the resource will give it to all of them

@yveslange
Copy link

yveslange commented Apr 2, 2019

Thanks for the sharing. I will definitely take a look at it.

My project is private and can't be published on NPM for the moment. Therefore, I can't use the Enterprise NPM offer.

I actually engaged myself to move to Lerna and a bootstrap.sh script just for the purpose of downloading the packages from NPM and my git repositories.

I added a monorepo to gather all the packages that are part of my specific project and bootstrap it. The bootstrap copies all the node_modules at the root and creates the symbolic links in each packages.

Thus, I can now develop easily in the packages that are dependent on each others.

As a result, the polyserve is now working correctly and I don't have nested importations.

Now I still need to resolve the publishing part (mainly because I want to publish to my git repositories and not to NPM).

A bit of work I guess...

@btopro
Copy link

btopro commented Apr 2, 2019

could always just not publish. wcf sets things in motion for npm publishing but isn't required. lerna publish is what does that.

@msbasanth
Copy link

https://github.com/elmsln/wcfactory bakes in some pre and post install hook hacks in order to avoid this issue. I haven't seen any "do it this way" guidance that doesn't hamper workflow.

you can see the solution we're using in our instance stamped from the tooling --
https://github.com/elmsln/lrnwebcomponents/blob/master/package.json#L27-L28
https://github.com/elmsln/lrnwebcomponents/tree/master/scripts -- pre and post scripts

I'd happily switch off this if there was a better solution but I have yet to run into it. Run these scripts pre and post install, always do installs from the root of the monorepo. I update package.json's manually per element, then run yarn install from the root.

Weakness of this approach:

  • bash based
  • can get you out of sync w/ dependencies since any project adding the resource will give it to all of them

Is removing the nesting polymer modules is the right solution for this problem?
My monorepo is also followed the folder structure of lrnwebcomponents. When I tried running the scripts preinstall.sh ran fine but with postinstall script I am getting an error "ln: failed to create symbolic link './node_modules': Device or resource busy". Seen this error before I am in Windows 10 running the postinstall command in bash shell (VS Code)

@btopro
Copy link

btopro commented Dec 19, 2019

@msbasanth I had someone report this yesterday; maybe try running the postinstall manually after it's finished and see if that helps. I think it might be bc the yarn script running all in 1 swoop to install is putting a lock on the node modules directory (guess here)

@flatmax
Copy link
Author

flatmax commented Dec 19, 2019

We have moved away from dynamic in-app deduping and as much as possible we use only sandard npm tools such as npm dedupe.
The idea is to use npm link to your local projects and dependencies, npm i installs 3rd party dependencies. It is similar to your approach, however have the following differences :

  • We don't allow the webapp to dynamically dedupe, we ensure all deduping is static and it is all done at install time.
  • use npm dedupe rather then a third party dedupe mechanism which is in the code base. This means we don't carry 3rd party payloads which enforce dynamic in app deduping.

The general description of our approach is as follows: Clean up any previous npm dedupe related problems by removing node_modules. In your dependency projects run npm link. Ensure all links are in the root node_modules directory. Use npm dedupe to remove any duplications.

More detail on the steps is like so :

  • Clean up after previous dedupe session, remove node_modules from any dependencies and the current project
  • in all local dependency directories run npm link. These directories are local to you and not in a node_modules directory.
  • npm install, in the project directory
  • Move any symbolic links deep in the node_modules directory to the root node_modules directory (otherwise they get clobbered by some npm tools). Here is how we do this ...
# file moveLinks.sh
echo moving links to base node_modules dir
linksBase=`find ../C++/webApp -type l | grep node_modules | grep -v .bin`
for l in $linksBase ; do
  # move links to root
  mv $l node_modules
done
  • relink broken links with the npm link tool, like so ...
# file relink.sh
echo relinking broken links 
links=`find node_modules -type l`
for l in $links ; do
  # for links which don't exist, run npm link
  if [ ! -e "$l" ]; then
    bn=`basename $l`
    npm link $bn
  fi
done
  • npm dedupe
  • Run the relink code above to fix any newly broken links by npm dedupe

now serve ! It should run nicely with nothing deduped at run time, all statically deduped on disk.

We put the code snippets into their own moveLinks.sh and relink.sh scripts and call them from our own installation script which looks like so :

#!/bin/bash
# webapp installer - leaving a deduped node_modules directory
rm -rf node_modules
pushd ../myDependency # rm node_modules run npm link in this dir and others 
  rm -rf node_modules package-lock.json
  npm link
popd
echo installing webApp requirements
npm i
./moveLinks.sh
./relink.sh
echo npm dedupe
npm dedupe
./relink.sh
# now serve

@msbasanth
Copy link

Thanks @flatmax for the detailed explanation. I will give a try with this approach.

Thanks alot

@msbasanth
Copy link

@msbasanth I had someone report this yesterday; maybe try running the postinstall manually after it's finished and see if that helps. I think it might be bc the yarn script running all in 1 swoop to install is putting a lock on the node modules directory (guess here)

@btopro Yes, I could see it is script running when tried independently. yarn documentation says "The dedupe command isn’t necessary. yarn install will already dedupe.". So if we have a yarn workspace we need these scripts?

Two approaches I tried,

  1. Only using yarn install(no preinstall.sh & postinstall.sh) in my WebComponent Library project and including it in another Angular project using NPM link.
    This works fine as each element source code is directly referenced (no BUNDLING using rollup or WebPack). So NO "Failed to execute 'define' on 'CustomElementRegistry'"

  2. Same as above except we have each element bundled separately using rollup. But with bundled elements we are still getting "Failed to execute 'define' on 'CustomElementRegistry'".

Is it like we cannot separately bundle (rollup) with Polymer/LitElement elements at all? Or do we have things to take care when we bundle a PolymerElement using rollup?

When I tried postinstall.sh is not helping with bundled elements. I could see rollup is used per element in https://github.com/elmsln/lrnwebcomponents. Is separately bundled UI WebComponents expected to work fine after running postinstall.sh?

Am I doing wrong with my rollup config?

import { createCompatibilityConfig } from '@open-wc/building-rollup';
const indexHTML = require('rollup-plugin-index-html');

import cpy from 'rollup-plugin-cpy';

const configs = createCompatibilityConfig({
	input: 'src/index.html',
	outputDir: 'build',
	extensions: ['.js', '.mjs', '.ts'],
	plugins: {
		workbox: false,
		indexHTML: false,
	}
});

export default function configFactory() {
	return [
		// LEGACY
		{
			...configs[0],
			output: {
				...configs[0].output,
				sourcemap: false,
				entryFileNames: '[name].js',
				chunkFilename: '[name].js'
			},
			plugins: [
				...configs[0].plugins,
				cpy([
					{ files: '../styles/styles.css', dest: 'build/legacy' },
					{ files: '../fonts', dest: 'build/legacy/fonts' },
					{ files: '../../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js', dest: 'build/legacy' }]),
				indexHTML({
					legacy: true,
				}),
			]
		},
		// MODERN
		{
			...configs[1],
			output: {
				...configs[1].output,
				sourcemap: false,
				entryFileNames: '[name].js',
				chunkFilename: '[name].js'
			},
			plugins: [
				...configs[1].plugins,
				cpy([
					{ files: '../styles/shui-styles.css', dest: 'build' },
					{ files: '../fonts', dest: 'build/fonts' },
					{ files: '../../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js', dest: 'build' }]),
				indexHTML({
					polyfills: {
						coreJs: true,
						regeneratorRuntime: false,
						webcomponents: false,
					},
				}),
			]
		}
	]
};

@yveslange
Copy link

yveslange commented Mar 18, 2020

Using es-dev-server works fine now ! I have a script that will install the node_modules in every directory and will move them up in the root directory. Then it installs the node modules of the root directory.

I hade this issue few times.
Most of the time this is because of the node_modules folder.

I resolve this by:

--> STOP your http-server, polymer serve, es-dev-server
$ rm -rf node_modules package-lock.json
$ npm install
--> STOP your http-server, polymer serve, es-dev-server again

@stale
Copy link

stale bot commented Mar 19, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Mar 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants