{"id":17205444,"url":"https://github.com/valentinh/bundlelove","last_synced_at":"2025-03-25T10:25:31.997Z","repository":{"id":66077400,"uuid":"201128069","full_name":"ValentinH/bundlelove","owner":"ValentinH","description":"A clone of bundlephobia.com using create-react-app and serverless","archived":false,"fork":false,"pushed_at":"2019-08-17T20:49:50.000Z","size":1130,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-30T09:41:44.969Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://bundlelove.now.sh","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ValentinH.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-07T21:06:16.000Z","updated_at":"2019-11-07T09:57:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"263430bc-af3d-4906-bc56-5b76dcba3d8d","html_url":"https://github.com/ValentinH/bundlelove","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ValentinH%2Fbundlelove","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ValentinH%2Fbundlelove/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ValentinH%2Fbundlelove/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ValentinH%2Fbundlelove/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ValentinH","download_url":"https://codeload.github.com/ValentinH/bundlelove/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245442440,"owners_count":20616017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T02:25:21.607Z","updated_at":"2025-03-25T10:25:31.980Z","avatar_url":"https://github.com/ValentinH.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bundlelove\n\nA clone of the awesome [bundlephobia.com](https://bundlephobia.com).\n\nThis application is split in two parts:\n\n- a react application using [create-react-app](https://create-react-app.dev) (in the `app` folder)\n- an express api served as an AWS lambda using [serverless](https://serverless.com/framework/docs/) (in the `api` folder)\n\n## Quick start\n\n```sh\n# install the dependencies\nyarn install\n# run both the react app and the local api\nyarn dev\n```\n\n## react application (app folder)\n\nThe first page of the application is the landing page (https://bundlelove.now.sh). It simply provides a search autocomplete input\nallowing the user to search for npm packages.\n\nThen, the main page is the result page (https://bundlelove.now.sh/result?p=react-easy-crop). It’s built on four components:\n\n- the search input (shared with the landing page)\n- the Stats card that shows the \"minified\" and \"minified + gzip\" sizes along with the estimated download times for 2G and 3G.\n  Hovering a time value will highlight it with an animation which duration matches the value.\n- the History card that shows a graph presenting the sizes of the last 3 versions plus the previous major one (if there is one).\n  Clicking a bar will go to the corresponding version result page.\n- the Composition card that shows a treemap presenting the size of each dependency of the module. Clicking a dependency rectangle\n  will open the corresponding result page in a new tab.\n\n### scripts\n\n- `start` starts the app on the 3000 port.\n- `test` runs the unit and integration tests.\n- `build` generates the production version of the app.\n- `deploy` deploys the application to the production target of now.sh.\n- `analyze` analyze the bundle size and open the `source-map-explorer` ui.\n\n### built with\n\n- [typescript](https://www.typescriptlang.org) for static type-checking\n- [material-ui](https://material-ui.com) for most of the UI components and writing the styles\n- [react-router](https://reacttraining.com/react-router/web/guides/quick-start) for routing\n- [jest](https://jestjs.io) for running the unit and integration tests\n- [react-testing-library](https://testing-library.com/docs/react-testing-library/intro) for testing the components\n- [ky](https://github.com/sindresorhus/ky) for the HTTP requests\n- [downshift](https://github.com/downshift-js/downshift) for the packages autocomplete component\n- [npms.io search api](https://api-docs.npms.io) for the packages autocomplete data\n- [d3-hierarchy](https://github.com/d3/d3-hierarchy) for generating the composition treemap\n\n## express api (api folder)\n\nThis api is responsible for providing the package information.\nIt mostly uses [package-build-stats](https://github.com/pastelsky/package-build-stats) to compute the package\nsizes (this is the module powering bundlephobia's backend) and the [yarn registry](https://registry.yarnpkg.com)\nto retrieve the package metadata.\n\nAs computing the sizes is quite slow, I've added a DynamoDB database to cache the previously computed data.\n\n### endpoints\n\n`GET /stats?name=react\u0026version=16.0.0`:\n\nComputes the stats for the given package version (if version is omitted it uses the latest).\n\n`GET /history?name=react`:\n\nComputes the sizes for the 3 latest versions plus the previous major one (if it exists).\n\n### scripts\n\n- `start` starts the api on the 3001 port using serverless (you need to run `serverless login` first)\n- `dev` starts the api on the 3001 port without serverless (thus without the cache database)\n- `test` runs the unit tests.\n- `deploy:dev` deploys the api and the database to the dev environment on AWS\n- `deploy:prod` deploys the api and the database to the production environment on AWS\n\n### built with\n\n- [serverless](https://serverless.com/framework/docs/) to deploy the api and its database to AWS\n- [serverless-offline](https://www.npmjs.com/package/serverless-offline) to run the api locally\n- [package-build-stats](https://github.com/pastelsky/package-build-stats) to compute the package sizes (this is the module powering bundlephobia's backend)\n- [yarn registry](https://registry.yarnpkg.com) to retrieve the package information\n- [pkg-versions](https://github.com/sindresorhus/pkg-versions) to retrieve all the versions of a package\n- [got](https://github.com/sindresorhus/got) for the HTTP requests\n- [aws-sdk](https://www.npmjs.com/package/aws-sdk) to query the DynamoDB database\n\n### Lighthouse report\n\n![image](https://user-images.githubusercontent.com/2678610/63210526-cc5eea80-c0ef-11e9-9ea2-846ff6a5ce1e.png)\n\nI've addressed all the lighthouse recommendations that made sense to me. Here are the main ones:\n\n- using [webfontloader](https://github.com/typekit/webfontloader) to avoid blocking the rendering while fonts are loading.\n- using `React.lazy` and `Suspense` to code-split the History and Composition components in order to improve the initial rendering time.\n- configure the caching policy of `now.sh` to let the user's browser cache the static resources.\n- adding `preconnect` links for the main resources (Googlefont and the AWS API).\n\nWhat's remaining but that I'm not willing to change now:\n\n1. **Performance**: have smaller JS bundles (I believe I'm already using quite a small amount of JS for this React app).\n1. **Accessibility**: have a higher contrast-ratio on the red texts (primary color) and some texts on the composition treemap.\n1. **Best practices**: -\n1. **SEO**: Page is blocked from indexing (indeed, as this project is private, indexing is blocked on purpose via robots.txt).\n\n## end-to-end tests\n\nI've written a few end-to-end tests using [Cypress](https://www.cypress.io). The goal is to ensure that the app\nand the api work well together. It is run as a last step of the CI/CD pipeline (see below).\n\nYou can see the UI output by running this command in the root folder:\n\n```sh\nyarn start\nyarn cy:open\n```\n\n## CI/CD pipeline\n\nIn order to automatically deploy the application, I've set up this [circleci](https://circleci.com) workflow:\n![image](https://user-images.githubusercontent.com/2678610/63109933-8fc5ae80-bf8a-11e9-8b4f-b77d6babdc10.png)\n\nIt contains 3 jobs:\n\n- `app`: run the jest tests and deploy the react application to [now.sh](http://now.sh)\n- `api`: run the jest tests and deploy the express api and the database to AWS lambda\n- `e2e`: run the cypress tests directly on the production app (https://bundlelove.now.sh) once the 2 other jobs are completed.\n\n## Limitations\n\n### Features\n\nTwo nice features of Bundlephobia that could be implemented in this app are:\n\n- the \"Similar packages\" section that lets the user find packages offering similar functionalities to the currently viewed package\n- the \"Scan a package.json\" page that lets you upload the package.json of any project and see all dependencies costs at a glance\n\n### CI/CD pipeline\n\nThe pipeline implemented in this project is a simple demo using CircleCI to deploy all the components of the application.\nRunning the e2e tests once everything is deployed won't prevent us from breaking the production, it will only alert if\nsomething went wrong. As an improvement, we could imagine deploying both the app and the api to a staging environment, run the e2e tests\nand only deploy to production if the tests pass.\n\n### API performance\n\nIn order to improve the time to show the statistics of the most popular packages, I could run a script to pre-compute the statistics of the [top 1000](https://gist.github.com/anvaka/8e8fa57c7ee1350e3491) packages of the NPM registry and warm the cache.\n\n### Better error handling\n\nThe `package-build-stats` exposes detailed error types that enables BundlePhobia to\nshow a custom message for each of them. In this project, these errors are not handled\nand the UI will always claim \"Package not found\" when something goes wrong.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalentinh%2Fbundlelove","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalentinh%2Fbundlelove","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalentinh%2Fbundlelove/lists"}