├── babel.config.json ├── .prettierrc ├── .npmignore ├── .gitignore ├── src ├── utils │ ├── getScreenSize.js │ └── debounce.js └── index.js ├── .eslintrc ├── package.json └── README.md /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react", "@babel/preset-env", "minify"] 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": true, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | build 4 | node_modules 5 | src 6 | .eslintrc 7 | .prettierrc 8 | .npmignore 9 | babel.config.json 10 | yarn.lock 11 | package-lock.json 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | lib 4 | node_modules 5 | .DS_Store 6 | yarn.lock 7 | package-lock.json 8 | index.js 9 | 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* -------------------------------------------------------------------------------- /src/utils/getScreenSize.js: -------------------------------------------------------------------------------- 1 | const getScreenSize = () => { 2 | return { 3 | width: window.innerWidth, 4 | height: window.innerHeight, 5 | }; 6 | }; 7 | 8 | export default getScreenSize; 9 | -------------------------------------------------------------------------------- /src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | const debounce = (func, delay) => { 2 | let timeoutId; 3 | 4 | return function (...args) { 5 | if (timeoutId) { 6 | clearTimeout(timeoutId); 7 | } 8 | 9 | timeoutId = setTimeout(() => { 10 | func(...args); 11 | }, delay); 12 | }; 13 | }; 14 | 15 | export default debounce; 16 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "parser": "babel-eslint", 7 | "rules": { 8 | "strict": 1, 9 | "no-console": 1 10 | }, 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:react/recommended", 14 | "plugin:prettier/recommended" 15 | ], 16 | "settings": { 17 | "react": { 18 | "version": "detect" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | import getScreenSize from './utils/getScreenSize'; 4 | import debounce from './utils/debounce'; 5 | 6 | const currentScreenSize = (settings = { debounceTime: 200 }) => { 7 | const [screenSize, setScreenSize] = useState(getScreenSize()); 8 | const handleResize = () => setScreenSize(getScreenSize()); 9 | const handleResizeDebounced = debounce(handleResize, settings.debounceTime); 10 | 11 | useEffect(() => { 12 | window.addEventListener('resize', handleResizeDebounced); 13 | 14 | return () => { 15 | window.removeEventListener('resize', handleResizeDebounced); 16 | }; 17 | }, []); 18 | 19 | return { 20 | width: screenSize.width, 21 | height: screenSize.height, 22 | }; 23 | }; 24 | 25 | export default currentScreenSize; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-new-module", 3 | "version": "1.0.0", 4 | "description": "NPM module template description", 5 | "keywords": [ 6 | "react", 7 | "hooks", 8 | "screen size" 9 | ], 10 | "private": false, 11 | "main": "lib/index.js", 12 | "scripts": { 13 | "build": "babel src --out-dir lib", 14 | "develop": "babel -w src --out-dir lib", 15 | "deploy": "npm publish" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "peerDependencies": { 20 | "react": "^16.6.1", 21 | "react-dom": "^16.13.1" 22 | }, 23 | "devDependencies": { 24 | "@babel/cli": "^7.10.5", 25 | "@babel/core": "^7.10.5", 26 | "@babel/preset-env": "^7.10.4", 27 | "@babel/preset-react": "^7.10.4", 28 | "babel-eslint": "^10.1.0", 29 | "babel-preset-minify": "^0.5.1", 30 | "eslint": "^7.5.0", 31 | "eslint-config-prettier": "^6.11.0", 32 | "eslint-plugin-prettier": "^3.1.4", 33 | "eslint-plugin-react": "^7.20.3", 34 | "prettier": "^2.0.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NPM module template 2 | Typescript implementation is available in a following [repo](https://github.com/Halo-Lab/react-hook-module-template-typescript) 3 | 4 | 5 | Boilerplate to create an npm module development environment with example code (custom hook that track window dimensions). 6 | 7 | > Our setup will consist of two separate projects: 8 | > 1. NPM Module Project 9 | > 2. React Host Project (to debug new features) 10 | 11 | ![projects structure](https://i.ibb.co/k2JsMyj/projects.png) 12 | 13 | NPM module will be connected to the React Host Project using `npm link`. Project separation will enable us to keep our module logic encapsulated and more maintainable. 14 |
15 |
16 | ## Available script commands 17 | 18 | Build `src` to `lib` folder. 19 | ``` 20 | npm run build 21 | ``` 22 | Run development will compile a file every time that any changes in `/src` folder will occur. 23 | ``` 24 | npm run develop 25 | ``` 26 | Deploy your project to NPM. The script will trigger `npm publish`. 27 | ``` 28 | npm run deploy 29 | ``` 30 |
31 |
32 | 33 | ## 🚀 Quick start 34 | 35 | 1. Clone template project. 36 | ``` 37 | git clone https://github.com/Halo-Lab/react-hook-module-template 38 | ``` 39 | 2. Pick a module name and change folder name in `package.json` accordingly. Make sure you are using a unique one so you can publish your package to npm. Provide additional information about your module by changing *description*, *author*, *license* and *keywords*. Describe basic functionality of your module in `README.md` file. 40 | 41 | *project folder* 42 | ``` 43 | /my-new-module 44 | ``` 45 | 46 | *package.json* 47 | ```json 48 | "name": "my-new-module", 49 | "description": "NPM module template description", 50 | "author": "John Smith", 51 | "license": "ISC", 52 | "keywords": ["react", "hooks", "screen size"] 53 | ``` 54 | 55 | 3. Install dependencies 56 | 57 | ``` 58 | npm i 59 | ``` 60 | 61 | 4. An initial build command will compile all files from `/src` folder to a single `/lib` folder. 62 | ``` 63 | npm run build 64 | ``` 65 | 5. Our module is ready for development. Now we are ready to connect our module to React Host Project. Create a new React Project in the different folder and change `App.js` file with example code. **Main concept is to keep two projects in separate folders. So after the development process Module Project will include 66 | module logic exclusively.** 67 | 68 | > Be sure that you're **not** creating new project inside Module folder. 69 | 70 | *Navigate to your main Project Folder and create a new React Project.* 71 | ``` 72 | cd .. 73 | npx create-react-app host_react_app 74 | ``` 75 | *App.js* 76 | ```jsx 77 | import React from 'react'; 78 | import useResizing from 'my-new-module'; 79 | 80 | function App() { 81 | const screenSize = useResizing(); 82 | 83 | return ( 84 |
85 | {`${screenSize.width}px ${screenSize.height}px`} 86 |
87 | ); 88 | } 89 | 90 | export default App; 91 | ``` 92 | 6. To connect our module open Module Project folder and create a symlink. Npm link will add our package to the global `/lib/node_modules/my-new-module` folder and create a link from it. You can find more information about npm link functionality in the [official documentation](https://docs.npmjs.com/cli/link). 93 | 94 | ``` 95 | cd my-new-module 96 | npm link 97 | ``` 98 | 7. Now open React Host Project and add your locally developed module. That will create a symbolic link from globally-installed ```my-new-module``` to current `node_modules/` folder 99 | 100 | ``` 101 | cd host_react_app 102 | npm link my-new-module 103 | ``` 104 | 105 | 8. Start React host and Module projects. Any changes inside module's `/src` folder will trigger both projects to rebuild. 106 | 107 | *React host project* 108 | ``` 109 | cd host_react_app 110 | npm run start 111 | ``` 112 | *Module project* 113 | ``` 114 | cd my-new-module 115 | npm run develop 116 | ``` 117 | 118 | 9. Change remote's Git URL to your own repository. 119 | 120 | ``` 121 | git remote set-url origin https://github.com/USERNAME/my-new-module.git 122 | ``` 123 | 124 | 10. Develop your custom module logic inside `/src` folder. 125 | 126 | ## Word from author 127 | 128 | Have fun! ✌️ 129 | 130 | 131 | Supported by Halo lab 132 | 133 | --------------------------------------------------------------------------------