• This repository has been archived on 29/Dec/2022
  • Stars
    star
    119
  • Rank 287,362 (Top 6 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created almost 9 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A tool to aid minification of Typescript code, using Typescript's type information.

TS-Minify (Experimental) Build Status

About


TS-Minify is tool to aid in the reduction of code size for programs written in the TypeScript language. It is currently highly experimental.

This tool is developed on TypeScript and NodeJS, and transpiled to ES5; it uses the CommonJS module system.

There is currently no CLI or build-tool integration for TS-Minify.

Table of Contents


Motivation


Angular 2 (which is written in TypeScript) currently sits at around 135kb after being Uglified and compressed through GZIP. In comparison, Angular 1.4 is about 50kb, minified and compressed.

A smaller bundle size means that less data needs to be transferred and loaded by the browser. This contributes to a better user experience.

The impetus for this tool was to reduce the code size of the Angular 2 bundle, but TS-Minify is meant to be a generic tool that can be used on programs written in TypeScript.

What it Does


To achieve code size reduction, TS-Minify uses the idea of property renaming: take a TypeScript source file and rename properties to shorter property names, then re-emit the file as valid TypeScript.

TS-Minify role in minification pipeline This diagram demonstrates TS-Minify's role in the intended minification pipeline.

TS-Minify only targets property renaming. Minification tactics like whitespace removal, dead code removal, variable name mangling, etc. are taken care of by tools such as UglifyJS. TS-Minify specifically targets property renaming since it is something that is difficult to achieve safely without type information. As such, TS-Minify requires a program to be correctly and throughly typed, otherwise, unwanted renaming may occur.

How Does it Work? The TL;DR


The TypeScript Compiler API is utilized in order to access the Abstract Syntax Tree of a TypeScript source file. Identifiers that might be considered properties (such as identifiers in property declarations, property access expressions, method names in method declarations, etc.) are renamed to short names such as a, b, etc. after determining their renaming eligibility. A β€œrenaming” global map is created with mappings from the original property name to the new generated property name so that re-namings are kept consistent between properties with the same names.

{ maybeHandleCall: g }
{ reportMissingType: h }
{ getHandler: i }
{ handlePropertyAccess: j }
{ emitExtraImports: k }
{ emit: l }
{ visitTypeName: m }

An example of some mappings from the original property name to the shorter, generated property name.

The renaming eligibility of a property takes several factors into consideration:

  • Does the property belong to an object declared in an external file (.d.ts file)?
  • Does the property belong to a standard built-in object?
  • Does the property name belong to the DOM?

External vs. Internal Types


TS-Minify is able to safely rename properties by understanding which types are external, and which are not, to one's program.

An external type is something that you are bringing into your program. It is a type which you have not defined. This includes objects and functions from the JavaScript standard library, and JavaScript libraries like underscore.js or jQuery. If you are using external libraries, it is imperative that you include their corresponding .d.ts files.

Typings for the standard library are included in the default library typings, lib.d.ts, which the TypeScript compiler uses during transpilation (it will typecheck your program at compile time) and does not need to be explicitly included.

Internal types are ones that you, the programmer, have defined yourselves. Declaring a class Foo in your program tells the minifier that properties on Foo objects are within the renaming scope. Internal types also include things like object literal types.

Note: If you want all internal sources to contain the same renamings, you should pass the relevant files together through a single pass of the minifier.

An example of what types are considered external and internal:

var x: { name: string, message: string }; // The object literal is an internal type

var x: Error; // Error is an external type

// Structurally, the two are compatible, which brings us to the next section...

Structural Typing


TypeScript uses a structural type system. This means that objects and variables can be casted from one type to another as long as they are structurally compatible. Sometimes this means that external objects might be casted to internal objects, or vise versa.

Here is an example of an external type being casted to an internal type:

function x(foo: { name: string, message: string }) {
	foo.name;
	return foo; 
} 

x(new Error());

Function x expects an internal object literal type. The call site x(new Error()) passes an Error object as the parameter.

Error is an object in the JavaScript standard library. Hence it is external to our small program above. Structurally, an Error object and the object literal { name: string, message: string } are compatible. However, this means that we do not want to rename the properties on the object literal because we will likely want to access the properties of the Error object as we know them: name and message. If we renamed the properties of the object literal, it means that if an Error object is passed into a function call for x(), foo.$some_renaming will throw an error, because Error does not have property $some_renaming.

Here is an example of an internal type being coerced into an external type:

function ff(e: Error) { 
	return e.name; 
} 

ff({ name: null, message: null });

The parameter e on function ff is an external type to our program. We do not want to rename its properties. At the function call site, we are passing in an object literal type with properties name and message, which is structurally compatible with Error. We do not want to rename properties in the object literal because we need to coerce it into an external typing, which is expected to have properties name and message.

All of this is to say, the tool relies on type information to figure out if two types can be coerced into each other and whether their properties can be renamed based on the internal/external distinction. Type your programs! :)

