Ngx-charts: ivy: d3-scale not transpile correctly

Created on 12 Feb 2020  路  15Comments  路  Source: swimlane/ngx-charts

Describe the bug
One of the dependency of ngx-charts, d3-scale throw error at line 23

const is not initialised 

To Reproduce
Steps to reproduce the behavior:

  1. update to angular version 9
  2. Test on IE 11

Expected behavior
Should able to transpile correctly

ngx-charts version
13.0.2

Bug

Most helpful comment

We had the same problem. While targeting ES2015 and letting differential loading take care of generating the ES bundles in production works fine we could not run and test the application locally with ng serve anymore. For ng serve we have to explicitly target ES5 to be able to debug the application in IE11.

We solved this for now by declaring "resolutions" in our package.json. This way we can downgrade d3-scale (to 2.x) and d3-array (to 1.x) - similar to what @shahmirn did - but without having to create a manuell build.

package.json

...
"resolutions": {
  "d3-scale": "^2.x",
  "d3-array": "^1.x"
},
...

All 15 comments

The problem is that d3-scale is not compiling its code to ES5 code, despite marking in its package.json that the code can be accessed via "main". See https://unpkg.com/browse/[email protected]/package.json.

main is assumed by ngcc to be ES5 (either CommonJS or UMD) format.

I would argue that this is a bug in the build setup for d3-scale.


I think you could work around this in ngcc by applying an ngcc.config.js file at the root of your project that looks like:

module.exports = {
  packages: {
    'd3-scale': {
      entryPoints: { './': { override: { main: undefined } } }
    }
  }
};

This should instruct ngcc to ignore the main property in d3-scale. It will fall back on the module property, which it will correctly infer is ES2015.

Hi @petebacondarwin, I tried the ngcc approach above doesn't work.

I edited the target on tsconfig.json to es2015 as the following, and it works. No idea why.

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "strictNullChecks": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
+++  "target": "es2015",
---  "target" : "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ],
    "paths": {
      "ngx-mp": [
        "dist/ngx-mp"
      ],
      "ngx-mp/*": [
        "dist/ngx-mp/*"
      ]
    }
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": false,
    "strictInjectionParameters": true
  }
}

I believe that works because it tells the CLI to check the module property before the main property since it is compiling ES2015 rather than ES5. I might have made a mistake in my configuration above since I wrote it off the top of my head and haven't checked it directly.

I found this in d3-scale:
Note: this release adopts ES2015 language features such as for-of and drops support for older browsers, including IE. If you need to support pre-ES2015 environments, you should stick with d3-scale 2.x or use a transpiler.

We are also encountering this error. How should we resolve?

@bryanrideshark - did you try setting your target to es2015?

@petebacondarwin - I haven't yet. I don't like making changes without fully understanding their implications. We need to support IE11, and if we change the target to es2015 might that cause our entire application to be compiled with let and const sprinkled everywhere?

I will try to change the target and see what happens, but that's not a good developer experience.

It would be superb for this library to support IE11 "out of the box". How can we fix @swimlane/ngx-charts so that users don't have to change their configurations to use the latest version?

@bryanrideshark - did you try setting your target to es2015?

Looking at this Stack Overflow answer, I am convinced that es2015 is not an acceptable solution.

https://stackoverflow.com/questions/42415942/typescript-what-is-target-in-tsconfig

I am quite new to Typescript. What does Target in tsconfig.json signify?

target signifies which target of JavaScript should be emitted from the given TypeScript. Examples:

target:es5
()=>null will become function(){return null} as ES5 doesn't have arrow functions.

target:es6
()=>null will become ()=>null as ES6 has arrow functions.

So, we really need to solve this without changing the target. If I find a solution I will post the answer here. For now, we are downgrading to version 12 as this version has d3 depencencies which are not offending IE11.

When building an Angular app using the CLI it is better to use ES2015 as the target because the CLI bundling will generate ES5 bundles that can be used by IE11 via differential loading. See https://angular.io/guide/deployment#differential-loading

@bryanrideshark I've got a PR open which essentially just downgrades d3-array and d3-scale to 1.x at https://github.com/swimlane/ngx-charts/pull/1379/files

I manually created a build (https://github.com/shahmirn/ngx-charts/tree/dist)

and changed my package.json to

"@swimlane/ngx-charts": "github:shahmirn/ngx-charts#dist",

You can do something similar, or just point your package.json to github:shahmirn/ngx-charts#dist

The only downside is that I every-so-often have to manually check if a new version of ngx-charts has been released that fixes this issue

@petebacondarwin This works fine when the app is built, but in development mode (so, using ng serve), it won't work in IE

We had the same problem. While targeting ES2015 and letting differential loading take care of generating the ES bundles in production works fine we could not run and test the application locally with ng serve anymore. For ng serve we have to explicitly target ES5 to be able to debug the application in IE11.

We solved this for now by declaring "resolutions" in our package.json. This way we can downgrade d3-scale (to 2.x) and d3-array (to 1.x) - similar to what @shahmirn did - but without having to create a manuell build.

package.json

...
"resolutions": {
  "d3-scale": "^2.x",
  "d3-array": "^1.x"
},
...

Does anyone know the difference between ng build --prod (differential loading) vs ng serve with a target of es5? I would have thought that would basically be the same thing but apparently not. It seems to me that just doing an es5 target with ng serve just targets the code I wrote in my application and doesn't transpile third party code the same way ng build --prod does?

The preferred approach the CLI takes is to build by setting tsconfig target at ES2015, building to ES2015 in TypeScript and then to down-level to ES5 afterwards. This is what happens normally when doing ng build --prod. The benefit of this is that you can do Differential Loading.
In this mode ngcc will be told to use ES2015 formats when compiling 3rd party libraries, if available and only falling back to ES5 if needed.

Setting the tsconfig target to ES5 circumvents this approach and only builds the ES5 in the first TypeScript build and so the only output is ES5.
If you are in ES5 target mode, then I think that the CLI will also tell ngcc to target ES5 over ES2015 when compiling 3rd party libraries.

We have also encountered this error with d3-array. How should we resolve it?
We use the version 14.0.0 and angular version 9

Was this page helpful?
0 / 5 - 0 ratings