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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

ivy throw [tagName] is not a known element #33685

Closed
elvisbegovic opened this issue Nov 8, 2019 · 21 comments

Comments

@elvisbegovic
Copy link
Contributor

@elvisbegovic elvisbegovic commented Nov 8, 2019

馃悶 bug report

Affected Package

I think, the issue is caused by package @angular/core

Is this a regression?

Yes, it works in ViewEngine

Description

In angular v9 rc1 enable ivy with certain 3th party lib throw * is not known element

馃敩 Minimal Reproduction

One line repro :
git clone https://github.com/elvisbegovic/ivy-tag-is-not-a-known-element.git && cd ivy-tag-is-not-a-known-element && npm i && ng s -o

Compilation/serve is OK, but at runtime (open dev tools) error is:

馃敟 Exception or Error


core.js:6068 ERROR Error: 'tree-viewport' is not a known element:
1. If 'tree-viewport' is an Angular component, then verify that it is part of this module.
2. If 'tree-viewport' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    at validateElement (core.js:23156)
    at Module.傻傻elementStart (core.js:22963)
    at TreeComponent_Template (tree.component.js:245)
    at executeTemplate (core.js:13684)
    at renderView (core.js:13486)
    at renderComponent (core.js:14841)
    at renderChildComponents (core.js:13291)
    at renderView (core.js:13512)
    at renderComponent (core.js:14841)
    at renderChildComponents (core.js:13291)

Snippet code of compiled tree.component.js

馃實 Your Environment

See Environment...

**Angular Version:**
<pre><code>
Angular CLI: 9.0.0-rc.1
Node: 12.13.0
OS: win32 x64
Angular: 9.0.0-rc.1
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.1
@angular-devkit/build-angular     0.900.0-rc.1
@angular-devkit/build-optimizer   0.900.0-rc.1
@angular-devkit/build-webpack     0.900.0-rc.1
@angular-devkit/core              9.0.0-rc.1
@angular-devkit/schematics        9.0.0-rc.1
@ngtools/webpack                  9.0.0-rc.1
@schematics/angular               9.0.0-rc.1
@schematics/update                0.900.0-rc.1
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2
</code></pre>

鉁嶏笍 Anything else relevant?

This breaks application at runtime, annoying we cannot see that durning build/serve step.

/cc @alxhub @petebacondarwin

@joshcomley

This comment has been minimized.

Copy link

@joshcomley joshcomley commented Nov 8, 2019

I am having this exact same issue, but I think I can narrow it down to <ng-content select="..."> usage. See my simple example project here (no 3rd party library, only an additional library in the workspace):

https://github.com/joshcomley/ng91tagbug

One line:

git clone https://github.com/joshcomley/ng91tagbug.git && cd ng91tagbug && npm i && ng build mylib && ng serve

This works fine with v9 rc0 but errors on v9 rc1.

@mattdsteele

This comment has been minimized.

Copy link

@mattdsteele mattdsteele commented Nov 8, 2019

I'm seeing something similar when trying to use custom elements. This only regressed in rc.1, custom elements were working fine in rc.0 and earlier.

To reproduce, create a new app using the CLI, add schemas: [CUSTOM_ELEMENTS_SCHEMA] to the module, and add a new elements to a template, such as <foo-bar>. This will throw this error:

ERROR Error: "'foo-bar' is not a known element

Changing the angularCompilerOption "enableIvy": false, fixes the issue.

@pkozlowski-opensource

This comment has been minimized.

Copy link
Member

@pkozlowski-opensource pkozlowski-opensource commented Nov 13, 2019

Probably due to c83f501

@chrste90

This comment has been minimized.

Copy link

@chrste90 chrste90 commented Nov 13, 2019

This also seems to break ngx-extended-pdf-viewer. With rc0, the library works, but with rc1 i get core.js:6068 ERROR Error: 'menuitem' is not a known element:, see more details here: stephanrauh/ngx-extended-pdf-viewer#169

@mattdsteele

This comment has been minimized.

Copy link

@mattdsteele mattdsteele commented Nov 13, 2019

@pkozlowski-opensource thanks for the commit.

Cursory view of it makes me think c83f501 doesn't play nicely with lazy-loaded custom elements (i.e. the tags are on the page, but don't have customElements.define() called against them until later after they've been loaded).

This is the default behavior of web components compiled with Stencil: https://stenciljs.com/blog/how-lazy-loading-web-components-work

Was the check against customElements.get() occurring in the past?

@stephanrauh

This comment has been minimized.

Copy link

@stephanrauh stephanrauh commented Nov 13, 2019

Additional information to #33685 (comment):

The validation method validateElement() is elegant, but it breaks on corner cases like menuitem.

Currently, menuitem is implemented by Firefox, but not by Chrome or Safari. As far as I know, menuitem was part of the HTML standard before HTML5. It has been marked as deprecated, but Firefox continued to support this tag.

