0.1.0 • Published 5 years ago

jumpcut v0.1.0

Weekly downloads
1
License
UNLICENSED
Repository
github
Last release
5 years ago

All of Jumpcut's components that are able to be shared across projects are hosted here.

The problem

We have spent a lot of money on branding. We've made the investment, and now we need that branding to be implemented consistently across our projects. Things like buttons, panels, lists, and even larger components and utility scripts can all be shared across projects. But how do we do that efficiently? Copying code and trying to maintain updates of components across projects is an absolute nightmare.

The solution

A repo and node package that will be published to NPM and imported across our projects. This repo has CI that automatically deploys the entire package to NPM. Whenever other projects that depend on this package are deployed, CI will update the project's NPM packages, automatically keeping our dependencies up-to-date.

Best practices

When modifying or extending existing components, you must keep in mind that these packages are used across projects and automatically updated. That means your OPEN-CLOSED principle is more important than ever here. If you're not familiar with the OPEN-CLOSED principle, you should be. Maybe checkout this article specifically related to javascript: Open-Closed Principle.

Lerna and Monorepos

Our shared component repo follows a popular structure called a Monorepo. That means we have multiple NPM packages managed in a single repo. We use a dev dependency called Lerna. Lerna is a tool for managing multiple packages contained in a single repo (or Monorepo). The overall repo is an NPM package named jumpcut. You may npm i jumpcut and individually import each of the packages you use (import Button from 'jumpcut/components/Button';), or you may npm i @jumpcut/components-Button and only install a specific package. Each of the types (component, script, and web) are also scoped packages with the names @jumpcut/components, @jumpcut/scripts, and @jumpcut/web that can be installed individually as well.

Commands

  • npm run generate [type] [name] will execute a node script that accepts two required arguments. This does a couple of things. First, it generates the folder structure, index.js, and package.json files for the module in the src folder. Second, it generates and modifies the relevant import files and package.json for deployment to and import from NPM.
    • type - an enum ['component', 'script', 'web'], where component is a React component, script is a vanilla js script, and web is a Web Component. ['c', 's', 'w'] abbreviations may also be used as the type argument.
    • name - the script or component file name without an extension. This will be the import name. NOTE: All shared components must be default exports in their root. You cannot have a component or script that has named exports. This is an unfortunate limitation required to keep imports easy and manageable.
  • npm run dependecy [targetType] [targetName] will add a dependency to the target source package by prompting you for the type and name of the package you want to add as a dependency. Often times we will want to use a shared package in another shared package. That is a traditional npm package dependency, but in a Monorepo environment we need to manage these dependencies a little differently because versions are changing across dependencies all the time. This is largely managed by Lerna, and this script takes some of the manual work and hides that Lerna CLI to reduce the developer's overhead.
  • npm run deploy simply hides the lerna command to reduce dev overhead. The lerna publish -y command will look at any packages that have been modified by the developer and increment the versions of those packages before publishing them to NPM. If you edit a script package and publish it, you'll have to increment the version of the package (eg. @jumpcut/scripts-uuid-validator) and the type scope of the package (eg. @jumpcut/scripts) and finally the root package jumpcut.
  • npm run rename [type] [name] and npm run move [type] [name] do the same thing. You will be prompted for a new type (just press Enter to keep the current type) and prompted for a new name. This is useful if you want to rename a component or move a React component to a web component.
  • npm run delete [type] [name] will trigger a prompt to confirm deletion of a package with a given type and name.

Usage - Your CRUD Operations

CREATE a new shared component/script

  1. Run npm run generate [type] [name] to generate the files.
  2. Edit the files in ~/src/[type]/[name]/ to your liking (actually write the component/script).
  3. When your done and tested on Storybook, commit your changes to the repo.
  4. Run npm run deploy.

READ (use) an existing shared component

Lerna automatically publishes this core jumpcut package and all sub modules from this repo as NPM modules. npm i jumpcut will install the entire jumpcut shared repo as a dependency. Packages can then be imported in a variety of traditional ways:

import Button from 'jumpcut/components/Button'

// OR 

import components from 'jumpcut/components';
const Component = components.Button
...
return <Component />

// Due to the default export restriction, what you CANNOT do is:

import { Button } from 'jumpcut/components';

npm i @jumpcut/components will install JUST the shared react components from our jumpcut shared repo. Then you just import from there:

import Button from '@jumpcut/components/Button';

npm i @jumpcut/components-button will install a specific shared component. The naming convention is the @jumpcut scope, and the package is named @jumpcut/[type]-[name] in all lower case. In which case you would import:

import Button from '@jumpcut/components-button';

When it comes to web components, you would use a monkey-patch import. For example:

import 'jumpcut/web/Button';
// OR
import '@jumpcut/web/Button';
// OR
import '@jumpcut/web-button';

UPDATE an existing shared component

Whenever you want to make a change to an existing shared component (keep in mind the OPEN/CLOSED Princple!), you can simply make the changes to the source files, commit your changes to the repo, and run npm run deploy. If you need to rename a file, or move it from one type (eg. component) to another (eg. web), then run npm run rename [type] [name] or npm run move [type] [name], respectively.

DELETE an existing shared coument

Run npm run delete [type] [name].

Cross-package dependencies

Often times we will want to use one shared package in another shared package. In such a case you will run the command npm run dependency [targetType] [targetName];

  • targetType - The TYPE (enum ['component', 'script', 'web']) of the package that you want to add a dependency to.
  • targetName - The NAME of the package that you want to add a dependency to. You will be prompted for the type and name of the package you want to add as a dependency. This process adds the input prompted package as a dependency in the package.json of the argument package. It then runs lerna bootstrap which manages those dependency versioning going forward.

Naming Conventions

React components will follow PascalCase for both file names and import names. scripts will follow kebab-case for file names, and camelCase for import names. web components will follow kebab-case for file names (matching their html tag name) and imported using monkey-patching.

// React components
import Button from '@jumpcut/components/Button';
// Scripts
import uuidValidator from '@jumpcut/scripts/uuid-validator';
// Web components
import '@jumpcut/web/jc-button';

React

When using web components in react projects run npm i @webcomponents/webcomponentsjs vendor-copy Then add the following entry to your project's root package.json.

"scripts" {
  ...
  "postinstall": "vendor-copy"
},
...
"vendorCopy": [
  {
    "from": "node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js",
    "to": "public/vendor/custom-elements-es5-adapter.js"
  },
  {
    "from": "node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js",
    "to": "public/vendor/webcomponents-bundle.js"
  }
]

and add the following to the head of your view file.

<script src="%PUBLIC_URL%/vendor/webcomponents-bundle.js"></script>
<script>if (!window.customElements) { document.write("<!--"); }</script>
<script src="%PUBLIC_URL%/vendor/custom-elements-es5-adapter.js"></script>
<!--! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->

and then you can simply use a monkey-patch import statement like so:

import '@jumpcut/web/jc-button';
...
render() {
  return (
    <jc-button id="example" />
  );
}
...
0.1.0

5 years ago

0.0.27

5 years ago

0.0.22

5 years ago

0.0.21

5 years ago

0.0.19

5 years ago

0.0.17

5 years ago

0.0.15

5 years ago

0.0.14

5 years ago

0.0.13

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

1.0.6

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago