Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat): closure compiler for minification #525

Closed
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ export interface TsdxOptions {
writeMeta?: boolean;
// Only transpile, do not type check (makes compilation faster)
transpileOnly?: boolean;
// EXPERIMENTAL: Use closure compiler to minify production bundle instead of terser
closureCompiler?: boolean;
}
```

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"templates"
],
"dependencies": {
"@ampproject/rollup-plugin-closure-compiler": "^0.22.2",
"@babel/core": "^7.4.4",
"@babel/helper-module-imports": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.4.4",
Expand Down
29 changes: 17 additions & 12 deletions src/createRollupConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { safeVariableName, safePackageName, external } from './utils';
import { paths } from './constants';
import { RollupOptions } from 'rollup';
import { terser } from 'rollup-plugin-terser';
import closureCompiler from '@ampproject/rollup-plugin-closure-compiler';
import { DEFAULT_EXTENSIONS } from '@babel/core';
// import babel from 'rollup-plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
Expand Down Expand Up @@ -195,18 +196,22 @@ export async function createRollupConfig(
// printInfo: false,
// }),
shouldMinify &&
terser({
sourcemap: true,
output: { comments: false },
compress: {
keep_infinity: true,
pure_getters: true,
passes: 10,
},
ecma: 5,
toplevel: opts.format === 'cjs',
warnings: true,
}),
(opts.closureCompiler
? closureCompiler({
compilation_level: 'SIMPLE_OPTIMIZATIONS',
})
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
: terser({
sourcemap: true,
output: { comments: false },
compress: {
keep_infinity: true,
pure_getters: true,
passes: 10,
},
ecma: 5,
toplevel: opts.format === 'cjs',
warnings: true,
})),
],
};
}
1 change: 1 addition & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ declare module '@babel/core' {
}

// Rollup plugins
declare module '@ampproject/rollup-plugin-closure-compiler';
declare module '@jaredpalmer/rollup-plugin-preserve-shebang';
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
declare module 'rollup-plugin-babel';
declare module 'rollup-plugin-size-snapshot';
Expand Down
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@ prog
.example('build --tsconfig ./tsconfig.foo.json')
.option('--transpileOnly', 'Skip type checking')
.example('build --transpileOnly')
.option(
'--closureCompiler',
'EXPERIMENTAL: Use closure compiler to minify production bundle instead of terser'
)
.example('build --env production --closureCompiler')
.option(
'--extractErrors',
'Extract errors to ./errors/codes.json and provide a url for decoding.'
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export interface TsdxOptions extends SharedOpts {
writeMeta?: boolean;
// Only transpile, do not type check (makes compilation faster)
transpileOnly?: boolean;
// EXPERIMENTAL: Use closure compiler to minify production bundle instead of terser
closureCompiler?: boolean;
}

export interface PackageJson {
Expand Down
7 changes: 0 additions & 7 deletions test/fixtures/build-withConfig/errors/ErrorDev.js

This file was deleted.

14 changes: 0 additions & 14 deletions test/fixtures/build-withConfig/errors/ErrorProd.js

This file was deleted.

4 changes: 0 additions & 4 deletions test/fixtures/build-withConfig/errors/codes.json

This file was deleted.

2 changes: 1 addition & 1 deletion test/fixtures/build-withConfig/src/foo.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const foo = () => 'bar';
export const split = (str: string) => str.split('');
10 changes: 5 additions & 5 deletions test/fixtures/build-withConfig/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import invariant from 'tiny-invariant';
import warning from 'tiny-warning';
invariant(true, 'error occurred! o no');
warning(false, 'warning - water is wet');
export { foo } from './foo';
import { split } from './foo';
ambroseus marked this conversation as resolved.
Show resolved Hide resolved

export const sum = (a: number, b: number) => {
if ('development' === process.env.NODE_ENV) {
console.log('fuck');
}
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
return a + b;
};

const bar = split('bar');

export const signature = `${split('bar').join('')} ${sum(bar.length, -3)}`;
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 19 additions & 0 deletions test/fixtures/build-withConfig/tsdx.config.closure-advanced.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const closureCompiler = require('@ampproject/rollup-plugin-closure-compiler');

const closureCompilerPlugin = closureCompiler({
compilation_level: 'ADVANCED_OPTIMIZATIONS',
});

module.exports = {
rollup(config) {
config.plugins = config.plugins.map(plugin => {
// override closure compiler plugin's default config
if (plugin && plugin.name === closureCompilerPlugin.name) {
return closureCompilerPlugin;
}
return plugin;
});

return config;
},
};
22 changes: 0 additions & 22 deletions test/fixtures/build-withConfig/tsdx.config.js

This file was deleted.

90 changes: 90 additions & 0 deletions test/tests/tsdx-build-closure-compiler.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
agilgur5 marked this conversation as resolved.
Show resolved Hide resolved
* @jest-environment node
*/

const shell = require('shelljs');
const util = require('../fixtures/util');

shell.config.silent = false;

const grep = (pattern, file) => {
const output = shell.grep(pattern, file);
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
const grepOutput = output.stdout.replace(`\n`, ``);
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
return grepOutput.length > 0;
};

const stageName = 'stage-build-closure-compiler';

describe('tsdx build with closure compiler default options', () => {
beforeAll(() => {
util.teardownStage(stageName);
});

it('should minify bundle with default options', () => {
util.setupStageWithFixture(stageName, 'build-withConfig');

let output = shell.exec(
'node ../dist/index.js build --env production --closureCompiler'
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
);
expect(output.code).toBe(0);

expect(shell.test('-f', 'dist/index.js')).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.cjs.development.js')
).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.cjs.production.min.js')
).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.esm.production.min.js')
).toBeTruthy();

expect(shell.test('-f', 'dist/index.d.ts')).toBeTruthy();

const lib = require(`../../${stageName}/dist`);
expect(lib.signature).toBe('bar 0');

expect(
grep(
'exports.signature=signature',
'dist/build-withconfig.cjs.production.min.js'
)
).toBeTruthy();
ambroseus marked this conversation as resolved.
Show resolved Hide resolved
});
ambroseus marked this conversation as resolved.
Show resolved Hide resolved

it('should minify bundle with advanced options', () => {
util.setupStageWithFixture(stageName, 'build-withConfig');
shell.mv('-f', 'tsdx.config.closure-advanced.js', 'tsdx.config.js');

let output = shell.exec(
'node ../dist/index.js build --env production --closureCompiler'
);
expect(output.code).toBe(0);

expect(shell.test('-f', 'dist/index.js')).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.cjs.development.js')
).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.cjs.production.min.js')
).toBeTruthy();
expect(
shell.test('-f', 'dist/build-withconfig.esm.production.min.js')
).toBeTruthy();

expect(shell.test('-f', 'dist/index.d.ts')).toBeTruthy();

const lib = require(`../../${stageName}/dist`);
expect(lib.signature).toBe('bar 0');

// closure compiler with advanced optimization level
// minifies bundle with `signature="bar 0"`
expect(
grep('bar 0', 'dist/build-withconfig.cjs.production.min.js')
).toBeTruthy();
});
ambroseus marked this conversation as resolved.
Show resolved Hide resolved

afterEach(() => {
util.teardownStage(stageName);
});
});
Loading