terser / terser

🗜 JavaScript parser, mangler and compressor toolkit for ES6+
https://terser.org
Other
8.7k stars 389 forks source link

Terser mangle properties #995

Closed Hoodgail closed 3 years ago

Hoodgail commented 3 years ago

I am using the terser webpack plugin,

Issue I have a lib fetching data from an api then parsing it using JSON.parse But terser mangle the properties from variable, as you see in the picture i want it to mangle other properties but just not from JSON.parse

image

Expected result

const a = JSON.parse(s);
if(void 0 === a.metadata || a.metadata.version[0] < 2 )
sirian commented 3 years ago

Possible solutions:

  1. mark all properties from api as reserved
mangle: {
    properties: {
        reserved: ['metadata', 'version', ...],
    }
}
  1. use "quoted" access for properties that should not be mangled and enable option mangle.properties.keep_quoted: true
    if (undefined === a["metadata"] || a["metadata"]["version"] < 2)

See example: foo not mangled because "reserved" bar mangled baz not mangled, becase quoted access ["baz"] image

billreynolds007 commented 3 years ago

In a related fashion, we have a ton of source code that accesses 3rd party libraries. A simple set of code is shown below which accesses AWS S3,

const AWS = require('aws-sdk');

class AwsS3Driver extends AbstractFileDriver
{   
constructor()
{
  super();
  this.s3 = null;
}
setServerParameters ()
{
  this.s3 = new AWS.S3({
    accessKeyId: this.myAccessKey,
    secretAccessKey: this.mySecretKey
  });
}
}

What I see is that the API related tokens of S3, accessKeyId, and secretAccessKey all get mangled.

So, it seems for all interactions with external libraries, we need to provide reserved words for:

Is that correct?

Hoodgail commented 3 years ago

Possible solutions:

  1. mark all properties from api as reserved

But i wont have access to change that in every libraries tho

sirian commented 3 years ago

@billreynolds007 @Hoodgail

So, it seems for all interactions with external libraries, we need to provide reserved words for:

  • all referenced function names such as "S3",
  • any intermediate field paths to those functions."bar" in foo.bar.doThisCall(), and
  • any of the object structure field names as well (accessKeyId and secretAccessKey)

Is that correct?

I choose another aproach (much more safe) - add '$' suffix to all properties in my code, and mangle properties using regex /\w\$$/. Thus mangling won't have side effects with 3rd party libs. It's a bit ugly at first look, but it's worth it. And this transformation could be easily done with structural replacement of WebStorm https://www.jetbrains.com/help/webstorm/structural-search-and-replace-examples.html

class Foo {
    bar$ = 1;
    zoo$() {
        ...
    }
}
Hoodgail commented 3 years ago

@billreynolds007 @Hoodgail

So, it seems for all interactions with external libraries, we need to provide reserved words for:

  • all referenced function names such as "S3",
  • any intermediate field paths to those functions."bar" in foo.bar.doThisCall(), and
  • any of the object structure field names as well (accessKeyId and secretAccessKey)

Is that correct?

I choose another aproach (much more safe) - add '$' suffix to all properties in my code, and mangle properties using regex /\w\$$/. Thus mangling won't have side effects with 3rd party libs. It's a bit ugly at first look, but it's worth it. And this transformation could be easily done with structural replacement of WebStorm https://www.jetbrains.com/help/webstorm/structural-search-and-replace-examples.html

class Foo {
    bar$ = 1;
    zoo$() {
        ...
    }
}

Thank you, it will take me about 3 weeks to make this change that for all 20+ files of 1000+ lines of js code but it will be worth it

sirian commented 3 years ago

@Hoodgail I refactored project with 400 files and over 25000 lines of code in less than 1 week. P.S. We use typescript - so huge refactoring is not a problem