Angular-cli: Cannot access variable that is initialized when jQuery is ready

Created on 1 Jul 2019  路  16Comments  路  Source: angular/angular-cli

馃悶 Bug report

Command (mark with an x)


- [ ] new
- [ ] build
- [x] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc

Is this a regression?


Yes, the previous version in which this bug was not present was: 8.0.6

Description

When a global variable is initialized inside a jQuery.ready callback, it is undefined when trying to be accessed from Angular code.

馃敩 Minimal Reproduction


https://github.com/bampakoa/jquery-issue

1. npm install
2. ng serve
3. Check console error messages

馃敟 Exception or Error

ERROR ReferenceError: App is not defined
    at AppService.show (app.service.ts:11)
    at AppComponent.ngOnInit (app.component.ts:36)
    at callHook (core.js:4847)
    at callHooks (core.js:4811)
    at executeHooks (core.js:4762)
    at executePreOrderHooks (core.js:4734)
    at refreshDescendantViews (core.js:11577)
    at renderComponentOrTemplate (core.js:11960)
    at tickRootContext (core.js:13242)
    at detectChangesInRootView (core.js:13278)

馃實 Your Environment

Angular CLI: 8.1.0-rc.0
Node: 10.15.3
OS: win32 x64
Angular: 8.0.3
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.801.0-rc.0
@angular-devkit/build-angular     0.801.0-rc.0
@angular-devkit/build-optimizer   0.801.0-rc.0
@angular-devkit/build-webpack     0.801.0-rc.0
@angular-devkit/core              8.1.0-rc.0
@angular-devkit/schematics        8.1.0-rc.0
@angular/cli                      8.1.0-rc.0
@ngtools/webpack                  8.1.0-rc.0
@schematics/angular               8.1.0-rc.0
@schematics/update                0.801.0-rc.0
rxjs                              6.4.0
typescript                        3.4.5
webpack                           4.35.0

Anything else relevant?

  • The App object is initialized in this line.
  • I have enabled Ivy compiler.

devkibuild-angular high regression bufix

Most helpful comment

Strict mode is an inherent property of module scripts and cannot be disabled independently.

However, the issue actually appears to be a defect in the ng serve HTML generation logic. It's currently being overzealous in its inclusion of type="module" attributes.

Trying the original authors reproduction with a build and manually serving resulting in a working application. However, ng serve did in fact exhibit the behavior.
Please note also that ng serve does not use differential loading and changing the target to es5 did fix the problem when running ng serve. However, this should not be necessary and a fix will be arriving shortly to correct the behavior of ng serve.

In addition, module scripts (and their inherent strict mode) are the future. Whenever possible, please consider updating code or notifying third-party library providers to request they make the transition.

All 16 comments

We're serving scripts with script[type="module"], this means that they are automatically in strict mode.

In non-strict mode:

var App = function () {
  ...
};

Would make App global, but in strict mode it will not. I'd not recommend exposing globals but if you have to, the way to solve your problem is to update app.js:

window.App = function () {
  ...
};

@mgechev thanks for the feedback. What should we do if the script is from a 3rd party vendor and we cannot change it? This is a common case, especially in jQuery based plugins.

You can disable differential loading, but still, not a recommendation. The best solution would be to use modern plugins which are compatible with strict mode.

Thanks again for your answer @mgechev . In our company, we are currently running two big projects that use a common theme, purchased from a 3rd party vendor. Scripts of the theme follow the principle that is described above.

We are now running Angular and CLI versions 8.0 Will this mean that we will not be able to upgrade to CLI 8.1 in the future? I think that this is something that the CLI team should consider.

I have this problem, too. with:

  • popper.js
  • bootstrap-material-design.js
  • ajv.js

@bampakoa we can use @angular-devkit/[email protected]. With it it's working as it should be.

Me to, but just only via ng s, working ng build.

This is a serious breaking change for who must use some old or broken third party library.

And is against what the angular guide itself says:

scripts | An object containing JavaScript script files to add to the global context of the project. The scripts are loaded exactly as if you had added them in a聽

Strict mode is an inherent property of module scripts and cannot be disabled independently.

However, the issue actually appears to be a defect in the ng serve HTML generation logic. It's currently being overzealous in its inclusion of type="module" attributes.

Trying the original authors reproduction with a build and manually serving resulting in a working application. However, ng serve did in fact exhibit the behavior.
Please note also that ng serve does not use differential loading and changing the target to es5 did fix the problem when running ng serve. However, this should not be necessary and a fix will be arriving shortly to correct the behavior of ng serve.

In addition, module scripts (and their inherent strict mode) are the future. Whenever possible, please consider updating code or notifying third-party library providers to request they make the transition.

I believe this change with type="module" has broken our Clarity Icons library, so we are recommending to downgrade to 8.0.6 until there is another workaround.

@gnomeontherun Can you provide an example application that is not working on 8.1?
I tried using the icons with both the direct script element configuration and adding the scripts (custom-elements.min.js/clr-icons.min.js) to the scripts option in angular.json. Both appear to be successful as a clr-icon element was displayed when added inside the app component during an ng serve

Assuming you have CLI 8.1 installed globally...

ng new icons-test --defaults
cd icons-test
ng add @clr/angular
ng serve

Doing this will create a new project with Clarity, and it tries to load the scripts using type=module which is causing issues. Be sure to open console for error, as some things seem to load but there is still an error.

Yes; there's an error but the custom element will still function.
The error is due to the UMD bundle using a global this which is undefined in strict mode. It's using that global this due to this line in the webpack configuration for the package: https://github.com/vmware/clarity/blob/master/webpack.icons.config.js#L45

This is incorrect for a web environment. I'm not sure why Webpack's documentation recommends using this. The correct form for a library that will be used in both node and web would be:

globalObject: '(typeof self !== "undefined" ? self : this)'

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings