├── .gitignore ├── .travis.yml ├── appveyor.yml ├── LICENSE.md ├── CHANGELOG.md ├── package.json ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.nyc_output 3 | /test/cache 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "9" 5 | - "8" 6 | - "6" 7 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: "9" 4 | - nodejs_version: "8" 5 | - nodejs_version: "6" 6 | 7 | platform: 8 | - x64 9 | 10 | install: 11 | - ps: Install-Product node $env:nodejs_version $env:platform 12 | - npm config set spin false 13 | - npm install 14 | 15 | test_script: 16 | - npm test 17 | 18 | matrix: 19 | fast_finish: true 20 | 21 | build: off 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) npm, Inc. 4 | 5 | Permission to use, copy, modify, and/or distribute this software for 6 | any purpose with or without fee is hereby granted, provided that the 7 | above copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE COPYRIGHT HOLDER DISCLAIMS 10 | ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 14 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 16 | USE OR PERFORMANCE OF THIS SOFTWARE. 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [1.1.1](https://github.com/npm/do-you-even-lift/compare/v1.1.0...v1.1.1) (2020-03-24) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * remove old weall* stuff ([4279bff](https://github.com/npm/do-you-even-lift/commit/4279bff)) 12 | 13 | 14 | 15 | 16 | # [1.1.0](https://github.com/npm/do-you-even-lift/compare/v1.0.0...v1.1.0) (2018-04-30) 17 | 18 | 19 | ### Features 20 | 21 | * **bundle:** report which bundler succeeded ([5d5f94a](https://github.com/npm/do-you-even-lift/commit/5d5f94a)) 22 | * **error:** better reporting of fallthrough errors ([1df5dce](https://github.com/npm/do-you-even-lift/commit/1df5dce)) 23 | 24 | 25 | 26 | 27 | # 1.0.0 (2018-04-26) 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "do-you-even-lift", 3 | "version": "1.1.1", 4 | "description": "Figure out an estimate of how heavy a particular npm package might be in various compression configurations", 5 | "main": "index.js", 6 | "files": [ 7 | "*.js", 8 | "lib" 9 | ], 10 | "scripts": { 11 | "prerelease": "npm t", 12 | "postrelease": "npm publish && git push --follow-tags", 13 | "pretest": "standard", 14 | "release": "standard-version -s", 15 | "test": "tap -J --coverage test/*.js" 16 | }, 17 | "repository": "https://github.com/npm/do-you-even-lift", 18 | "keywords": [ 19 | "npm", 20 | "bundle", 21 | "web", 22 | "rollup", 23 | "browserify" 24 | ], 25 | "author": "Kat Marchán ", 26 | "license": "ISC", 27 | "dependencies": { 28 | "babel-core": "^6.26.3", 29 | "babel-preset-minify": "^0.4.0", 30 | "browserify": "^16.2.0", 31 | "figgy-pudding": "^3.1.0", 32 | "glob": "^7.1.2", 33 | "pacote": "^8.1.1", 34 | "rollup": "^0.58.2", 35 | "rollup-plugin-commonjs": "^9.1.0", 36 | "unique-filename": "^1.1.0" 37 | }, 38 | "devDependencies": { 39 | "standard": "^11.0.1", 40 | "standard-version": "^4.3.0", 41 | "tap": "^11.1.3" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # do-you-even-lift [![npm version](https://img.shields.io/npm/v/do-you-even-lift.svg)](https://npm.im/do-you-even-lift) [![license](https://img.shields.io/npm/l/do-you-even-lift.svg)](https://npm.im/do-you-even-lift) [![Travis](https://img.shields.io/travis/npm/do-you-even-lift.svg)](https://travis-ci.org/npm/do-you-even-lift) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/do-you-even-lift?svg=true)](https://ci.appveyor.com/project/npm/do-you-even-lift) [![Coverage Status](https://coveralls.io/repos/github/npm/do-you-even-lift/badge.svg?branch=latest)](https://coveralls.io/github/npm/do-you-even-lift?branch=latest) 2 | 3 | [`do-you-even-lift`](https://github.com/npm/do-you-even-lift) is a Node.js 4 | library for calculating how big a specific package might be once bundled and 5 | compressed. It's built on top of [`pacote`](https://npm.im/pacote) and so will 6 | accept any valid package specifier for extraction. 7 | 8 | ## Install 9 | 10 | `$ npm install do-you-even-lift` 11 | 12 | ### Example 13 | 14 | ```javascript 15 | const liftMeBro = require('do-you-even-lift') 16 | 17 | liftMeBro('react').then(console.log) 18 | // => 19 | { 20 | unpackedSize: 119169, 21 | bundleSize: 55615, 22 | minifiedBundleSize: 19747, 23 | gzippedBundleSize: 15783, 24 | gzippedMinifiedBundleSize: 7090, 25 | bundleTime: 1242 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const util = require('util') 4 | 5 | const babel = require('babel-core') 6 | const browserify = require('browserify') 7 | const cjsResolve = require('rollup-plugin-commonjs') 8 | // const figgyPudding = require('figgy-pudding') 9 | const fs = require('fs') 10 | const glob = util.promisify(require('glob')) 11 | const os = require('os') 12 | const pacote = require('pacote') 13 | const path = require('path') 14 | const rimraf = util.promisify(require('rimraf')) 15 | const rollup = require('rollup') 16 | const uniqueFilename = require('unique-filename') 17 | const zlib = require('zlib') 18 | 19 | const gzipAsync = util.promisify(zlib.gzip) 20 | const statAsync = util.promisify(fs.stat) 21 | 22 | module.exports = pkgStats 23 | 24 | // const LiftConfig = figgyPudding({ 25 | // tmpdir: {} 26 | // }) 27 | 28 | async function pkgStats (pkg, opts) { 29 | // opts = LiftConfig(opts) 30 | opts = opts || {} 31 | const stats = {} 32 | const pkgDir = uniqueFilename(opts.tmpdir || os.tmpdir()) 33 | const startTime = Date.now() 34 | try { 35 | await pacote.extract(pkg, pkgDir, opts) 36 | stats.unpackedSize = await getSize('**/*', pkgDir) 37 | const bundle = await bundlePackage(pkgDir) 38 | stats.bundler = bundle.bundler 39 | stats.bundleSize = Buffer.from(bundle.code, 'utf8').length 40 | const minifyResult = babel.transform(bundle.code, { 41 | presets: ['minify'] 42 | }) 43 | const minified = Buffer.from(minifyResult.code, 'utf8') 44 | stats.minifiedBundleSize = minified.length 45 | stats.gzippedBundleSize = (await gzipAsync(bundle.code)).length 46 | stats.gzippedMinifiedBundleSize = (await gzipAsync(minified)).length 47 | } finally { 48 | await rimraf(pkgDir) 49 | } 50 | stats.bundleTime = Date.now() - startTime 51 | return stats 52 | } 53 | 54 | async function getSize (str, cwd) { 55 | const files = await glob(str, {cwd}) 56 | const stats = await Promise.all(files.map(f => statAsync(path.join(cwd, f)))) 57 | return stats.reduce((acc, stat) => { 58 | if (stat.isFile()) { 59 | return acc + stat.size 60 | } else { 61 | return acc 62 | } 63 | }, 0) 64 | } 65 | 66 | async function bundlePackage (pkgDir) { 67 | const pkgJson = require(path.join(pkgDir, 'package.json')) 68 | const entry = path.join(pkgDir, pkgJson.main || pkgJson.module || 'index.js') 69 | try { 70 | return Object.assign(await (await rollup.rollup({ 71 | input: entry, 72 | onwarn: () => {}, 73 | plugins: [ 74 | cjsResolve({ 75 | ignoreGlobal: false, 76 | sourceMap: true, 77 | exclude: ['node_modules/**'] // no deps -- just this one 78 | }) 79 | ] 80 | })).generate({name: pkgJson.name, format: 'umd'}), { 81 | bundler: 'rollup' 82 | }) 83 | } catch (rollupError) { 84 | const b = browserify(entry, { 85 | bare: true, 86 | bundleExternal: false, 87 | ignoreMissing: true 88 | }) 89 | try { 90 | return await new Promise((resolve, reject) => { 91 | b.bundle((err, buf) => { 92 | if (err) { 93 | reject(err) 94 | } else { 95 | resolve({code: buf, map: '', bundler: 'browserify'}) 96 | } 97 | }) 98 | }) 99 | } catch (browserifyError) { 100 | throw Object.assign( 101 | new Error( 102 | `Bundle could not be built. All bundlers failed.\nRollup Error: ${rollupError.message}\nBrowserify Error: ${browserifyError.message}` 103 | ), { 104 | browserifyError, 105 | rollupError 106 | } 107 | ) 108 | } 109 | } 110 | } 111 | --------------------------------------------------------------------------------