Commit 96cd501395a5a7184948ba07a7ea02a05ae9f23a
all the docs
Michael Williams committed on 1/9/2016, 10:25:18 AMParent: 9642105bd047078b96b5d68874a78e1c620077e2
Files changed
README.md | changed |
README.md | ||
---|---|---|
@@ -3,16 +3,36 @@ | ||
3 | 3 | ** work in progress ** |
4 | 4 | |
5 | 5 | real-world, production-quality stack for [Craftworks](http://craftworks.enspiral.com) |
6 | 6 | |
7 | +## resources | |
8 | + | |
9 | +- [thinking in react](https://facebook.github.io/react/docs/thinking-in-react.html) | |
10 | +- [simplest redux example](https://github.com/jackielii/simplest-redux-example/blob/master/index.js) | |
11 | +- [smart and dumb components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) | |
12 | +- [css modules](http://glenmaddern.com/articles/css-modules) | |
13 | +- [mixins are dead, long live higher-order components](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) | |
14 | +- [react on es6+](http://babeljs.io/blog/2015/06/07/react-on-es6-plus/) | |
15 | +- [how to use classes and sleep at night](https://medium.com/@dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4) | |
16 | +- [common react mistakes: unneeded state](http://reactkungfu.com/2015/09/common-react-dot-js-mistakes-unneeded-state/) | |
17 | +- [promise cookbook](https://github.com/mattdesl/promise-cookbook) | |
18 | +- [approaches to testing react components](http://reactkungfu.com/2015/07/approaches-to-testing-react-components-an-overview/) | |
19 | +- [unit testing react components without a dom](http://simonsmith.io/unit-testing-react-components-without-a-dom/) | |
20 | + | |
21 | + | |
7 | 22 | ## stack |
8 | 23 | |
24 | +- node version manager: [`nvm`](https://github.com/creationix/nvm) | |
25 | + - when in this directory run `nvm use` which will use the version of `node` specified in [our .nvmrc](./.nvmrc). | |
26 | +- package manager: [`npm@3`](https://www.npmjs.com/) | |
27 | + - install with `npm install -g npm@3` | |
28 | + - to install a package, run `npm install --save my-favorite-package` | |
9 | 29 | - task runner: [npm scripts](http://substack.net/task_automation_with_npm_run) |
10 | -- client bundler: [browserify](https://github.com/substack/browserify-handbook) | |
11 | - - es6/jsx transform: [babelify](https://www.npmjs.com/package/babelify) | |
12 | - - css transform: [cssify](https://www.npmjs.com/package/cssify) and [css-modules-require-hook](https://www.npmjs.com/package/css-modules-require-hook) | |
13 | - - bulk require: [bulkify](https://www.npmjs.org/package/bulkify) | |
14 | -- configuration: [simple-rc](https://www.npmjs.org/package/simple-rc) | |
30 | +- browser bundler: [browserify](https://github.com/substack/browserify-handbook) | |
31 | +- es6/jsx transpiler: [babel](babeljs.io/) ([babel-require-hook](https://www.npmjs.com/package/babel-require-hook) and [babelify](https://www.npmjs.com/package/babelify)) | |
32 | +- modular css: [css modules](http://glenmaddern.com/articles/css-modules) ([css-modules-require-hook](https://www.npmjs.com/package/css-modules-require-hook) and [cssify](https://www.npmjs.com/package/cssify)) | |
33 | +- bulk require: [bulk-require](https://www.npmjs.com/package/bulk-require) and [bulkify](https://www.npmjs.com/package/bulkify) | |
34 | +- configuration: [simple-rc](https://www.npmjs.com/package/simple-rc) and [evalify](https://www.npmjs.com/package/evalify) | |
15 | 35 | - utility functions: [lodash](https://lodash.com/docs/) |
16 | 36 | - data model: [tcomb](https://github.com/gcanti/tcomb) |
17 | 37 | - database: [knex](https://www.npmjs.com/package/knex) |
18 | 38 | - api service: [feathers-knex](https://www.npmjs.com/package/feathers-knex) |
@@ -28,73 +48,239 @@ | ||
28 | 48 | - render views: [react](https://www.npmjs.com/package/react) |
29 | 49 | - render forms: [tcomb-form](https://github.com/gcanti/tcomb-form) |
30 | 50 | - test specs: [ava](https://www.npmjs.com/package/ava) |
31 | 51 | - test features: [cucumber](https://www.npmjs.com/package/cucumber) |
32 | -- test dom: [zombie](http://zombie.js.org/) | |
52 | +- test browser: [zombie](http://zombie.js.org/) | |
33 | 53 | - TODO generators: [plop](https://github.com/amwmedia/plop) |
34 | 54 | |
55 | +## scripts | |
35 | 56 | |
57 | +- [install](#install) | |
58 | +- [start](#start) | |
59 | +- [test](#test) | |
60 | +- [lint](#lint) | |
61 | +- [format](#format) | |
62 | +- [shrinkwrap](#shrinkwrap) | |
63 | +- [webpack-rails](#webpack-rails) | |
64 | + | |
65 | +### install | |
66 | + | |
67 | +```shell | |
68 | +npm install | |
69 | +``` | |
70 | + | |
71 | +### dev | |
72 | + | |
73 | +starts development environment | |
74 | + | |
75 | +```shell | |
76 | +npm run dev | |
77 | +``` | |
78 | + | |
79 | +### prod | |
80 | + | |
81 | +starts production environment | |
82 | + | |
83 | +```shell | |
84 | +npm run prod | |
85 | +``` | |
86 | + | |
87 | +### test | |
88 | + | |
89 | +runs tests | |
90 | + | |
91 | +```shell | |
92 | +npm test | |
93 | +``` | |
94 | + | |
95 | +#### test:spec | |
96 | + | |
97 | +runs [ava](https://www.npmjs.com/package/ava) tests | |
98 | + | |
99 | +can optionally take a [glob](https://www.npmjs.com/package/glob) | |
100 | + | |
101 | +```shell | |
102 | +npm run test:spec -- './app/todos/**/*.spec.js' | |
103 | +``` | |
104 | + | |
105 | +default glob is `./app/**/*.spec.js` | |
106 | + | |
107 | +#### test:feature | |
108 | + | |
109 | +runs [cucumber](https://www.npmjs.com/package/cucumber) tests | |
110 | + | |
111 | +can optionally take a [glob](https://www.npmjs.com/package/glob) | |
112 | + | |
113 | +```shell | |
114 | +npm run test:feature -- './features/todo.feature` | |
115 | +``` | |
116 | + | |
117 | +default glob is `./features/**/*.feature` | |
118 | + | |
119 | +### lint | |
120 | + | |
121 | +checks for [standard style](http://standardjs.com) | |
122 | + | |
123 | +can optionally take a [glob](https://www.npmjs.com/package/glob) | |
124 | + | |
125 | +```shell | |
126 | +npm run lint -- './app/todos/**/*.js' | |
127 | +``` | |
128 | + | |
129 | +default glob is `./**/*.js` ignoring `node_modules` | |
130 | + | |
131 | +### format | |
132 | + | |
133 | +converts to [standard](http://standardjs.com) if possible | |
134 | + | |
135 | +can optionally take a [glob](https://www.npmjs.com/package/glob) | |
136 | + | |
137 | +```shell | |
138 | +npm run format -- './app/**/*.js' | |
139 | +``` | |
140 | + | |
141 | +default glob is `./**/*.js` ignoring `node_modules` | |
142 | + | |
143 | +### database | |
144 | + | |
145 | +#### pg | |
146 | + | |
147 | +to run a local postgres db with [`docker`](https://docs.docker.com/) installed, | |
148 | + | |
149 | +- to install db, run `npm run pg:pull` | |
150 | +- to create db, run `npm run pg:run` | |
151 | +- to start db, run `npm run pg:start` | |
152 | +- to stop db, run `npm run pg:stop` | |
153 | +- to remove db, run `npm run pg:rm` | |
154 | +- to show db logs, run `npm run pg:logs` | |
155 | + | |
156 | +#### knex | |
157 | + | |
158 | +run [any `knex` command](http://knexjs.org/#Migrations-CLI) with `npm run knex -- [command] [args]` | |
159 | + | |
160 | +for example, run latest sql migrations with | |
161 | + | |
162 | +```shell | |
163 | +npm run knex -- migrate:latest | |
164 | +``` | |
165 | + | |
166 | +and generate new sql migration with | |
167 | + | |
168 | +```shell | |
169 | +npm run knex -- migrate:make add_some_columns_and_stuff | |
170 | +``` | |
171 | + | |
36 | 172 | ## directory structure |
37 | 173 | |
38 | 174 | - `/config/` |
39 | 175 | - `/config/index.js` |
40 | - - `/config/{ NODE_ENV }.js` | |
176 | + - `/config/${ NODE_ENV }.js` | |
41 | 177 | - `/app/${ module }/` |
42 | 178 | - symlink `/app` to `/node_modules/app` |
43 | - - only do relative requires if within module | |
44 | - - otherwise, always require top-down (`require('app/things/model')`). | |
179 | + - only do relative requires (`require('./models')`) if within module | |
180 | + - otherwise, always require top-down (`require('app/things/models')`). | |
45 | 181 | - `/feature/` |
46 | 182 | - `/feature/support/world.js` |
183 | + - `/feature/support/hooks.js` | |
47 | 184 | - `/feature/step_definitions/steps.js` |
48 | - - `/feature/todos.feature` | |
185 | + - `/feature/smoke.feature` | |
186 | +- spec tests are any files that end in `.spec.js` | |
49 | 187 | |
50 | -### micro-services | |
188 | +### app entry points | |
51 | 189 | |
52 | -TODO split into micro-services based on [mad-science-stack](https://github.com/enspiral-craftworks/mad-science-stack) | |
190 | +our server code is run as separate processes, namely: | |
53 | 191 | |
54 | -TODO write docs about what is a micro-service | |
192 | +- `static`: static file server using [`http`](https://nodejs.org/api/http.html) and [`ecstatic`](https://www.npmjs.com/package/ecstatic) | |
193 | +- `api`: RESTful HTTP interface to data using [`feathers`](http://feathersjs.com) and [`connect` middleware](https://github.com/senchalabs/connect#readme) | |
194 | +- `render`: server-side rendering using [`http`](https://nodejs.org/api/http.html), [`react-dom/server`](https://www.npmjs.com/package/react-dom), [`feathers-client`](https://www.npmjs.com/package/feathers-client), and more... | |
55 | 195 | |
196 | +our client code for `render` is bundled using [`browserify`](http://browserify.org), which similar to the server `render` process also uses [`react-dom`](https://www.npmjs.com/package/react-dom), [`feathers-client`](https://www.npmjs.com/package/feathers-client), and more... | |
197 | + | |
198 | +each server process has a separate url available to other entry points via the [./config](./config) | |
199 | + | |
56 | 200 | ### app modules |
57 | 201 | |
58 | 202 | in contrast to frameworks like Rails which split our `app` into directories for each "type" of file (models, views, controllers), our `app` is split into directories for each module, where each module contains the various types of files *within* that module. |
59 | 203 | |
60 | 204 | each module directory may contain any of: |
61 | 205 | |
62 | 206 | - `index.js`: exports all the below exports from the module |
63 | -- `models/*.js`: exports [`tcomb`](https://www.npmjs.com/package/tcomb) models | |
207 | +- `models.js`: exports [`tcomb`](https://www.npmjs.com/package/tcomb) models | |
64 | 208 | - `constants.js`: exports constants (such as [redux action types](https://www.npmjs.com/package/create-action-types)) |
65 | -- `actions.js`: exports [redux actions](https://www.npmjs.com/package/redux-actions) | |
66 | -- `reducer.js`: exports [redux reducer](http://redux.js.org/docs/basics/Reducers.html) | |
67 | -- `routes.js`: exports [`function (store) { return <ReactRouter.Route /> }`](https://www.npmjs.com/package/react-router) | |
209 | +- `actions.js`: exports [redux actions](https://www.npmjs.com/package/redux-actions) (recommended to use [`feathers-action`](https://npmjs.com/package/feathers-action)) | |
210 | +- `reducer.js`: exports [redux reducer](http://redux.js.org/docs/basics/Reducers.html) (recommended to use [`feathers-action`](https://npmjs.com/package/feathers-action)) | |
211 | +- `routes.js`: exports [`<ReactRouter.Route />`](https://www.npmjs.com/package/react-router) | |
68 | 212 | - `getters.js`: exports [`reselect`](https://www.npmjs.com/package/reselect) getters for use in containers' `connect` |
69 | 213 | - `containers/*.js`: exports [smart component](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) [`connect`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)ed with [`react-redux`](https://www.npmjs.com/package/react-redux) |
70 | 214 | - `components/*.js`: exports [dumb component](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) |
71 | 215 | - `components/*.css`: exports [css modules](http://glenmaddern.com/articles/css-modules) for respective component |
72 | 216 | - `service.js`: exports [`feathers`](http://feathersjs.com) service (recommended to use [`feathers-knex`](https://github.com/feathersjs/feathers-knex) and [`feathers-tcomb`](https://github.com/ahdinosaur/feathers-tcomb)) |
73 | -- `client.js`: exports [`feathers-client`](https://github.com/feathersjs/feathers-client) | |
74 | 217 | |
75 | -### setup postgres database | |
218 | +## FAQ | |
76 | 219 | |
77 | -install `docker` | |
220 | +### how to set default props | |
78 | 221 | |
79 | -- to install db, run `npm run pg:pull` | |
80 | -- to create db, run `npm run pg:run` | |
81 | -- to start db, run `npm run pg:start` | |
82 | -- to stop db, run `npm run pg:stop` | |
83 | -- to remove db, run `npm run pg:rm` | |
84 | -- to show db logs, run `npm run pg:logs` | |
222 | +```jsx | |
223 | +import React from 'react' | |
85 | 224 | |
86 | -run latest migrations with | |
225 | +export default class Thing extends React.Component { | |
226 | + static displayName = 'Thing' | |
87 | 227 | |
88 | -```shell | |
89 | -npm run knex -- migrate:latest | |
228 | + static defaultProps = { | |
229 | + isAwesome: true | |
230 | + } | |
231 | + | |
232 | + ... | |
233 | +} | |
90 | 234 | ``` |
91 | 235 | |
92 | -or run [any other `knex` command] with `npm run knex -- [command] [args]` | |
93 | 236 | |
237 | +### how to set prop types | |
238 | + | |
239 | +```jsx | |
240 | +import React, { PropTypes } from 'react' | |
241 | + | |
242 | +export default class Thing extends React.Component { | |
243 | + static displayName = 'Thing' | |
244 | + | |
245 | + static propTypes = { | |
246 | + increment: PropTypes.function | |
247 | + } | |
248 | + | |
249 | + ... | |
250 | +} | |
251 | +``` | |
252 | + | |
253 | +### how to bind functions to parent component when passing them down? | |
254 | + | |
255 | +```jsx | |
256 | +import React, { PropTypes } from 'react' | |
257 | + | |
258 | +export class Parent extends React.Component { | |
259 | + constructor(props) { | |
260 | + super(props) | |
261 | + this.state = { a: 0 } | |
262 | + } | |
263 | + | |
264 | + render () { | |
265 | + return <Child increment={this.increment} /> | |
266 | + } | |
267 | + | |
268 | + increment = () => { | |
269 | + this.setState({ a: this.state.a + 1 }) | |
270 | + } | |
271 | +} | |
272 | + | |
273 | +export class Child extends React.Component { | |
274 | + static propTypes = { | |
275 | + increment: PropTypes.function | |
276 | + } | |
277 | + | |
278 | + render () { | |
279 | + return <button onClick={this.props.increment}>click me</button> | |
280 | + } | |
281 | +} | |
282 | +``` | |
283 | + | |
94 | 284 | ## known issues |
95 | 285 | |
96 | 286 | - adding a new file won't always be noticed by `node-dev` or `watchify` due to usage of `bulk-require`). potential fix is to use `chokidar-cli` and some transform to watch for new files and re-run the script command |
97 | - | |
98 | -## resources | |
99 | - | |
100 | -- [simplest redux example](https://github.com/jackielii/simplest-redux-example/blob/master/index.js) |
Built with git-ssb-web