question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Introduce new flag for minifier optimization hints

See original GitHub issue

Search Terms

Optimization Minifier Bundler IIFE Wrapper Terser

Suggestion

TypeScript 3.9 pulled in PR #32011, which tailors TypeScript’s output for optimization with minifiers such as Terser. This PR definitely goes in the right direction for optimizing TypeScript’s emit for most users, but doesn’t necessarily work for all toolchains out there. At Google we have optimization processes after TypeScript compilation that use static analysis to look for classes, do some rough type-checking, and for example rename class properties and drop methods. The wrapper introduced in TypeScript 3.9 hinders our ability to analyze these classes.

We’d like to propose a new flag to toggle this behavior, which I’ll call --add-optimization-hints for now. This flag would control if TypeScript decides to emit these hints for optimizers and bundlers, which is not necessarily limited to the /** @class */ form introduced in TypeScript 3.9. For users such as Google, we can disable this flag and instead rely on our own optimizers to handle this, but users piping directly through Webpack and Terser can still receive the benefits from #32011.

Use Cases

Removing IIFE Wrapper for ES2015 Classes

Expanding on our toolchain a bit from above, at Google we use a combination of tsickle, closure-compiler, and other tools to optimize our TypeScript code. Tsickle is used to add type annotations and use the goog.module module system to TypeScript’s emit such that Closure Compiler can optimize the code. Using the TypeScript 3.9 RC which emits IIFE wrappers around ES2015 classes Closure Compiler is unable to understand that this is an alias for the inner class. By setting --add-optimization-hints=false we would be able to statically analyze TypeScript’s output without doing additional special processing.

Adding Further Optimization Hints

PR #32011 isn’t the first to request optimization hints from the TypeScript output, for example #13721 requested a /** #pure */ annotation as well, and there could be more in the future that TypeScript would like to hint at. Adding this flag allows TypeScript to produce messier code that is less similar to the input, but more compatible with bundlers and minifiers.

Examples

This would be a new flag for the TypeScript compiler. Assuming TypeScript 3.9 is being used, given the input:

// input.ts
class C {
  static prop = 10;

  getProp() {
    return C.prop;
  }
}

Compiling with tsc --add-optimization-hints=true:

// output.js
"use strict";
let C = /** @class */ (() => {
    class C {
        getProp() {
            return C.prop;
        }
    }
    C.prop = 10;
    return C;
})();

Compiling with tsc --add-optimization-hints=false:

// output.js
"use strict";
class C {
    getProp() {
        return C.prop;
    }
}
C.prop = 10;

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:15
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

13reactions
rrdelaneycommented, May 26, 2020

Thanks for taking a look into this! We really appreciate the thought going into this issue. We (@IgorMinar, @mprobst, @rrdelaney) met, here’s our perspective:

  • terser does not work well with the TS emit for classes containing static properties or decorators (terser cannot detect that the static property assignments have no side effects as long as the class goes unused).
  • We’ve considered improving terser, but that seems difficult to achieve.
  • Angular CLI currently includes relatively complex workarounds to post-process TS emit for terser compatibility.
    • We think these are less complex to implement in TS.
    • They are also more efficient: they’d run before publishing to NPM, instead of on each (Angular) application build.
    • This was the goal of #32011.
  • Closure Compiler does not work with this particular emit (detecting the particular case and reliably unwrapping the IIFE — and only this kind — is hard). We expect other toolchains would have similar issues.

We think rolling back for the time being is the right thing to do, and we should reconsider the approach taken in the PR.

A potential solution might be annotating TS emit on a semantic level (e.g. /** @staticproperty */ MyClass.staticProp = 1), which would allow downstream tools to easily process the output without special casing for a particular optimizer. This also seems to be more in line with TypeScript’s design goals, in particular 3. and 4. This will need more research though.

9reactions
farfromrefugcommented, Nov 11, 2020

This is already 6 months old, what s the status on this? When can we see this at list with a flag? I stumbled upon as i was trying to figure out why tree shaking was not working in Nativescript. Nativescript is heavily based on Typescript and decorators. Tree shaking makes a big difference in app startup time. Without that flag/fix we will never be able to improve things further.

EDIT: did anyone did that with a transformer. We might be able to detect static/decorators and wrap in that case? I am not that familiar with transformers but maybe someone found a way.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Asset Size - Elm Guide
Instructions. Step one is to compile with the --optimize flag. This does things like shortening record field names. Step two is to minify...
Read more >
Optimizing Code — Emscripten 3.1.26-git (dev) documentation
Code is optimized by specifying optimization flags when running emcc. ... Emscripten also optimizes the combined wasm+JS, by minifying imports and exports ...
Read more >
The complete best practices for minifying CSS - LogRocket Blog
CSS minification is an optimization best practice that can deliver a significant performance boost — even if it turns out to be mostly...
Read more >
Minifying - SurviveJS
In webpack, minification process is controlled through two configuration fields: optimization.minimize flag to toggle it and optimization.minimizer array to ...
Read more >
Decrease front-end size - web.dev
Webpack 4 introduced the new mode flag. ... Webpack supports two ways to minify the code: the bundle-level ... new webpack.optimize.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found