Usage


First clone the repo and run npm install.

$ git clone [email protected]:angular/ts-minify.git
$ cd ts-minify
$ npm install

Create a new TypeScript file:

import {Minifier, options} from './src/main';
var minifier = new Minifier();
minifier.renameProgram(['path/to/file.ts', 'path/to/another/file.ts', 'some/other/file.d.ts'], 'path/to/destination');

Transpile the above script into JavaScript using the TypeScript compiler and run it with Node:

tsc --module commonjs script.ts
node script.js

A new instance of the minifier takes an optional constructor argument:

MinifierOptions {
  failFast?: boolean;
  basePath?: string;
}

failFast: Setting failFast to true will throw an error when the minifier hits one.

basePath: Specifies the base path that the minifier uses to figure out to where to write the minfied TypeScript file. The basePath maybe be relative or absolute. All paths are resolved from the directory in which the minifier is executed. If there is no base path, the minified TypeScript file is outputted to the specified destination using a flattened file structure.

minifier.renameProgram() takes a list of file names and an optional destination path:

renameProgram(fileNames: string[], destination?: string)

renameProgram accepts TypeScript files and .d.ts files. If you are not explicitly including typings using the reference path syntax in your TypeScript file, please pass in the .d.ts file so that the minifier can use the type information.

The minifier will uniformly rename the properties (which are available for renaming) across all the files that were passed in.

TSConfig Users


If you are using a tsconfig.json file to reference your type definitions, pass in the .d.ts files for libraries used in your program to the minifier so that it can reference the type information for property renaming. The minfier does not have access to the tsconfig.json file. Otherwise, make sure to have /// <reference path = 'foo.d.ts' /> at the top of your programs if you are using any external libraries.

Scope of Minification


Currently, TS-Minify will do property renaming throughout all the files that are passed into it. The minifier excludes .d.ts files from renaming because those are the typing definitions of external libraries. If your TypeScript program exports objects across those files, the minifier will rename them uniformly in their declarations and their usage sites.

Caveats/Warnings


In order to get the most out of the minifier, it is recommended that the user types their program as specifically and thoroughly as possible. In general, you should avoid using the any type, and implicit anys in your code as this might result in unwanted naming.

We recommend that you compile your TypeScript program with the noImplicitAny compiler flag enabled before trying the minifier.

Please avoid explicit any casting:

// example of explicit any casting
var x = 7; 
<any>x;

Sample Measurements


TS-Minify was run on a well-typed TypeScript program with the following stats and results:

  • Approximately 2100 lines of code (split across 10 files)
  • Unminified and Uglified: 72kb
  • Minified and Uglified: 56kb (codesize reduction of about 20%)
  • About 6% - 8% codesize reduction after minification, Uglification, and GZIP compression.

Contributing


Clone the repository from GitHub:

$ git clone [email protected]:angular/ts-minify.git
$ cd ts-minify
$ npm install

Run the unit tests with gulp unit.test

Run the end-to-end tests with gulp e2e.test.

This project uses clang-format. Run gulp test.check-format to make sure code you write conforms to this standard.

  • If you need some guidance on understanding TypeScript, look at the TypeScript GitHub Wiki.
  • If you need a quick introduction to the TS Compiler API, take a look at the page on using the TS Compiler API.
  • Take a look at the typescript.d.ts for type signatures, and to understand what is available to you from the TS toolchain.

If you need some help debugging, there is a DEBUG flag that can be enabled in src/main.ts:

const DEBUG = true; // switch from false to true to enable the console.logs

There are some helpful print statements which print out:

  • the SyntaxKind of the nodes being traversed
  • the minified string output
  • a dictionary of external/internal type casts

