├── .gitignore ├── images ├── npm.png ├── github.png ├── ChromeWebStore.png └── FirefoxAddOns.png ├── extension ├── icons │ ├── icon16.png │ ├── icon48.png │ └── icon128.png ├── js │ ├── content.js │ ├── github-content.js │ └── npmjs-content.js ├── css │ └── style.css └── manifest.json ├── MIT-LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | builds -------------------------------------------------------------------------------- /images/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/images/npm.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/images/github.png -------------------------------------------------------------------------------- /extension/icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/extension/icons/icon16.png -------------------------------------------------------------------------------- /extension/icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/extension/icons/icon48.png -------------------------------------------------------------------------------- /images/ChromeWebStore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/images/ChromeWebStore.png -------------------------------------------------------------------------------- /images/FirefoxAddOns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/images/FirefoxAddOns.png -------------------------------------------------------------------------------- /extension/icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vicrazumov/js-bundle-size/HEAD/extension/icons/icon128.png -------------------------------------------------------------------------------- /extension/js/content.js: -------------------------------------------------------------------------------- 1 | const getBundlephobiaLink = package => `https://bundlephobia.com/result?p=${package}` 2 | 3 | const sizeTransformer = ({ gzip, size }) => { 4 | const parse = input => parseFloat(input).toFixed(1) 5 | const format = input => input > 1048576 6 | ? `${parse(input / 1048576)} MB` : input > 1024 7 | ? `${parse(input / 1024)} KB` : `${input} B` 8 | 9 | return { 10 | gzip: format(gzip), 11 | size: format(size), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /extension/css/style.css: -------------------------------------------------------------------------------- 1 | .jsbs-github-container { 2 | display: flex; 3 | margin: 6px 0; 4 | } 5 | 6 | .jsbs-github-container a { 7 | text-decoration: none !important; 8 | } 9 | 10 | .jsbs-badge-container { 11 | display: flex; 12 | margin-right: 4px; 13 | } 14 | 15 | .jsbs-badge-label { 16 | padding: 4px; 17 | font-size: 10px; 18 | color:white; 19 | background-color: grey; 20 | border-radius:5px 0px 0px 5px; 21 | } 22 | 23 | .jsbs-badge-value { 24 | font-size: 10px; 25 | font-weight: bold; 26 | color: black; 27 | background-color: #f6e100; 28 | border-radius:0px 5px 5px 0px; 29 | padding: 4px; 30 | } -------------------------------------------------------------------------------- /extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Javascript Bundle Size", 4 | "author": "Viktor Razumov", 5 | "description": "Automatically adds javascript bundle size data to npm and github project pages", 6 | "homepage_url": "https://github.com/vicrazumov/js-bundle-size", 7 | "version": "0.1.0", 8 | "content_scripts": [{ 9 | "css": ["css/style.css"], 10 | "js": [ 11 | "js/content.js", 12 | "js/github-content.js" 13 | ], 14 | "matches": ["https://github.com/*/*"] 15 | }, 16 | { 17 | "css": ["css/style.css"], 18 | "js": [ 19 | "js/content.js", 20 | "js/npmjs-content.js" 21 | ], 22 | "matches": ["https://www.npmjs.com/package/*"] 23 | }], 24 | "icons": { 25 | "16": "/icons/icon16.png", 26 | "48": "icons/icon48.png", 27 | "128": "icons/icon128.png" 28 | }, 29 | "permissions": ["https://bundlephobia.com/api/size"] 30 | } 31 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Viktor Razumov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Javascript Bundle Size Cross-Browser Extension 2 | 3 | Frontend developers frequently face the problem of choosing a proper library with a minimal footprint. [bundlephobia](https://bundlephobia.com) helps greatly by building bundles and providing their sizes minified and gzipped. 4 | 5 | This cross-browser extension takes the next step, automatically requesting this data and adding it to: 6 | * npm as a part of the right sidebar 7 | 8 | ![npm](https://github.com/vicrazumov/js-bundle-size/raw/master/images/npm.png) 9 | 10 | * github at the top of the readme page 11 | 12 | ![github](https://github.com/vicrazumov/js-bundle-size/raw/master/images/github.png) 13 | 14 | Tested in [Google Chrome 71](https://chrome.google.com/webstore/detail/javascript-bundle-size/aojdnjnhhjmokccbelfdocgiedioienh/) and [Mozilla Firefox 64.0.2](https://addons.mozilla.org/ru/firefox/addon/javascript-bundle-size/) on macOS 10.14. 15 | 16 | ## Notes 17 | Please note, that Chrome doesn't require the `permissions` property in `manifest.json`, whereas Firefox doesn't allow `fetch` calls without that (even with mentioning the npm and github hosts explicitly). 18 | 19 | ## Contribution 20 | Contributors' help is welcome, especially in bringing this to Edge, Opera, Safari and, maybe, other browsers. 21 | -------------------------------------------------------------------------------- /extension/js/github-content.js: -------------------------------------------------------------------------------- 1 | const getPackageNameFromGithubBody = bodyText => { 2 | if (!bodyText) return 3 | 4 | const npmOrYarnMatch = bodyText.match(/((npm i\w*)( )(-[a-zA-Z-]+\s)*([a-z0-9-\.\_\@\/]+))|(yarn add ([a-z0-9-\.\_\@\/]+))/i) 5 | return npmOrYarnMatch && (npmOrYarnMatch[7] || npmOrYarnMatch[5]) 6 | } 7 | 8 | const githubTransformer = npmPackage => ({ gzip, size }) => { 9 | const badgeGenerator = (href, name, value) => `
${name}
${value}
` 10 | 11 | const article = document.querySelector('article.markdown-body') 12 | if (!article) return 13 | 14 | const link = getBundlephobiaLink(npmPackage) 15 | const div = document.createElement('div') 16 | div.className = 'jsbs-github-container' 17 | div.innerHTML = badgeGenerator(link, 'minified', size) 18 | + badgeGenerator(link, 'minified + gzipped', gzip) 19 | 20 | article.insertBefore(div, article.firstChild) 21 | } 22 | 23 | const main = () => { 24 | const package = getPackageNameFromGithubBody(document.querySelector('body').innerHTML) 25 | if (!package) return 26 | 27 | const transformer = githubTransformer(package) 28 | 29 | fetch(`https://bundlephobia.com/api/size?package=${package}`) 30 | .then(response => response.json()) 31 | .then(sizeTransformer) 32 | .then(transformer) 33 | .catch(err => console.warn('Retrieving JS bundle size failed', { err })) 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /extension/js/npmjs-content.js: -------------------------------------------------------------------------------- 1 | const getPackageNameFromNpm = url => { 2 | if (!url) return 3 | 4 | const match = url.match(/(https:\/\/www.npmjs.com\/package\/)(.+)/i) 5 | return match && match[2] 6 | } 7 | 8 | const npmTransformer = npmPackage => ({ gzip, size }) => { 9 | const npmDivClassList = 'dib w-50 bb b--black-10 pr2' 10 | const npmInnerHTMLGenerator = (header, package, value) => `

${header}

${value}

` 11 | 12 | const sidebarDivs = document.querySelectorAll('div.pr2') 13 | if (!sidebarDivs.length) return 14 | 15 | const lastElement = sidebarDivs[sidebarDivs.length - 1] 16 | const container = lastElement.parentNode 17 | const sizeDiv = document.createElement('div') 18 | container.insertBefore(sizeDiv, lastElement) 19 | sizeDiv.classList = npmDivClassList 20 | sizeDiv.innerHTML = npmInnerHTMLGenerator('minified', npmPackage, size) 21 | 22 | const gzipDiv = document.createElement('div') 23 | container.insertBefore(gzipDiv, lastElement) 24 | gzipDiv.classList = npmDivClassList 25 | gzipDiv.innerHTML = npmInnerHTMLGenerator('minified + gzipped', npmPackage, gzip) 26 | } 27 | 28 | const main = () => { 29 | const package = getPackageNameFromNpm(window.location.href) 30 | if (!package) return 31 | 32 | const transformer = npmTransformer(package) 33 | 34 | fetch(`https://bundlephobia.com/api/size?package=${package}`) 35 | .then(response => response.json()) 36 | .then(sizeTransformer) 37 | .then(transformer) 38 | .catch(err => console.warn('Retrieving JS bundle size failed', { err })) 39 | } 40 | 41 | main() 42 | --------------------------------------------------------------------------------