minify.js 2.49 KB
Newer Older
Evan Hahn's avatar
Evan Hahn committed
1 2 3 4
const path = require('path')
const util = require('util')
const childProcess = require('child_process')
const RegPack = require('regpack').RegPack
5
const readSource = require('./read-source')
Evan Hahn's avatar
Evan Hahn committed
6 7 8 9 10 11 12 13 14

const execFile = util.promisify(childProcess.execFile)

const SOURCE_PATH = path.join(__dirname, 'js1k.js')
const BIN_PATH = path.join(__dirname, '..', 'node_modules', '.bin')
const BABEL_MINIFY_PATH = path.join(BIN_PATH, 'minify')
const BABEL_MINIFY_OPTIONS = ['--builtIns', '--booleans', '--mangle', '--infinity', '--flipComparisons', '--mangle.topLevel']

module.exports = async function minify () {
15
  const rawSource = await readSource()
Evan Hahn's avatar
Evan Hahn committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
  const babelResult = await babelMinify()
  const regPackResult = regpackMinify(babelResult)

  console.log()
  console.log('Raw source size: ' + rawSource.length)
  console.log('Babel minify size: ' + babelResult.length)
  console.log('Regpack size: ' + regPackResult.length)

  const results = [rawSource, babelResult, regPackResult]

  return shortest(results).toString('utf8').trim()
}

function shortest (arr) {
  return arr.reduce((result, value) => {
    return result.length < value.length ? result : value
  }, arr[0]).toString('utf8').trim()
}

async function babelMinify () {
  const result = await execFile(BABEL_MINIFY_PATH, [SOURCE_PATH].concat(BABEL_MINIFY_OPTIONS))
  const withoutTrailingSemicolon = result.stdout.replace(/;$/, '')
  return Buffer.from(withoutTrailingSemicolon, 'utf8')
}

function regpackMinify (sourceBuffer) {
  const source = sourceBuffer.toString('utf8')
  const regpack = new RegPack()
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
  /*
  You can try this to try all possible options:

  const packerResults = allPossibleObjects({
    withMath: [true, false],
    crushGainFactor: [0, 1, 2],
    crushLengthFactor: [0, 1],
    crushCopiesFactor: [0, 1],
    crushTiebreakerFactor: [0, 1]
  })
    .map((options) => Object.assign({
      hash2DContext: true,
      contextVariableName: 'c',
      reassignVars: true,
      varsNotReassigned: ['a', 'b', 'c', 'd']
    }, options))
    .map((options) => regpack.runPacker(source, options))
    .reduce((flattened, arr) => flattened.concat(arr), [])
  */
Evan Hahn's avatar
Evan Hahn committed
63
  const packerResults = regpack.runPacker(source, {
64
    withMath: true,
65
    hash2DContext: false,
Evan Hahn's avatar
Evan Hahn committed
66
    reassignVars: true,
67
    varsNotReassigned: ['a', 'b', 'c']
Evan Hahn's avatar
Evan Hahn committed
68 69 70 71 72 73 74
  })
  const resultStrings = packerResults.reduce((resultStrings, packerResult) => {
    const packerResultStrings = packerResult.result.map((r) => r[1])
    return resultStrings.concat(packerResultStrings)
  }, [])
  return Buffer.from(shortest(resultStrings))
}