diff --git a/README.md b/README.md index b2aae4e9..f978ca40 100644 --- a/README.md +++ b/README.md @@ -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) +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: @@ -28,6 +32,7 @@ fast-json-stringify obj x 4,976,369 ops/sec ±1.00% (89 runs sampled) - `Additional Properties` - `Reuse - $ref` - `Long integers` + - `Uglify` - `Acknowledgements` - `License` @@ -319,6 +324,27 @@ const obj = { console.log(stringify(obj)) // '{"id":18446744073709551615}' ``` + +#### 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"}' +``` + ## Acknowledgements diff --git a/bench.js b/bench.js index 8eba4293..c7001fa5 100644 --- a/bench.js +++ b/bench.js @@ -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++) { @@ -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) }) @@ -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') }) @@ -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) }) @@ -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() diff --git a/index.js b/index.js index cd7ba6e0..179069c3 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const fastSafeStringify = require('fast-safe-stringify') +var uglify = null let isLong try { isLong = require('long').isLong @@ -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) } @@ -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 diff --git a/package.json b/package.json index 5ebd8a82..c063a2f9 100644 --- a/package.json +++ b/package.json @@ -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" }, "dependencies": { "fast-safe-stringify": "^1.1.11" diff --git a/test/basic.test.js b/test/basic.test.js index eb4299bd..44725dd1 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -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') }) }