Remember to switch the DEBUG flag off afterwards.

Contributors


Daria Jung (Google intern)

License: Apache 2.0


Copyright 2015 Google, Inc. http://angular.io

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Future


Property renaming is hard and there are a lot of issues! If you're interesting in contributing to this project, please check some of them out.

Issues are labelled easy, medium, and hard. Some have a Needs Exploration label which means you might have to poke around a bit before reaching conclusions about how to tackle the problem!

More Repositories

1

angular

The modern web developer’s platform
TypeScript
91,840
star
2

angular.js

AngularJS - HTML enhanced for web apps!
JavaScript
59,091
star
3

angular-cli

CLI tool for Angular
TypeScript
26,587
star
4

components

Component infrastructure and Material Design components for Angular
TypeScript
24,075
star
5

material

Material design for AngularJS
JavaScript
16,637
star
6

angular-seed

Seed project for angular apps.
JavaScript
13,050
star
7

protractor

E2E test framework for Angular apps
JavaScript
8,780
star
8

angularfire

Angular + Firebase = ❀️
TypeScript
7,595
star
9

flex-layout

Provides HTML UI layout for Angular applications; using Flexbox and a Responsive API
TypeScript
5,911
star
10

universal

Server-side rendering and Prerendering for Angular
TypeScript
4,029
star
11

zone.js

Implements Zones for JavaScript
TypeScript
3,243
star
12

quickstart

Angular QuickStart - source from the documentation
JavaScript
3,128
star
13

angular-phonecat

Tutorial on building an angular application.
JavaScript
3,128
star
14

batarang

AngularJS WebInspector Extension for Chrome
JavaScript
2,444
star
15

material-start

Starter Repository for AngularJS Material
JavaScript
2,214
star
16

universal-starter

Angular Universal starter kit by @AngularClass
TypeScript
2,028
star
17

mobile-toolkit

Tools for building progressive web apps with Angular
JavaScript
1,344
star
18

in-memory-web-api

The code for this project has moved to the angular/angular repo. This repo is now archived.
TypeScript
1,172
star
19

angular.io

Website for the Angular project (see github.com/angular/angular for the project repo)
HTML
1,032
star
20

angular2-seed

TypeScript
1,011
star
21

tsickle

Tsickle β€” TypeScript to Closure Translator
TypeScript
893
star
22

material.angular.io

Docs site for Angular Components
TypeScript
859
star
23

di.js

Dependency Injection Framework for the future generations...
JavaScript
822
star
24

react-native-renderer

Use Angular and React Native to build applications for Android and iOS
TypeScript
789
star
25

dgeni

Flexible JavaScript documentation generator used by AngularJS, Protractor and other JS projects
TypeScript
770
star
26

angular-cn

Chinese localization of angular.io
Pug
761
star
27

vscode-ng-language-service

Angular extension for Visual Studio Code
TypeScript
757
star
28

router

The Angular 1 Component Router
JavaScript
667
star
29

angular-electron

Angular2 + Electron
TypeScript
610
star
30

devkit

549
star
31

bower-material

This repository is used for publishing the AngularJS Material v1.x library
JavaScript
506
star
32

watchtower.js

ES6 Port of Angular.dart change detection code.
JavaScript
410
star
33

preboot

Coordinate transfer of state from server to client view for isomorphic/universal JavaScript web applications
TypeScript
384
star
34

angular-hint

run-time hinting for AngularJS applications
JavaScript
368
star
35

angular-bazel-example

MOVED to the bazel nodejs monorepo πŸ‘‰
TypeScript
350
star
36

builtwith.angularjs.org

builtwith.angularjs.org
HTML
271
star
37

protractor-accessibility-plugin

Runs a set of accessibility audits
JavaScript
263
star
38

angularjs.org

code for angularjs.org site
JavaScript
260
star
39

angular-update-guide

An interactive guide to updating the version of Angular in your apps
TypeScript
245
star
40

webdriver-manager

A binary manager for E2E testing
TypeScript
227
star
41

bower-angular

Bower package for AngularJS
CSS
224
star
42

angular-ja

repository for Japanese localization of angular.io
HTML
208
star
43

ngSocket

WebSocket support for angular
JavaScript
204
star
44

peepcode-tunes

