ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.41k stars 777 forks source link

stencil build generates unintelligible error messages due to Terser #2457

Closed elpupi closed 2 years ago

elpupi commented 4 years ago

Stencil version:

 @stencil/core v1.13.0

I'm submitting a:

[x] bug report [] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

stencil build generates incomprehensible error messages without any clue from where it is originated.

Expected behavior:

Error messages should indicate which file produced an error and the message should explain a bit more what is happening. I understand, the error message comes from Terser and they are responsible of the output. But stencil is responsible to display the file producing the errors.

It is a nightmare to spot the culprit file without any clue, especially when a project has dependencies that can go deep. I spent almost 2 days to understand from what file was coming this error message:

Screenshot_20200519_125151

Firstly the message is not obvious at all. It is hard to understand that the error is that the "trailing comma in function arguments" is not supported until ECMAScript 2017. That message comes from Terser and I understand they are responsible to improve it. But, as you can see, the file producing the error is not mentioned. I spent 2 days to understand that the mistake was coming from a "node_modules" dependency, from the package "csvtojson". Moreover, I do not get why it is happening because looking at the source code of this package, the source code is not exactly the same than the one from the error message:

 // bla bla
 return "stack" in i || !n || "number" != typeof Error.stackTraceLimit ? (v = function(t, e) {
                            return "string" == typeof t ? t : "object" != typeof e && "function" != typeof e || void 0 === e.name || void 0 === e.message ? W(e) : e.toString()
 // etc

As you can see, it is different from:

return "stack" in i || !n || "number" != typeof Error.stackTraceLimit ? function (v, ) {
                                if (v === void 0) { v = function (t, e) { return "string" == typeof t ? t : "object" != typeof e && "function" != typeof e || void 0 === e.name || void 0 === e.message ? W(e) : e.toString(); }; }

and the culprit function (v, ) does not exist in the original source code. I guess, there is a first processing modifying the source code that is then generating the error.

Related code:

Let's define a simple component with the 2 properties we want to test:

import { Component, Host, h, Prop, Watch } from '@stencil/core';

@Component({
    tag: 'el-test'
})
export class ElTest {
    @Prop({ attribute: 'array' }) array: any[];
    @Prop() prop: string;

    @Watch('prop')
    @Watch('array')
    watch(newValue: any, _, propName: string) {
        console.log({ propName, newValue });
    }

    componentWillLoad() {
        this.watch(this.array, undefined, 'array');
        this.watch(this.prop, undefined, 'prop');
    }

    render() {
        return (<Host></Host>);
    }
}

Now let's instantiate it and see the output:

<el-test id="test" prop="a little test" array="[1,2,3,4]"></el-test>

<script>
    const test = document.getElementById('test2');

    setTimeout(() => {
        test.prop = 'a second test'
        test.array = [10, 11, 12];
    }, 1000);
</script>

Here is the console output:

23:04:57.390 el-test.entry.js:8 {propName: "array", newValue: undefined}
23:04:57.391 el-test.entry.js:8 {propName: "prop", newValue: "a little test"}
23:04:57.946 el-test.entry.js:8 {propName: "prop", newValue: "a second test"}
23:04:57.946 el-test.entry.js:8 {propName: "array", newValue: Array(3)}

As we can see, for the array property, the value is newValue: undefined during componentWillLoad phase, while it is not the case for prop being newValue: "a little test".

manucorporat commented 4 years ago

But, as you can see, the file producing the error is not mentioned.

terser is performed over the bundled code, it's not performed over the original file, so there is not easy way to tell where that really happened

elpupi commented 4 years ago

@manucorporat Yes this I know, but not easy does not mean impossible. It should be nice to implement a solution to keep track of the original files like sourcemaps.

splitinfinities commented 2 years ago

@milottit Heads up, Stencil supports sourcemaps as of v2.9.0! https://stenciljs.com/docs/config#sourcemap hopefully this should help you in the future!