Skip to content

Commit

Permalink
packaging: dual-package ui-components with parcel
Browse files Browse the repository at this point in the history
Parcel[^1] is an alternative to webpack with a few significant
differences:

1. Configuration is managed (mostly) through package.json, with minimal
   configuration actually needed.
2. It's significantly faster than webpack for a package of this size, as
   it uses native-code packages (e.g. swc) for transformation and
   minification
3. It has first-class support for ES Module outputs (webpack's support
   is still experimental)
4. It supports bundling for JS libraries in a mode that bundles only
   first-party code and *nothing* from node_modules.

Use parcel to dual-package ui-components as ESM + CJS, so that bundlers
have access to good export analysis (via ESM) and node has access to a
format that doesn't require transformation (CJS).

As a size comparison, using `du --bytes`:

```
Before (dist/main.js):           774214 B (774KB)
After (dist/cjs/index.js):        90701 B ( 90KB)
After (dist/esm/index.js):        90232 B ( 90KB)
```

This is possible because no dependencies are included in that bundle.
Compared to the previous bundle, the parcel-produced bundles include
zero copies of:

* lodash (or any part of it)
* recharts
* @cockroachlabs/icons
* anything else in node_modules/

Those dependencies required at runtime are all specified in
package.json's 'dependencies' or 'peerDependencies' blocks. Anything in
dependencies is automatically downloaded by consumers, but can be
successfully de-duped with other compatible node_modules that it uses
(i.e. there's no copy of lodash embedded here and another copy in the
consumer's node_modules). Similarly, anything in peerDependencies must
be provided explicitly by the consuming package (i.e. we declare
compatibility with react 17, but installing this package won't even
download one into node_modules).

The result is a JS bundle that contains only our code, minified for
production use in other packages.

[^1]: https://parceljs.org
  • Loading branch information
sjbarag committed Sep 20, 2023
1 parent 0cff2a2 commit e90ec01
Show file tree
Hide file tree
Showing 13 changed files with 1,714 additions and 1,005 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ node_modules
# Output of 'npm pack'
*.tgz

# Parcel build cache
.parcel-cache

# Yarn Integrity file
.yarn-integrity

Expand Down
19 changes: 19 additions & 0 deletions packages/ui-components/.hg
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This is not a Mercurial repo.
#
# parcel 2.9.3 handles pnpm workspaces strangely, and walks the file system
# upwards looking for a lockfile, a .git file or directory, or a .hg file or
# directory:
#
# https://github.com/parcel-bundler/parcel/blob/5ac45672bb603841bf294c66019930be4354625a/packages/core/core/src/resolveOptions.js#L72
#
# Without this .hg file, parcel would continue walking to the root of this git
# repo (../../ from here) and install dependencies there. We don't actually want
# that, and would prefer if packages installed for a package were listed in that
# package's dependencies. The presence of this file is enough to keep parcel
# properly rooted within this workspace package, so this .hg file must remain.
# I'm sorry for the confusing naming --- it seems like the least-bad option.
#
# There's an open issue in parcel to address this upstream, but it hasn't been
# resolved as-of September 2023:
#
# https://github.com/parcel-bundler/parcel/issues/7206
3 changes: 3 additions & 0 deletions packages/ui-components/.sassrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"includePaths": ["node_modules"],
}
16 changes: 0 additions & 16 deletions packages/ui-components/babel.config.js

This file was deleted.

