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

Default import is undefined in dev, but exists in --prod #9058

Closed
cebor opened this issue Jan 2, 2018 · 5 comments · Fixed by #9759
Closed

Default import is undefined in dev, but exists in --prod #9058

cebor opened this issue Jan 2, 2018 · 5 comments · Fixed by #9759

Comments

@cebor
Copy link
Contributor

cebor commented Jan 2, 2018

Versions

<!--
Output from: `ng --version`.
If nothing, output from: `node --version` and `npm --version`.
  Windows (7/8/10). Linux (incl. distribution). macOS (El Capitan? Sierra?)
-->
Angular CLI: 1.6.3
Node: 9.3.0
OS: darwin x64
Angular: 5.1.2
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.6.3
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.5.3
webpack: 3.10.0

Repro steps

Observed behavior

<!-- Normally this includes a stack trace and some more information. -->
TypeError: chartModule is not a function
    at eval (webpack-internal:///../../../../angular-highcharts/angular-highcharts.es5.js:257)
    at Array.forEach (<anonymous>)
    at ChartService.initModules (webpack-internal:///../../../../angular-highcharts/angular-highcharts.es5.js:256)
    at new ChartModule (webpack-internal:///../../../../angular-highcharts/angular-highcharts.es5.js:286)
    at _createClass (webpack-internal:///../../../core/esm5/core.js:11112)
    at _createProviderInstance$1 (webpack-internal:///../../../core/esm5/core.js:11086)
    at initNgModule (webpack-internal:///../../../core/esm5/core.js:11039)
    at new NgModuleRef_ (webpack-internal:///../../../core/esm5/core.js:12293)
    at createNgModuleRef (webpack-internal:///../../../core/esm5/core.js:12283)
    at Object.debugCreateNgModuleRef [as createNgModuleRef] (webpack-internal:///../../../core/esm5/core.js:14627)

Desired behavior

Following default import should not be undefined: https://github.com/cebor/angular-highcharts-demo/blob/master/src/app/app.module.ts#L4

Mention any other details that might be useful (optional)

  • ng serve --prod is working
  • with ng 1.6.1 all works fine
@zoamel
Copy link

zoamel commented Jan 2, 2018

I have similar issues with lodash (which I partially resolved by installing lodash-es instead) and with is_js (this is blocking issue for me since I can't find good solution for using this with cli > 1.6.1)

So at the moment I can't use imports like:
import is from 'is_js' or import isString from 'lodash/isString' since I'm getting errors that is or isString are undefined

@KamelJabber
Copy link

KamelJabber commented Jan 2, 2018

I was just about to post a bug with steps to reproduce the loadash issue. I have encountered similar issues.
I specifically am running ng build --watch, however, the same errors occur with ng serve

@zoamel @cebor , I have fixed my lodash issue by changing:
import isFunction from 'lodash/isFunction'
to
import * as isFunction from 'lodash/isFunction'

My other issue has to do with my Angular Components that extends a BaseComponent.
When Angular component does not have an ngOnInit function, ONLY in watch mode, attempting to access the Angular Component's ngOnInit I get an undefined method.

For that, I had to wrap checks around the method calls.

For example:

@Injectable()
export class EaiComponent implements OnInit, OnDestroy, OnChanges {
    private _util: Util;

    constructor(private injector: Injector) {
        this._util = this.injector.get(Util);

        const ngOnInit = this.ngOnInit !== EaiComponent.prototype.ngOnInit ? this.ngOnInit : this.util.noop;
        const ngOnChanges = this.ngOnChanges !== EaiComponent.prototype.ngOnChanges ? this.ngOnChanges : this.util.noop;
        const ngOnDestroy = this.ngOnDestroy !== EaiComponent.prototype.ngOnDestroy ? this.ngOnDestroy : this.util.noop;
        const destroy = this.destroy !== EaiComponent.prototype.destroy ? this.destroy : this.util.noop;
        this._me = this.constructor ? this.constructor.name : EaiComponent.name;

        this.ngOnInit = (...args) => {
            EaiComponent.prototype.ngOnInit.apply(this, args);
            if (ngOnInit) {
                ngOnInit.apply(this, args)
            }
        }
}

Note: Rolling back to 1.6.1 works fine in both scenarios. The issue presented starting with 1.6.2

@filipesilva filipesilva self-assigned this Jan 3, 2018
@filipesilva filipesilva added needs: investigation Requires some digging to determine if action is needed P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent type: bug/fix P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful and removed needs: investigation Requires some digging to determine if action is needed P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent labels Jan 3, 2018
@filipesilva filipesilva changed the title Default import is undefined Default import is undefined in dev, but exists in --prod Jan 3, 2018
@filipesilva
Copy link
Contributor

#9059 reported a similar problem. Using the reproduction provided by @cebor I boiled it down to a simpler repro:

import more from 'highcharts/highcharts-more.src';
import dragula from 'dragula';

console.log(more);
console.log(dragula);

Both of these console logs will show undefined in ng serve but functions in ng serve --prod. It's not related to --aot however.

I tracked it down to #8128, where we force TS to use commonjs on dev serve. The difference is significant... at the time it could go as high as 60% of rebuild time.

This causes different semantics to be used for default imports. This optimization will go away with Webpack 4 (#8611) but for now it's a huge rebuild speed improvement.

For now I think the only good alternative is to force the default import:

import * as more from 'highcharts/highcharts-more.src';
import * as dragula from 'dragula';

console.log(more);
console.log(dragula);

This will work on dev/prod.

@will-l-h
Copy link

@filipesilva Thanks for above workaround. It fixed one issue for us on one default import but in another case a library where we use momentjs and build the library using ngc & rollup, using the "import *" approach gives the following error during the rollup step

[!] Error: Cannot call a namespace ('moment')

There are some workarounds to that, ( rollup/rollup#670 (comment) ) but a consuming angular app throws

TypeError: moment_1.default is not a function

Is the fix that will come with webpack 4 a big task that is not going to happen anytime soon?

@hansl hansl removed the blocked label Jan 24, 2018
@filipesilva filipesilva added comp: cli/build and removed P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix labels Feb 14, 2018
filipesilva added a commit to filipesilva/angular-cli that referenced this issue Feb 23, 2018
filipesilva added a commit to filipesilva/angular-cli that referenced this issue Feb 23, 2018
filipesilva added a commit to filipesilva/angular-cli that referenced this issue Feb 23, 2018
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
6 participants