Be that as it may, some people - such as the pdf.js team - are using both menu and menuitem in their application. That's why ngx-extended-pdf-viewer run fine on Firefox but is broken on Chrome and Safari.

@kara kara removed this from the v9-candidates milestone Nov 14, 2019
@ngbot ngbot bot added this to the needsTriage milestone Nov 14, 2019
@kara kara modified the milestones: needsTriage, v9-blockers Nov 14, 2019
@mhevery mhevery self-assigned this Nov 14, 2019
@negue

This comment has been minimized.

Copy link

@negue negue commented Nov 17, 2019

At first I thought this issue was only after an error happened, but now this happens to me randomly on a rebuild (9.0.0-rc.2) with material components (currently only using these as 3rd party components) - the only fix is to kill and restart the serve process.

@elvisbegovic

This comment has been minimized.

Copy link
Contributor Author

@elvisbegovic elvisbegovic commented Nov 18, 2019

More infos: my issue with certain lib happened at first 芦聽ng serve聽禄 at runtime (without any lazyroutes)

And if I remove deps of the 3th party lib I can confirm what @negue is saying, in our project we get some * is not a kown element when CLI rebuild.

@mhevery

This comment has been minimized.

Copy link
Member

@mhevery mhevery commented Nov 20, 2019

Seems related to #32388 (which has fixes #33551 or #33522), however this does not seem to fix this issues since trying https://github.com/elvisbegovic/ivy-tag-is-not-a-known-element.git with master still fails.

Analysis

The core issue is that the application instantiates <tree-root [nodes]="nodes"></tree-root> which in turn instantiates <tree-viewport #viewport>. Both <tree-root> and <tree-viewport> come from node_modules.

When we see what ngcc produced for the TreeComponent we see this (abbreviated):

TreeComponent.傻cmp = _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻defineComponent"]({
    type: TreeComponent,
    selectors: [["Tree"], ["tree-root"]],
    contentQueries: function TreeComponent_ContentQueries(rf, ctx, dirIndex) { ... }
    },
    viewQuery: function TreeComponent_Query(rf, ctx) { ... },
    hostBindings: function TreeComponent_HostBindings(rf, ctx, elIndex) {
        if (rf & 1) {
            _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻listener"]("keydown", function TreeComponent_keydown_HostBindingHandler($event) {
                return ctx.onKeydown($event);
            }, false, _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻resolveBody"])("mousedown", function TreeComponent_mousedown_HostBindingHandler($event) {
                return ctx.onMousedown($event);
            }, false, _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻resolveBody"]);
        }
    },
    inputs: {...},
    outputs: {...},
    features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻ProvidersFeature"]([_models_tree_model__WEBPACK_IMPORTED_MODULE_1__["TreeModel"]]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻NgOnChangesFeature"]()],
    decls: 5,
    vars: 4,
    consts: ...,
    template: function TreeComponent_Template(rf, ctx) {
        if (rf & 1) {
            _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻elementStart"](0, "tree-viewport", null, 0);
            ...
            _angular_core__WEBPACK_IMPORTED_MODULE_0__["傻傻elementEnd"]();
        }
        ...
    },
    encapsulation: 2
});

Notice that the output is missing:

   directiveDefs: [ TreeViewComponent ]

Because of the above code missing the schema checker than fails with the error above saying 'tree-viewport' is not a known element:

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

I think the missing property is actually directives: ... but I agree that ngcc is not generating it for this package.

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

I have identified the root, root cause of the problem in @elvisbegovic's one-line reproduction. This is probably not the general problem for other commenters on this issue but see the bottom of my analysis for ideas in those cases.

  1. The root cause is actually that angular-tree-component's UMD build is not valid. Their use of rollup does not specify mobx, mobx-angular and lodash as external packages, which leads to the UMD bundle including these packages inline.
    Note that the ESM files do not bundle up these external libraries and instead imports them as expected.
  2. ngcc computes dependencies between packages before processing them; it must ensure that packages are processed after their dependences. Do do this it parses just the first of the code formats that it recognises. Because it considers the package.json properties in this order - ['fesm2015', 'fesm5', 'es2015', 'esm2015', 'esm5', 'main', 'module'] it finds the main property (UMD) before the module property (ESM). So ngcc was using the broken UMD format for computing the dependencies and so missing the mobx-angular package.
  3. Since mobx-angular was not found as a dependency of angular-tree-component the former was being processed "after" the latter, which meant that angular-tree-component had a missing dependency when it came to processing the ESM format (aka module).
  4. The missing dependency during compilation can be identified as an error but is currently being swallowed.
  5. The compilation (and so the ngcc processing) completes "successfully" but the directives used by the component are not generated in the rendered output, leading to the runtime errors we see here.