38 changes: 15 additions & 23 deletions packages/ui-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
"type": "git",
"url": "https://github.com/cockroachdb/ui"
},
"main": "dist/main.js",
"source": "src/index.ts",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/types/index.d.ts",
"scripts": {
"build": "npm-run-all build:typescript build:bundle",
"build:bundle": "webpack --mode production",
"build:bundle": "parcel build",
"build:typescript": "tsc",
"build:watch": "webpack --mode development --watch",
"build:watch": "parcel watch",
"ci": "jest --ci -i",
"clean": "rm -rf ./dist/*",
"lint": "eslint \"src/**/*.{tsx,ts,js}\"",
Expand All @@ -27,23 +29,23 @@
"keywords": [],
"license": "MIT",
"dependencies": {
"@cockroachlabs/design-tokens": "workspace:../design-tokens",
"@cockroachlabs/icons": "workspace:../icons",
"@popperjs/core": "^2.9.2",
"classnames": "2.3.2",
"lodash": "^4.17.21",
"react-final-form": "6.5.9",
"react-lines-ellipsis": "^0.15.0",
"react-popper": "^2.2.5",
"recharts": "^2.8.0"
},
"devDependencies": {
"@babel/cli": "7.21.0",
"@babel/core": "7.21.0",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
"@babel/preset-env": "7.20.2",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.21.0",
"@cockroachlabs/design-tokens": "workspace:../design-tokens",
"@cockroachlabs/eslint-config": "workspace:../eslint-config",
"@parcel/config-default": "^2.9.3",
"@parcel/packager-ts": "^2.9.3",
"@parcel/reporter-bundle-analyzer": "^2.9.3",
"@parcel/transformer-sass": "^2.9.3",
"@parcel/transformer-typescript-types": "^2.9.3",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "12.1.5",
"@types/classnames": "2.3.0",
Expand All @@ -56,9 +58,6 @@
"@types/testing-library__jest-dom": "^5.14.6",
"@typescript-eslint/eslint-plugin": "6.7.0",
"@typescript-eslint/parser": "6.7.0",
"babel-loader": "8.3.0",
"classnames": "2.3.2",
"css-loader": "^6.8.1",
"eslint": "8.49.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-prettier": "4.2.1",
Expand All @@ -69,21 +68,14 @@
"jest": "29.4.3",
"jest-environment-jsdom": "29.4.3",
"jest-runner-eslint": "1.1.0",
"mini-css-extract-plugin": "^2.7.5",
"npm-run-all": "4.1.5",
"parcel": "^2.9.3",
"prettier": "2.8.4",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-final-form": "6.5.9",
"sass": "1.58.3",
"sass-loader": "13.2.0",
"source-map-loader": "4.0.1",
"style-loader": "3.3.1",
"ts-jest": "29.1.1",
"typescript": "5.x",
"webpack": "5.75.0",
"webpack-cli": "4.10.0",
"webpackbar": "5.0.2"
"typescript": "5.x"
},
"peerDependencies": {
"react": "^17.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/Icon/Pictogram.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "~@cockroachlabs/design-tokens/dist/web/tokens";
@import "@cockroachlabs/design-tokens/dist/web/_tokens.scss";

.size-small {
height: 40px;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/Typography/Code.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "~@cockroachlabs/design-tokens/dist/web/tokens";
@import "@cockroachlabs/design-tokens/dist/web/_tokens.scss";

.code {
font-family: $type-family-code;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/Typography/Heading.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "~@cockroachlabs/design-tokens/dist/web/tokens";
@import "@cockroachlabs/design-tokens/dist/web/_tokens.scss";

.type-h1 {
font-family: $type-family-ui;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/Typography/Text.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "~@cockroachlabs/design-tokens/dist/web/tokens";
@import "@cockroachlabs/design-tokens/dist/web/_tokens.scss";

.type-body {
font-family: $type-family-ui;
Expand Down
1 change: 1 addition & 0 deletions packages/ui-components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="./declaration.d.ts"/>
export * from "./Avatar/Avatar";
export * from "./Badge/Badge";
export * from "./Button/Button";
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/styles/tokens.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "~@cockroachlabs/design-tokens/dist/web/tokens";
@import "@cockroachlabs/design-tokens/dist/web/_tokens.scss";

/**
Variables
Expand Down
77 changes: 0 additions & 77 deletions packages/ui-components/webpack.config.js

This file was deleted.

Loading

0 comments on commit e90ec01

Please sign in to comment.