UNPKG

13.2 kBMarkdownView Raw
1Composi
2========
3[![npm](https://img.shields.io/npm/v/composi.svg)](https://www.npmjs.org/package/composi)
4[![Gzip Size](https://img.badgesize.io/https://unpkg.com/composi/dist/composi.js.gzip)](https://www.npmjs.org/package/composi)
5[![apm](https://img.shields.io/npm/l/composi.svg)](https://www.npmjs.org/package/composi)
6[![npm](https://img.shields.io/npm/dt/composi.svg)](https://www.npmjs.org/package/composi)
7[![Read the Docs (version)](https://img.shields.io/readthedocs/pip/stable.svg)](https://composor.github.io)
8
9Composi is a framework for creating desktop and mobile apps. With Composi you can create a dynamic website with reactive components, a progressive web app, or a hybrid app for mobile app stores. Visit the [website](https://composor.github.io).
10
11Composi is small. The core is barely 3KB gzipped. It therefore loads fast. Its virtual DOM updates components efficiently and quickly. It has an API very similar to React, while mainting it's emphasis on simplicity, size, and ease of learning. In fact, you can learn everything you need to know to build apps with Composi in an hour or two.
12
13Composi components can be stateless or stateful. Stateful components are reactive. When you change a component's state, that triggers the component's render function. That in turn creates a new virtual DOM based on the data changes. It then patches the DOM to match the changes. If there are no changes, nothing will happen.
14
15A component's markup is written with JSX. This means you can create custom tags to organize your component's template. You can also pass props to a component tag. If you prefer, you can instead use the `h` function to define the component's markup with hyperscript. In fact, at render time the JSX is converted to this.
16
17Browser Support
18---------------
19
20Composi is compatible with browsers back to IE 9 on Windows 7, although you may need to include a [polyfill for promises](https://github.com/stefanpenner/es6-promise) for complete compatibility.
21
22
23
24Live Examples on Codepen
25------------------------
26
271. <a href='https://codepen.io/rbiggs/pen/GOyObq' target='__blank'>Todo List</a>
283. <a href='https://codepen.io/rbiggs/pen/zPmERR' target='__blank'>Minimal Hacker News</a>
292. <a href='https://codepen.io/rbiggs/pen/POMbxG' target='__blank'>Tour of Heroes (Client Side Routing)s</a>
304. <a href='https://codepen.io/rbiggs/pen/BmXqqL' target='__blank'>Calculator</a>
315. <a href='https://codepen.io/rbiggs/pen/qVxvOp' target='__blank'>Cat Image Browser</a>
326. <a href='https://codepen.io/rbiggs/pen/EbovjJ' target='__blank'>Pythagoras Dancing Tree</a>
337. <a href='https://codepen.io/rbiggs/pen/POpMMz' target='__blank'>Tic-Tac-Toe</a>
348. <a href='https://codepen.io/rbiggs/pen/jYbVPe' target='__blank'>Rick and Morty Character Viewer</a>
359. <a href='https://codepen.io/rbiggs/pen/VywZWE' target='__blank'>Slideshow Component</a>
3610. <a href='https://codepen.io/rbiggs/pen/gXopyN' target='__blank'>Coin Flip App</a>
3711. <a href='https://codepen.io/rbiggs/pen/LOZmbG' target='__blank'>Canvas Clock</a>
3812. <a href='https://codepen.io/rbiggs/pen/RjRpxL' target='__blank'>SVG Clock</a>
3913. <a href='https://codepen.io/rbiggs/pen/mqyxJX' target='__blank'>Spreadsheet</a>
4014. <a href='https://codepen.io/rbiggs/pen/oervxx' target='__blank'>Counter with Redux</a>
4115. <a href='https://codepen.io/rbiggs/pen/JygrLo' target='__blank'>Counter with Mobx</a>
42
43Installation
44-------------
45
46To install Composi, you'll need to have [Nodejs](https://nodejs.org/en/) installed. Open your terminal and run:
47
48```sh
49npm i -g composi
50```
51
52**Note:** On macOS and Linux, you may need to run the above command with `sudo`.
53
54Create a New Project
55--------------------
56After installing Composi, you can use it to create a new project. The simplest way to do this is to provide a project name following the `-n` flag:
57
58```sh
59composi -n myproject
60```
61This will create a project named "myproject" on your desktop. If you want to have the project placed somewhere else, you can provide a path with the `-p` flag:
62
63```sh
64npm -n myproject -p dev/New \Projects
65```
66On Windows use the standard Windows file system path notation to define your project's path.
67
68Project Structure
69-----------------
70A new project will have the following folder structure:
71```
72+--myproject
73| +--dev
74| +--components
75| |--title.js
76| +--css
77| |--styles.css
78| |--app.js
79| +--js
80|--.babelrc
81|--.editorconfig
82|--gulpfile.js
83|--index.html
84|--jsconfig.json
85|--package.json
86|--README.md
87```
88
89Building
90--------
91To build your project, `cd` to its folder and run:
92
93```sh
94npm i
95```
96
97Then, while in your project's root folder, run:
98
99```sh
100npm start
101```
102
103This will build and launch your project in your default browser.
104
105With this structure, you can add other sub-folders to components, or create other folders inside the `dev` folder as necessary.
106
107`styles.css` is a CSS reset. We are using the Bootstrap 4 rest since it provides a consistent baseline for HTML across all browsers. `app.js` is the core of your website/app. `components` folder has one component: `list.js`. You can add more files for other component as needs. Feel free to add more folders and files to the `dev` folder as you see fit to achieve the structure your app needs. Import them into `app.js`. At build time the build script uses `app.js` to bundle all your files and output them to `js/app.js`. The `index.html` is automatically setup to import that script. `index.html` is your main page.
108
109Example Code - Functional Component
110-----------------------------------
111
112```javascript
113import { h, mount } from 'composi'
114
115function HelloWorld({name}) {
116 return (
117 <nav>
118 <h1>Hello, {name}!</h1>
119 </nav>
120 )
121}
122
123mount(<HelloWorld name='World' />, 'header')
124```
125
126Example Code - Class Component
127------------------------------
128```javascript
129import { h, Component } from 'composi'
130import { sampleData } from './data/sample-data'
131
132class List extends Component {
133 render(data) {
134 return (
135 <ul class='list'>
136 {
137 data.map(item => <li key={item.key}>{item.name}</li>)
138 }
139 </ul>
140 )
141 }
142}
143
144// Instantiate class to render component to DOM:
145new List({
146 container: 'section',
147 state: sampleData
148})
149```
150
151Documentation
152-------------
153To learn how to use Composi, open the [docs](./docs/index.md) folder for project documentation, or for in depth tutorials visit the [website](https://composor.github.io)
154
155Summary
156-------
157
158Composi is all about components. These provide a great way to organize your code into modular and reusable chunks. The virtual DOM means you never have to touch the DOM to change something.
159
160Because Composi uses JSX, there are many similarities to React patterns. Please note that Composi is not a React clone. It is not trying to be compatible with React and the React ecosystem the way Preact and Inferno do. Component state is managed quite differently from React. Components lack the React refs and context properties. Also lacking, PropTypes. Events are not synthetic. They are either real inline events or the `handleEvent` interface. Props and custom tags are supported only because JSX provides these by default. The component architecture is actually adapted from the Component class of [ChocolateChip-UI](https://github.com/chocolatechip-ui/chocolatechipui). Changes were made to the API to work with a virtual DOM.
161
162Composi is small, just 3KB for the gzipped core. It loads quickly. Its small and focused API means you can learn everything in half a day and be productive. If you're already familiar with JSX, then you only need to learn the Component API. You can easily do that in an hour.
163
164Type Safety
165-----------
166
167Composi is written in standard ES6 with JSDoc comments to document type usage. This exposes Composi's type system to TypeScript during build time to verify that the source code is correctly typed. This also provides enhanced features when using Composi with [Visual Studio Code](https://code.visualstudio.com). Open `Settings` from the `Preferences` menu in Visual Studio Code and add the following setting:
168
169```javascript
170"javascript.implicitProjectConfig.checkJs": true
171```
172This tells Visual Studio Code to use TypeScript to check the JavaScript in a project. By default it uses inference to understand JavaScript types, which is very lax. But with JSDoc comments specifying types, it uses those instead for a more strict check of the code structure.
173
174This also gives intellisense when hovering over terms, intelligent code completion, symbol definition peek, symbol renaming across files, typo detection, flagging of unused variables, and wrong use of types as parameters, wrong number of parameters, etc. All of this is happening live, as you are coding. Not build step necessary.
175
176You can run a type check on Composi with TypeScript using this package script:
177
178```javascript
179npm run checkjs
180```
181This test gets run automatically when performiing a build:
182
183```shell
184npm run build
185> npm run format && npm run lint && npm run checkjs && npm run bundle && gulp gzip
186> prettier --no-semi --single-quote --write ./lib/*.js ./lib/utils/*.js
187> eslint --config ./.eslintrc.json lib
188> tsc --allowJs --checkJs --noEmit --target ES6 lib/*.js lib/**/*.js
189> rollup -c
190```
191
192Running Tests
193-------------
194
195Composi comes with unit test written with Mocha and Chai. These are loaded from a CDN, so you require an internet connect to run these tests. To run them, open your terminal and execute:
196
197```bash
198npm test
199```
200
201This will open a navigation page in your default browser. There are four tests:
202
2031. h
2042. fragment
2053. mount and render
2064. Component
207
208Clicking on one of these will open the test page. The test runs automatically when you open the page. Some errors may only show in the browser console, so open it to check. You can get back to the test navigation page by clicking any where on the top header.
209
210What's Missing
211--------------
212Composi is focused on one thing - providing a solution for components for building and structureing a projects. That means there are certain things it does not address, such as state management, routing, Ajax, and data persistence. There are already solutions that provide these, as enumerated below.
213
214### State Management
215Composi provides the barest support for state through the component's `state` property and `setState` method. However for a more robust solution you may prefer to use [Redux](http://redux.js.org), [Mobx](https://mobx.js.org), or some other state management solution. When you do so, you'll want to create stateless components. Read the documentation for [Component](./docs/components.md) to learn more about stateless components. If yo want something really minimal, take a look at [trkl](https://www.npmjs.com/package/trkl) and [pure](https://www.npmjs.com/package/purestate). You could event roll your own state management solution by defining a class and using Composi's [pubsub functions](./docs/pubsub.md), `subscribe` and `dispatch` for making it reactive. Another possibility for state management is [freezer-js](https://www.npmjs.com/package/freezer-js)
216
217### Router
218Composi does not provide a client-side router. However, you can use our blessed router [composi-router](https://www.npmjs.com/package/composi-router). The Github repository has documentation on how to use.
219
220Other alternatives for client-side routing are [Page.js](https://www.npmjs.com/package/page.js), [Universal Router](https://www.npmjs.com/package/universal-router), [Navigo](https://www.npmjs.com/package/navigo) or [rlite-router](https://www.npmjs.com/package/rlite-router).
221
222### Ajax
223Composi does not provide a means of aquiring remote data. If you only need to support current, ever-green browsers, you an use [fectch](). If you would like to use `fetch` with older browsers, you can provide the [WHATWG polyfill](https://github.com/whatwg/fetch). If don't need every possible feature of `fetch` and are concerned about the polyfill size, you can consider [unfetch](https://www.npmjs.com/package/unfetch). It's tiny and provides good support for the basics.
224
225If you would prefer an approach more like tradition Ajax championed by jQuery, you can take a look at [Axios](https://www.npmjs.com/package/axios).
226
227### Local Data Persistence
228If you need to persist data locally, you could use the browser's [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). If you need greater storage or a more sophisticated API, you might look at [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). If you need support for older browsers, you might consider [localForage](https://www.npmjs.com/package/localforage). This is a libarary that uses whatever local dataStore is the best choice for the browser. It provides a simple interface that works the same for localStorage, WebSQL and IndexedDB.
229
230
231Prior Art
232---------
233
234Composi was not conceived in a vacuum. Inspiration came for exposure to:
235
2361. [vue](https://github.com/vuejs/vue)
2372. [react](https://github.com/facebook/react)
2383. [preact](https://github.com/developit/preact)
2394. [domvm](https://github.com/leeoniya/domvm)
2405. [yo-yo](https://github.com/maxogden/yo-yo)
2416. [choo](https://github.com/choojs/choo)
2427. [hyperapp](https://github.com/hyperapp/hyperapp)