Possible resolutions:

  1. Workaround by adding a ngcc.config.js that hides the main property in angular-tree-component so that we always use the module property for both processing and for dependency resolution.
  2. Fix angular-tree-component - provide a PR to fix this package's distributable (500tech/angular-tree-component#771)
  3. Change the order of dependency resolution properties, so that module is before main. I think it was originally in this order because it was felt that a single flat file would be parsed faster than having to load up a deep non-flat hierarchy of files; but it is also reasonable to assume that main is more likely to be "broken" than module in 3rd party libraries out there.
  4. Add better diagnostic reporting to ngcc to help diagnose these scenarios. PR here #33964
@joshcomley

This comment has been minimized.

Copy link

@joshcomley joshcomley commented Nov 21, 2019

So what about my example above?

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

I'll look at yours next @joshcomley :-)

@elvisbegovic

This comment has been minimized.

Copy link
Contributor Author

@elvisbegovic elvisbegovic commented Nov 21, 2019

I can confirm it works!!!

Having this temporary ngcc.config.js with (if I understand):

module.exports = {
  packages: {
    'angular-tree-component': {
      entryPoints: {
        '.': {
          override: {
            main: undefined
          }
        }
      }
    }
  }
};

Or removing this line "main": "dist/angular-tree-component.umd.js", in node_modules/angular-tree-component/package.json

Then rerun ngcc, makes our large-app working with ivy!

By the way, doing this first ng serve always throw this warning:

WARNING in Entry point 'angular-tree-component' contains deep imports into 'C:/Users/xxx/node_modules/lodash/defaultsDeep', 'C:/Users/xxx/node_mo
dules/lodash/get', 'C:/Users/xxx/node_modules/lodash/omit', 'C:/Users/xxx/node_modules/lodash/isNumber', 'C:/Users/xxx
/node_modules/lodash/first', 'C:/Users/xxx/node_modules/lodash/last', 'C:/Users/xxx/node_modules/lodash/some', 'C:/Users/e.begovic/WebstormProjec
ts/i10/node_modules/lodash/every', 'C:/Users/xxx/node_modules/lodash/compact', 'C:/Users/xxx/node_modules/lodash/find', 'C:/Users/e.begovic/Webst
ormProjects/i10/node_modules/lodash/isString', 'C:/Users/xxx/node_modules/lodash/isFunction', 'C:/Users/xxx/node_modules/lodash/throttle', 'C:/Us
ers/xxx/node_modules/lodash/includes', 'C:/Users/xxx/node_modules/lodash/pick'. This is probably not a problem, but may cause the compilation of
entry points to be out of order.

Thank you @petebacondarwin

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

That warning is expected, since the angular-tree-component imports deeply from lodash which are not "proper" APF entry-points. But it doesn't matter in this case because lodash is not an Angular library.

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

With the change to the diagnostics reporting we get:

Compiling angular-tree-component : module as esm5
console_logger.ts:38
Error: Failed to compile entry-point angular-tree-component due to compilation errors:
node_modules/mobx-angular/dist/mobx-angular.d.ts(5,22): error TS-996002: Appears in the NgModule.imports of TreeModule, but could not be resolved to an NgModule class

which at least will tell us where to start looking and not leave us with an obscure runtime error.

petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 21, 2019
Previously, these errors were being swallowed, which made it
hard to debug problems with packages.

See angular#33685 (comment)
alxhub added a commit that referenced this issue Nov 21, 2019
)

Previously, these errors were being swallowed, which made it
hard to debug problems with packages.

See #33685 (comment)

PR Close #33964
alxhub added a commit that referenced this issue Nov 21, 2019
)

Previously, these errors were being swallowed, which made it
hard to debug problems with packages.

See #33685 (comment)

PR Close #33964
@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

@joshcomley - as far as I can tell your scenario is working as expected. The <myselector> element is not known to Angular - it is neither a well-known HTML element nor a component/directive defined with an element selector.

Note also that this has nothing to do with MyLibComponent being in a separate package (or even NgModule). You can move it to the main package (and declare it in the AppModule and you get the same result. It is possible that this error was not shown in JIT mode until recently when we landed c83f501.


Oh! I just saw in your repro that you have actually added NO_ERRORS_SCHEMA to the NgModule, which means that it really should not error... 馃

I think this is a bug in the ivy code - probably related to c83f501

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

I have created a new issue for the NO_ERRORS_SCHEMA scenario which is different to this issue: #33976

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 21, 2019

Closing this as ngcc is actually working as expected and we have landed the PR to improve the error messaging.

@stephanrauh

This comment has been minimized.

Copy link

@stephanrauh stephanrauh commented Nov 21, 2019

@petebacondarwin Just doublechecking: did you address the menuitem issue, too?

IMHO that's a tricky one. It works on Firefox but fails on most other browsers.

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 22, 2019

@stephanrauh:

The menuitem element is deprecated and not supported by the Angular AOT compiler (see its element registry). And now it is not supported in JIT mode since c83f501.

There is an easy workaround, which is to tell Angular about this element by declaring a directive with that element as its selector:

@Directive({selector: 'menuitem'})
export class MenuitemDirective {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can鈥檛 perform that action at this time.