Skip to content

Add ability to uglify generated code #36

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

Merged
merged 1 commit into from
May 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ advantages reduces on large payloads.
Benchmarks:

```
JSON.stringify array x 3,679 ops/sec ±1.01% (85 runs sampled)
fast-json-stringify array x 4,618 ops/sec ±1.64% (87 runs sampled)
JSON.stringify long string x 13,303 ops/sec ±1.01% (89 runs sampled)
fast-json-stringify long string x 13,489 ops/sec ±0.88% (90 runs sampled)
JSON.stringify short string x 4,974,749 ops/sec ±1.14% (86 runs sampled)
fast-json-stringify short string x 11,030,700 ops/sec ±0.82% (89 runs sampled)
JSON.stringify obj x 1,774,593 ops/sec ±1.07% (90 runs sampled)
fast-json-stringify obj x 4,976,369 ops/sec ±1.00% (89 runs sampled)
JSON.stringify array x 3,288 ops/sec ±5.18% (82 runs sampled)
fast-json-stringify array x 1,813 ops/sec ±10.21% (71 runs sampled)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is worse, but that's #15, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we must definitely fix that issue :S

fast-json-stringify-uglified array x 2,106 ops/sec ±3.23% (83 runs sampled)
JSON.stringify long string x 12,933 ops/sec ±1.27% (87 runs sampled)
fast-json-stringify long string x 12,221 ops/sec ±3.31% (84 runs sampled)
fast-json-stringify-uglified long string x 13,256 ops/sec ±0.95% (92 runs sampled)
JSON.stringify short string x 4,878,641 ops/sec ±1.14% (90 runs sampled)
fast-json-stringify short string x 11,649,100 ops/sec ±0.98% (91 runs sampled)
fast-json-stringify-uglified short string x 11,877,661 ops/sec ±0.91% (90 runs sampled)
JSON.stringify obj x 1,705,377 ops/sec ±2.61% (87 runs sampled)
fast-json-stringify obj x 2,268,915 ops/sec ±1.39% (90 runs sampled)
fast-json-stringify-uglified obj x 2,243,341 ops/sec ±1.11% (89 runs sampled)
```

#### Table of contents:
Expand All @@ -28,6 +32,7 @@ fast-json-stringify obj x 4,976,369 ops/sec ±1.00% (89 runs sampled)
- <a href="#additionalProperties">`Additional Properties`</a>
- <a href="#ref">`Reuse - $ref`</a>
- <a href="#long">`Long integers`</a>
- <a href="#uglify">`Uglify`</a>
- <a href="#acknowledgements">`Acknowledgements`</a>
- <a href="#license">`License`</a>

Expand Down Expand Up @@ -319,6 +324,27 @@ const obj = {
console.log(stringify(obj)) // '{"id":18446744073709551615}'
```

<a name="uglify"></a>
#### Uglify
If you want to squeeze a little bit more performance out of the serialisation, at the cost of readability in the generated code, you can pass `uglify: true` as an option.
Note that you have to manually install `uglify-es` in order for it to work. Only version 3 is supported.
Example:
```javascript

const stringify = fastJson({
title: 'Example Schema',
type: 'object',
properties: {
id: {
type: 'integer'
}
}
}, { uglify: true })

// stringify is now minified code
console.log(stringify({ some: 'object' })) // '{"some":"object"}'
```

<a name="acknowledgements"></a>
## Acknowledgements

Expand Down
19 changes: 19 additions & 0 deletions bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ const obj = {
const multiArray = []

const stringify = require('.')(schema)
const stringifyUgly = require('.')(schema, { uglify: true })
const stringifyArray = require('.')(arraySchema)
const stringifyArrayUgly = require('.')(arraySchema, { uglify: true })
const stringifyString = require('.')({ type: 'string' })
const stringifyStringUgly = require('.')({ type: 'string', uglify: true })
var str = ''

for (var i = 0; i < 10000; i++) {
Expand All @@ -61,6 +64,10 @@ suite.add('fast-json-stringify array', function () {
stringifyArray(multiArray)
})

suite.add('fast-json-stringify-uglified array', function () {
stringifyArrayUgly(multiArray)
})

suite.add('JSON.stringify long string', function () {
JSON.stringify(str)
})
Expand All @@ -69,6 +76,10 @@ suite.add('fast-json-stringify long string', function () {
stringifyString(str)
})

suite.add('fast-json-stringify-uglified long string', function () {
stringifyStringUgly(str)
})

suite.add('JSON.stringify short string', function () {
JSON.stringify('hello world')
})
Expand All @@ -77,6 +88,10 @@ suite.add('fast-json-stringify short string', function () {
stringifyString('hello world')
})

suite.add('fast-json-stringify-uglified short string', function () {
stringifyStringUgly('hello world')
})

suite.add('JSON.stringify obj', function () {
JSON.stringify(obj)
})
Expand All @@ -85,6 +100,10 @@ suite.add('fast-json-stringify obj', function () {
stringify(obj)
})

suite.add('fast-json-stringify-uglified obj', function () {
stringifyUgly(obj)
})

suite.on('cycle', cycle)

suite.run()
Expand Down
38 changes: 38 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const fastSafeStringify = require('fast-safe-stringify')

var uglify = null
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems inconsistent between let and var in the code base. Which do you want?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var is better since is a little faster than let, thanks! :)

let isLong
try {
isLong = require('long').isLong
Expand Down Expand Up @@ -74,6 +75,11 @@ function build (schema, options) {
;
return ${main}
`

if (options.uglify) {
code = uglifyCode(code)
}

if (hasAdditionalPropertiesTrue(schema)) {
return (new Function('fastSafeStringify', code))(fastSafeStringify)
}
Expand Down Expand Up @@ -457,4 +463,36 @@ function nested (laterCode, name, key, schema, externalSchema, fullSchema) {
}
}

function uglifyCode (code) {
if (!uglify) {
loadUglify()
}

const uglified = uglify.minify(code, { parse: { bare_returns: true } })

if (uglified.error) {
throw uglified.error
}

return uglified.code
}

function loadUglify () {
try {
uglify = require('uglify-es')
const uglifyVersion = require('uglify-es/package.json').version

if (uglifyVersion[0] !== '3') {
throw new Error('Only version 3 of uglify-es is supported')
}
} catch (e) {
uglify = null
if (e.code === 'MODULE_NOT_FOUND') {
throw new Error('In order to use uglify, you have to manually install `uglify-es`')
}

throw e
}
}

module.exports = build
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"long": "^3.2.0",
"pre-commit": "^1.1.3",
"standard": "^10.0.0",
"tap": "^10.3.0"
"tap": "^10.3.0",
"uglify-es": "^3.0.9"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the es variant to support const in the code, btw

},
"dependencies": {
"fast-safe-stringify": "^1.1.11"
Expand Down
6 changes: 5 additions & 1 deletion test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ const build = require('..')

function buildTest (schema, toStringify) {
test(`render a ${schema.title} as JSON`, (t) => {
t.plan(3)
t.plan(5)

const validate = validator(schema)
const stringify = build(schema)
const stringifyUgly = build(schema, {uglify: true})
const output = stringify(toStringify)
const outputUglify = stringifyUgly(toStringify)

t.deepEqual(JSON.parse(output), toStringify)
t.deepEqual(JSON.parse(outputUglify), toStringify)
t.equal(output, JSON.stringify(toStringify))
t.equal(outputUglify, JSON.stringify(toStringify))
t.ok(validate(JSON.parse(output)), 'valid schema')
})
}
Expand Down