├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json └── src ├── HelloWorld.js ├── HelloWorld.test.js ├── InputSomething.js ├── InputSomething.test.js └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015-loose", "react"], 3 | "plugins": ["transform-class-properties"] 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | [*.js] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [*.json] 14 | indent_style = space 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | 3 | dist 4 | karma.conf.js 5 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: airbnb 2 | parser: babel-eslint 3 | rules: 4 | react/jsx-filename-extension: 0 5 | import/no-extraneous-dependencies: 0 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | 3 | node_modules 4 | npm-debug.log 5 | 6 | .nyc_output 7 | coverage 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "5.0" 4 | 5 | script: 6 | - npm run lint 7 | - npm test 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Johannes Stein 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-lib-starterkit 2 | This provides the starting point for creating re-usable libraries/components for React. 3 | 4 | ### Technology stack: 5 | - Transpiler: Babel 6 | - Bundler: Rollup (with `rollup-babel-lib-bundler`) 7 | - Libraries: React 8 | - Testing: Karma, Mocha, Chai, Enzyme 9 | - Linter: ESLint 10 | - Commit Hooks: Husky 11 | - Code style: AirBnB 12 | 13 | ### Folder structure 14 | ``` 15 | dist - Distribution files for the component 16 | test - Tests for the component 17 | src - The source of the component 18 | ``` 19 | 20 | `dist` files are not under version control, they are being generated on `npm install` and `npm publish` through the `prepublish` hook. If you need the library to be available in a browser environment, use NPMCDN instead of linking directly to Github. 21 | 22 | ### Commands 23 | ``` 24 | npm run build - Builds distribution 25 | npm run lint - Lints all files 26 | npm test - Lints and run tests 27 | ``` 28 | 29 | ### Choice of bundler: Why not Webpack? 30 | I prefer rollup for libraries, because the shared scope across files resembles more of what the code what look like if I were to write the library by hand. It also saves bytes and we all know every byte counts. 31 | I prefer Webpack for apps, because Webpacks allows more or and more precise optimizations in single-page apps. 32 | 33 | 34 | ### Things to improve on 35 | - Add code coverage with coveralls 36 | - Add badges 37 | 38 | ### License 39 | MIT 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-lib-starterkit", 3 | "version": "1.3.0", 4 | "description": "Starterkit for React libraries", 5 | "main": "dist/react-lib-starterkit.js", 6 | "jsnext:main": "dist/react-lib-starterkit.es2015.js", 7 | "scripts": { 8 | "prebuild": "rimraf dist", 9 | "build": "rollup-babel-lib-bundler src/index.js", 10 | "lint": "eslint .", 11 | "test": "ava --verbose 'src/**/*.test.js'", 12 | "coverage": "nyc --reporter lcov --reporter html ava 'src/**/*.test.js'", 13 | "precommit": "npm run lint", 14 | "prepublishOnly": "npm run build" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/frostney/react-lib-starterkit.git" 19 | }, 20 | "keywords": [ 21 | "react", 22 | "lib", 23 | "starterkit", 24 | "boilerplate" 25 | ], 26 | "author": "Johannes Stein", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/frostney/react-lib-starterkit/issues" 30 | }, 31 | "homepage": "https://github.com/frostney/react-lib-starterkit#readme", 32 | "peerDependencies": { 33 | "react": "^15.0.1" 34 | }, 35 | "ava": { 36 | "babel": "inherit", 37 | "require": "babel-register" 38 | }, 39 | "rollupBabelLibBundler": { 40 | "babel": { 41 | "presets": [ 42 | "es2015-loose-rollup", 43 | "react" 44 | ], 45 | "plugins": [ 46 | "transform-class-properties" 47 | ] 48 | } 49 | }, 50 | "devDependencies": { 51 | "ava": "^0.16.0", 52 | "babel-core": "^6.7.7", 53 | "babel-eslint": "^7.0.0", 54 | "babel-plugin-transform-class-properties": "^6.6.0", 55 | "babel-preset-es2015-loose": "^8.0.0", 56 | "babel-preset-es2015-loose-rollup": "^7.0.0", 57 | "babel-preset-react": "^6.5.0", 58 | "enzyme": "^2.2.0", 59 | "eslint": "^3.7.0", 60 | "eslint-config-airbnb": "^12.0.0", 61 | "eslint-plugin-import": "^1.16.0", 62 | "eslint-plugin-jsx-a11y": "^2.2.2", 63 | "eslint-plugin-react": "^6.3.0", 64 | "husky": "^0.11.4", 65 | "in-publish": "^2.0.0", 66 | "json-loader": "^0.5.4", 67 | "nyc": "^8.3.0", 68 | "react-addons-test-utils": "^15.0.1", 69 | "react-dom": "^15.0.1", 70 | "rimraf": "^2.5.2", 71 | "rollup-babel-lib-bundler": "^3.0.1" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/HelloWorld.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | 3 | class HelloWorld extends Component { 4 | static propTypes = { 5 | name: PropTypes.string, 6 | }; 7 | 8 | static defaultProps = { 9 | name: 'world', 10 | }; 11 | 12 | render() { 13 | return
Hello {this.props.name}
; 14 | } 15 | } 16 | 17 | export default HelloWorld; 18 | -------------------------------------------------------------------------------- /src/HelloWorld.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import test from 'ava'; 3 | import { shallow } from 'enzyme'; 4 | 5 | import HelloWorld from './HelloWorld'; 6 | 7 | test((t) => { 8 | const wrapper = shallow(); 9 | t.is(wrapper.find('div').length, 1); 10 | }); 11 | -------------------------------------------------------------------------------- /src/InputSomething.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const InputSomething = () => ; 4 | 5 | export default InputSomething; 6 | -------------------------------------------------------------------------------- /src/InputSomething.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import test from 'ava'; 3 | import { shallow } from 'enzyme'; 4 | 5 | import InputSomething from './InputSomething'; 6 | 7 | test((t) => { 8 | const wrapper = shallow(); 9 | t.is(wrapper.find('input').length, 1); 10 | }); 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import HelloWorld from './HelloWorld'; 2 | import InputSomething from './InputSomething'; 3 | 4 | export { HelloWorld, InputSomething }; 5 | --------------------------------------------------------------------------------