Peepcode's Backbone.js Music Player Reimplemented in AngularJS
JavaScript
204
star
45

clutz

Closure to TypeScript `.d.ts` generator
Java
163
star
46

benchpress

JavaScript
160
star
47

code.angularjs.org

code.angularjs.org
153
star
48

ngcc-validation

Angular Ivy library compatibility validation project
TypeScript
146
star
49

dgeni-packages

A collection of dgeni packages for generating documentation from source code.
JavaScript
143
star
50

bower-angular-route

angular-route bower repo
JavaScript
143
star
51

atscript-playground

A repo to play with AtScript.
JavaScript
141
star
52

bower-angular-animate

Bower package for the AngularJS animation module
JavaScript
137
star
53

protractor-cookbook

Examples for using Protractor in various common scenarios.
TypeScript
130
star
54

diary.js

Flexible logging and profiling library for JavaScript
JavaScript
127
star
55

bower-angular-i18n

internationalization module for AngularJS
JavaScript
125
star
56

closure-demo

TypeScript
114
star
57

ngMigration-Forum

109
star
58

material-adaptive

Adaptive template development with Angular Material
JavaScript
101
star
59

watScript

The next generation JavaScript language that will kill ALL the frameworks!
101
star
60

bower-angular-sanitize

angular-sanitize bower repo
JavaScript
99
star
61

code-of-conduct

A code of conduct for all Angular projects
99
star
62

clang-format

Node repackaging of the clang-format native binary
Python
97
star
63

tactical

Data access library for Angular
TypeScript
93
star
64

bower-angular-resource

angular-resource bower repo
JavaScript
92
star
65

dashboard.angularjs.org

AngularJS Dashboard
JavaScript
89
star
66

angular-jquery-ui

jQueryUI widgets wrapped as angular widgets
JavaScript
88
star
67

bower-angular-mocks

angular-mocks.js bower repo
JavaScript
87
star
68

bower-angular-cookies

angular-cookies bower repo
JavaScript
85
star
69

issue-zero

TypeScript
82
star
70

bower-angular-touch

JavaScript
79
star
71

templating

Templating engine for Angular 2.0
JavaScript
76
star
72

a

Library for annotating ES5
JavaScript
67
star
73

material-icons

Common resources for material design in AngularJS
66
star
74

vladivostok

TypeScript
65
star
75

bower-angular-messages

JavaScript
63
star
76

angular-component-spec

Specification for reusable AngularJS components
61
star
77

ci.angularjs.org

ci.angularjs.org CI server scripts
Shell
60
star
78

projects

github reference application for Angular 2.0
JavaScript
58
star
79

dev-infra

Angular Development Infrastructure
JavaScript
57
star
80

code.material.angularjs.org

Documentation site for AngularJS Material
HTML
50
star
81

material-tools

Tools for AngularJS Material
TypeScript
47
star
82

jasminewd

Adapter for Jasmine-to-WebDriverJS
JavaScript
46
star
83

material-update-tool

Standalone update tool for updating Angular CDK and Material
TypeScript
46
star
84

material-builds

Build snapshots for @angular/material
JavaScript
45
star
85

material2-docs-content

Docs content for @angular/material
HTML
37
star
86

benchpress-tree

A reference implementation of a benchpress deep-tree benchmark as seen in Angular
JavaScript
37
star
87

cdk-builds

Angular CDK builds
JavaScript
37
star
88

router-builds

@angular/router build artifacts
JavaScript
36
star
89

angular-ko

HTML
36
star
90

prophecy

Deferred/Promise for AngularJS 2.0
JavaScript
36
star
91

answers-app

TypeScript
36
star
92

assert

A runtime type assertion library.
JavaScript
35
star
93

ngo

TypeScript
34
star
94

protractor-console-plugin

Checks the browser log after each test for warnings and errors
JavaScript
34
star
95

codelabs

31
star
96

introduction-to-angular

TypeScript
31
star
97

microsites

Master repository for sites on the angular.io subdomains (universal.angular.io, material.angular.io, etc)
HTML
29
star
98

core-builds

@angular/core build artifacts
JavaScript
29
star
99

ngtools-webpack-builds

Build artifacts for @ngtools/webpack
JavaScript
28
star
100

service-worker-builds

Build artifacts for @angular/service-worker
JavaScript
27
star