React npm ã©ã¤ãã©ãª/ããã±ã¼ã¸ã®ä½æå ¥éããnpmå ¬éã¾ã§ï¼Rollupã¨TypeScriptç·¨ï¼
ããã«ã¡ã¯ãçããï¼ä»æ¥ã¯ãRollupã¨TypeScriptã使ç¨ãã¦Reactã®npmããã±ã¼ã¸ãä½æããexampleãã£ã¬ã¯ããªã§åä½ç¢ºèªããæ¹æ³ã«ã¤ãã¦è©³ãã説æãã¾ãããã®è¨äºã§ã¯ãåå¿è ã§ãåãããããããã«ã¹ããããã¤ã¹ãããã§é²ãã¦ããã¾ãããã£ããå§ãã¾ãããï¼
- React npm ã©ã¤ãã©ãª/ããã±ã¼ã¸ã®ä½æå
¥éããnpmå
¬éã¾ã§ï¼Rollupã¨TypeScriptç·¨ï¼
- ä½ã£ããã®
- 1. åææ¡ä»¶
- 2. ããã¸ã§ã¯ãã®ã»ããã¢ãã
- ã©ã¤ãã©ãªã«ã¯ã©ã®ããã«ããã±ã¼ã¸ããã®ï¼ï¼npm rollupãããã¯npm packï¼ï¼
- 3. ãã£ã¬ã¯ããªæ§é ã®è¨å®
- 4. TypeScriptã®è¨å®
- 5. Rollupã®è¨å®
- 6. ã³ã³ãã¼ãã³ãã®ä½æ
- 7. ããã±ã¼ã¸ã®ãã«ã
- 8. Exampleã¢ããªã§ã®åä½ç¢ºèª
- 9. Exampleã¢ããªã®å®è¡
- 10. ããã±ã¼ã¸ã®å ¬éæºå
- 11. npmã¸ã®å ¬é
- ã¾ã¨ã
ä½ã£ããã®
react-iconsãå梱ããã¢ã¤ã³ã³ããã«ã¼ã§ãã
ãªãèªä½ã®ã©ã¤ãã©ãªãä½ã£ãã
è²ã ã¨npmã«ã¯ã¢ã¤ã³ã³ããã«ã¼ãåå¨ããã®ãããããã®ä¸ã®ã²ã¨ã¤ã使ç¨ãã¦ã¢ããªã±ã¼ã·ã§ã³ã«çµã¿è¾¼ãã§ãã¾ããããã®ã©ã¤ãã©ãªãéçºãçµäºï¼ãã¦ãããããªæãã ã£ãã®ã§ä¾åãã¦ããreact-iconsãå¤ãã¾ã¾ã ã£ãã®ã§SNSããã®ä»ä½¿ç¨ãããã¢ã¤ã³ã³ã追å ãããªã©ãåºæ¥ã¾ããã§ããããã®ããäºææ§ãä¿ã¡ã¤ã¤ã¢ã¤ã³ã³ã追å ã§ããããã«ãã®ã©ã¤ãã©ãªããã©ã¼ã¯ãã¦åéçºãè¡ãã¾ããã çµæãå梱ããã¢ã¤ã³ã³ãèªç±ã«å æ¸ãã§ããããã«ãªã£ããã¨ããã®ãä»åã®ãã£ããã«ãªãã¾ãã
1. åææ¡ä»¶
å¿ è¦ãªãã¼ã«
- Node.jsã¨npmãã¤ã³ã¹ãã¼ã«ããã¦ãããã¨ã
- åºæ¬çãªReactã¨TypeScriptã®ç¥èã
2. ããã¸ã§ã¯ãã®ã»ããã¢ãã
ã¾ããæ°ãããã£ã¬ã¯ããªãä½æãããã®ä¸ã§npmããã¸ã§ã¯ããåæåãã¾ãã
mkdir my-react-component cd my-react-component npm init -y
次ã«ãReactã¨ReactDOMãããã¦éçºã«å¿ è¦ãªä¾åé¢ä¿ãã¤ã³ã¹ãã¼ã«ãã¾ãã
npm install react react-dom react-icons tslib npm install --save-dev @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-typescript rollup rollup-plugin-peer-deps-external rollup-plugin-terser typescript @types/react @types/react-dom
ã©ã¤ãã©ãªã«ã¯ã©ã®ããã«ããã±ã¼ã¸ããã®ï¼ï¼npm rollupãããã¯npm packï¼ï¼
ããã§ã¾ãã©ã¤ãã©ãªãä½ãä¸ã§éè¦ãªãã®ãããã¾ãããããrollupã§ãã æåã¯ä¼ç¤¾å ã ãã§ä½¿ç¨ããããnpm packã¨ããã³ãã³ãã§ããã±ã¼ã¸ã³ã°ãã¦ãã¡ã¤ã«ãã©ããã«ãã㦠ãããnpm installããã°ããã®ã§ã¯ï¼ã¨ããã®ãèãã¾ããã
npm packã¨ã¯
pack ã¯ãé常 npm pack ã¨ãã¦ä½¿ç¨ãããnpmããã±ã¼ã¸ãã¢ã¼ã«ã¤ãåã㦠.tgz ãã¡ã¤ã«ï¼tarballï¼ã«ãã¾ãããã®ãã¡ã¤ã«ã¯å¾ã« npm install ã§ã¤ã³ã¹ãã¼ã«å¯è½ã§ãã
- ããã±ã¼ã¸ãã¢ã¼ã«ã¤ããã¦ãå¾ã§ã¤ã³ã¹ãã¼ã«å¯è½ãªå½¢å¼ã«å¤æãã¾ãã
- é常ãnpmããã±ã¼ã¸ã®é å¸ãå ¬éåã®ãã¹ããªã©ã§ä½¿ç¨ããã¾ãã
pack ã¯npmããã±ã¼ã¸ãã¢ã¼ã«ã¤ãåããå¾ã§ã¤ã³ã¹ãã¼ã«å¯è½ãªå½¢å¼ã«å¤æããããã«ä½¿ç¨ããã¾ãã
rollupã¨ã¯
rollup ã¯ãJavaScriptã®ã¢ã¸ã¥ã¼ã«ãã³ãã©ã¼ã§ãã主ã«ESã¢ã¸ã¥ã¼ã«ã対象ã«ãã¦ãããTree-shakingï¼ä¸è¦ãªã³ã¼ãã®åé¤ï¼ãªã©ãè¡ããå¹ççã«ãã³ãã«ãçæãã¾ãã
- ESã¢ã¸ã¥ã¼ã«ã«ç¹åãã¦ãããTree-shakingã«ãã£ã¦æé©åããããã³ãã«ãçæã§ããã
- 主ã«ã©ã¤ãã©ãªãããã±ã¼ã¸ã®éçºã§ä½¿ç¨ãããç¹ã«ããã³ãã¨ã³ãåãã®ããã±ã¼ã¸ã³ã°ã«é©ãã¦ããã
rollup ã¯ã¢ã¸ã¥ã¼ã«ãã³ãã©ã¼ã§ãJavaScriptã®ã³ã¼ããå¹ççã«ããã±ã¼ã¸ã³ã°ããããã«ä½¿ç¨ããã¾ãã
使ãæ¹ã«ãã£ã¦ç¨éã¯åããã
ä»åã¯å½åããã±ã¼ã¸ã³ã°ãã¦ä½¿ç¨ãèãã¦ãã¾ãããgithubã¨npmã«ç»é²ãã¦ å ¬éãããã¨ã§OSSã§ãããä»å¾ãã¢ãããã¼ãã®éã«ãã¼ã¸ã§ã³å¤æ´ããã ã㧠æ§ã ãªãã®ã«åæ ã§ããã¨ãããã¨ã§rollupã«ãã¾ããã
ã³ãã³ãã¯
- -cï¼configãã¡ã¤ã«ï¼rollup.config.jsï¼ã«ãã¨ã¥ãã¦rollupããï¼
- -wï¼Watchã¢ã¼ãï¼
ã使ç¨ãã¦ã¾ãã
ã«ã¼ãç´ä¸ã®rollup.config.jsã§rollupã®è¨å®ãåºæ¥ã¾ãã ãããã¸ãã¯ä¸è¨ã®ãã¼ã¸ãåèã«è¡ãã¾ãããã¾ããã«ããã㦠é å¸ç¨ã«ã¯è»½ãããããã«ã½ã¼ã¹ãããã¯ä¸è¦ã«ãã¾ããã
3. ãã£ã¬ã¯ããªæ§é ã®è¨å®
ããã¸ã§ã¯ãã®ãã£ã¬ã¯ããªæ§é ã以ä¸ã®ããã«è¨å®ãã¾ãã
my-react-component/ âââ dist/ âââ example/ â âââ src/ â â âââ App.tsx â â âââ index.tsx â âââ public/ â â âââ index.html â âââ package.json âââ src/ â âââ index.ts â âââ components/ â âââ IconPicker.tsx â âââ index.tsx âââ .gitignore âââ package.json âââ rollup.config.js âââ tsconfig.json
4. TypeScriptã®è¨å®
TypeScriptè¨å®ãã¡ã¤ã«ã®ä½æ
ããã¸ã§ã¯ãã®ã«ã¼ãã«tsconfig.jsonãã¡ã¤ã«ãä½æãã以ä¸ã®å 容ã追å ãã¾ãã ããã«é¢ãã¾ãã¦ã¯tsconfigã®å 容ãªã®ã§å²æãã¾ãã
{ "compilerOptions": { "importHelpers": true, "noEmitHelpers": true, "target": "ES5", "module": "ESNext", "declaration": true, "declarationDir": "dist/types", "outDir": "dist", "jsx": "react", "strict": true, "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src"] }
5. Rollupã®è¨å®
Rollupè¨å®ãã¡ã¤ã«ã®ä½æ
ããã¸ã§ã¯ãã®ã«ã¼ãã«rollup.config.jsãã¡ã¤ã«ãä½æãã以ä¸ã®å 容ã追å ãã¾ãã å ã»ã©ã®èª¬æã®éããããã¤æã«è»½ãããããã½ã¼ã¹ããããç¡å¹ã«ãã¦ãã¾ãã
ãã®ä»ã«é¢ãã¦ã¯rollupã®å ¬å¼ã«ãããã®ãä¸è¨ãåèã«ãã¾ããã
import resolve from "@rollup/plugin-node-resolve"; import commonjs from "@rollup/plugin-commonjs"; import peerDepsExternal from "rollup-plugin-peer-deps-external"; import typescript from "@rollup/plugin-typescript"; import { terser } from "rollup-plugin-terser"; import pkg from "./package.json"; export default { input: "src/index.ts", output: [ { file: pkg.main, format: "cjs", sourcemap: false, // ã½ã¼ã¹ããããç¡å¹ã«ãã }, { file: pkg.module, format: "es", sourcemap: false, // ã½ã¼ã¹ããããç¡å¹ã«ãã }, ], plugins: [ peerDepsExternal(), resolve(), commonjs(), typescript({ tsconfig: "./tsconfig.json" }), terser(), ], external: ["react", "react-dom", "@emotion/react"], // Reactã¨ReactDOMãEmotionãå¤é¨ä¾åã¨ãã¦æå® };
ç°¡åã«èª¬æããã¨
- input: "src/index.ts": ãã³ãã«ã®ã¨ã³ããªã¼ãã¤ã³ããæå®ãã¾ãã
- output: åºåè¨å®ãæå®ãã¾ããããã§ã¯CommonJSå½¢å¼ã¨ESã¢ã¸ã¥ã¼ã«å½¢å¼ã®2種é¡ãåºåãã¦ãã¾ããã½ã¼ã¹ãããã¯ç¡å¹ã«è¨å®ããã¦ãã¾ãã
- plugins: 使ç¨ãããã©ã°ã¤ã³ãæå®ãã¾ãã
- peerDepsExternal(): å¤é¨ä¾åãå¤é¨ã«è¨å®ãã¾ãã
- resolve(): Node.jsã®ã¢ã¸ã¥ã¼ã«è§£æ±ºãRollupã§è¡ããããã«ãã¾ãã
- commonjs(): CommonJSã¢ã¸ã¥ã¼ã«ãESã¢ã¸ã¥ã¼ã«ã«å¤æãã¾ãã
- typescript({ tsconfig: "./tsconfig.json" }): TypeScriptããã³ãã«ã«ä½¿ç¨ãã¾ãã
- terser(): ã³ã¼ããå§ç¸®ãã¾ãã
- external: ãã³ãã«ã«å«ããªãå¤é¨ä¾åãæå®ãã¾ãããã®å ´åãReactãReactDOMãEmotionãæå®ããã¦ãã¾ãã
6. ã³ã³ãã¼ãã³ãã®ä½æ
srcãã£ã¬ã¯ããªå ã®componensãã£ã¬ã¯ããªå ã«index.tsxãä½æãã以ä¸ã®ã³ã¼ãã追å ãã¾ãã
export * from './IconPicker';
srcãã£ã¬ã¯ããªå ç´ä¸ã«index.tsãä½æãã以ä¸ã®ã³ã¼ãã追å ãã¾ãã
export { IconPicker } from './components/IconPicker';
srcãã£ã¬ã¯ããªå ã®componensãã£ã¬ã¯ããªå ã®IconPicker.tsxã«ã¯ã©ã¤ãã©ãªã®éçºã³ã¼ããå ¥ãã¾ãã
7. ããã±ã¼ã¸ã®ãã«ã
package.jsonã«ä»¥ä¸ã®ã¹ã¯ãªããã追å ãã¾ãã
"scripts": { "build": "rollup -c", "watch": "rollup -c --watch", "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }
ãã®ã¹ã¯ãªãããå®è¡ããã¨ãsrcãã£ã¬ã¯ããªå ã®ã³ã¼ããdistãã£ã¬ã¯ããªã«ãã«ãããã¾ãã
npm run build
8. Exampleã¢ããªã§ã®åä½ç¢ºèª
Exampleãã£ã¬ã¯ããªã®ã»ããã¢ãã
exampleãã£ã¬ã¯ããªã«srcãã©ã«ãã¨publicãã©ã«ããä½æããããããã«å¿ è¦ãªãã¡ã¤ã«ãä½æãã¾ãã
mkdir -p example/src/public/
example/src/App.tsxã«ä»¥ä¸ã®ã³ã¼ãã追å ãã¾ãã
import React from 'react'; import ReactDOM from 'react-dom'; import MyButton from '@locaop/icon-picker'; const App = () => { return ( <div> <MyButton label="Click Me" onClick={() => alert('Button Clicked!')} /> </div> ); }; ReactDOM.render(<App />, document.getElementById('root'));
example/public/index.htmlã«ä»¥ä¸ã®ã³ã¼ãã追å ãã¾ãã
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React Component Example</title> </head> <body> <div id="root"></div> </body> </html>
Exampleã¢ããªã®è¨å®
example/package.jsonãä½æãã以ä¸ã®å 容ã追å ãã¾ãã
{ "name": "example", "version": "0.1.0", "private": true, "dependencies": { "@emotion/react": "^11.4.0", "@locaop/icon-picker": "file:../", "react": "file:../node_modules/react", "react-dom": "file:../node_modules/react-dom", "react-scripts": "4.0.3" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "predeploy": "npm run build", "deploy": "gh-pages -d build" }, "homepage": "https://locaop-owner.github.io/locaop-react-icons-picker/", "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "gh-pages": "^6.1.1" } }
ãã¡ã¤ã«ã®ãã¹ã®é¨åãéè¦
ãªã«ãä¸è¨ã®package.jsonã§ä¸æè°ãªå ´æã¯ããã¾ããã§ãããï¼ ãããããã§ãã
"react": "file:../node_modules/react", "react-dom": "file:../node_modules/react-dom",
ãªãã«ã¼ãã®srcã®æ¹ï¼éçºãã¦ããæ¹ï¼ã®ç¸å¯¾ãã¹ãå ¥ãã¦ããã®ã§ããããã ããã¯reactæ¬ä½ã®ä¸ã§å¥ã®reactæ¬ä½ãåä½ãããã®ãé²æ¢ããããã§ãã
ã¨ã©ã¼ãåºã¦exampleãåä½ããªãã§ãã
> Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: > 1. You might have mismatching versions of React and the renderer (such as React DOM) > 2. You might be breaking the Rules of Hooks > 3. You might have more than one copy of React in the same app > See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem. > at resolveDispatcher (react.development.js:1465) > at Object.useState (react.development.js:1496) > at ../dist/PlainJsonEditor.js.exports.PlainJsonEditor (PlainJsonEditor.js:38) > at renderWithHooks (react-dom.development.js:14803) > at mountIndeterminateComponent (react-dom.development.js:17482) > at beginWork (react-dom.development.js:18596) > at HTMLUnknownElement.callCallback (react-dom.development.js:188) > at Object.invokeGuardedCallbackDev (react-dom.development.js:237) > at invokeGuardedCallback (react-dom.development.js:292) > at beginWork$1 (react-dom.development.js:23203)
3. You might have more than one copy of React in the same app ï¼æ訳ï¼Reactãè¤æ°å«ã¾ãã¦ããããããã¾ãã
ãã®ããã«é å¸ããéã¯peerDependenciesãåå¨ãã¾ãã
peer ä¾åé¢ä¿ã¯ç¹å¥ãªç¨®é¡ã§ãèªèº«ã®ããã±ã¼ã¸ãå ¬éãããå ´åã®ã¿æ±ããã®ã§ãã
peer ä¾åé¢ä¿ãæã¤ãã¨ã¯ãããªãã®ããã±ã¼ã¸ãããã±ã¼ã¸ãã¤ã³ã¹ãã¼ã«ãã人ã¨å ¨ãåãä¾åé¢ä¿ãå¿ è¦ã¨ããã¨ãããã¨ã§ãã react ã®ããã«ããããã¤ã³ã¹ãã¼ã«ãã人ããã使ç¨ããããåä¸ã® react-dom ã®ã³ãã¼ãæã¤å¿ è¦ãããããã±ã¼ã¸ã§å½¹ã«ç«ã¡ã¾ãã
chore-update--yarnpkg.netlify.app
ã¤ã¾ãexampleã®reactã¨ä¾åé¢ä¿ããªããããã«ã¯åä¸ã®ä¸è¨ã®reactã¨react-domã使ç¨ããå¿ è¦ãããã¾ãã ããããã¼ã«ã«ç°å¢ã§ã¯è§£æ¶ãããã¨ã¯ã§ãã¾ããã
ãªããªã peerDependencies 㯠yarn install ï¼ã¾ã㯠npm install ï¼ã«ç¡è¦ãããã®ã§ãéçºæã«ãã«ãã§ããªããªãããã§ã
解æ¶ããã«ã¯
- npm linkã使ã
- ä¾åããã±ã¼ã¸ã¯ç¸å¯¾ãã¹ã§ä½¿ã
ãåå¨ãã¾ããnpm linkã¯ãã¾ãåä½ããªãã®ã§2ã®ç¸å¯¾ãã¹ã§ä»åã¯è¡ãã¾ããã
次ã«ãå¿ è¦ãªããã±ã¼ã¸ãã¤ã³ã¹ãã¼ã«ãã¾ãã
cd example npm install
9. Exampleã¢ããªã®å®è¡
Exampleã¢ããªãå®è¡ãã¦ãããã±ã¼ã¸ã®åä½ã確èªãã¾ãã
npm start
ãã©ã¦ã¶ã§http://localhost:3000ã«ã¢ã¯ã»ã¹ãããã¿ã³ãæ£ãã表示ãããã確èªãã¾ãã
10. ããã±ã¼ã¸ã®å ¬éæºå
ããã¸ã§ã¯ãã®ã«ã¼ãã®package.jsonã«ä»¥ä¸ã®è¨å®ã追å ãã¾ãã
{ "name": "@locaop/icon-picker", "version": "0.4.1", "description": "This is an icon picker for react-icons.", "main": "dist/index.js", "module": "dist/index.es.js", "types": "dist/types/index.d.ts", "publishConfig": { "access": "public" }, "repository": { "type": "git", "url": "https://github.com/locaop-owner/locaop-react-icons-picker" }, "homepage": "https://locaop.jp", "scripts": { "build": "rollup -c", "watch": "rollup -c --watch", "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }, "keywords": [ "react", "icon", "picker", "icon-picker", "icon-picker-react", "icon-picker-react-component" ], "author": "locaop", "license": "ISC", "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-typescript": "^11.1.6", "@types/react": "^17.0.1", "@types/react-dom": "^17.0.1", "rollup": "^2.79.1", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-terser": "^7.0.2", "typescript": "^5.4.5" }, "dependencies": { "old-react-icons": "npm:react-icons@^3.11.0", "react-icons": "^5.2.1", "tslib": "^2.6.2" }, "peerDependencies": { "@emotion/react": "^11.4.0", "react": "^17.0.1", "react-dom": "^17.0.1" } }
11. npmã¸ã®å ¬é
ãã¨ã¯roll upããããã±ã¼ã¸ãã«ã¼ãããå ¬éã³ãã³ããããã ãã§ãã
ã¾ããnpmã«ãã°ã¤ã³ãã¾ãã
npmã§èªåãä½ã£ãã©ã¤ãã©ãªãé å¸ããããã«ã¯ã¢ã«ã¦ã³ããå¿ è¦ã§ãã npmã®ã¢ã«ã¦ã³ãããªãå ´åã¯ãä¸è¨ã®ãªã³ã¯ãã¯ãªãã¯ãã¦ã¢ã«ã¦ã³ããæ°è¦ç»é²ãã¦ãã ããã npmãµã¤ã:
npm login
次ã«ãããã±ã¼ã¸ãå ¬éãã¾ãã
npm publish
以ä¸ã§ãReactã®npmããã±ã¼ã¸ãå ¬éããã¾ããï¼
ã¾ã¨ã
ãã®è¨äºã§ã¯ãRollupã¨TypeScriptã使ç¨ãã¦Reactã®npmããã±ã¼ã¸ãä½æããexampleãã£ã¬ã¯ããªã§åä½ç¢ºèªããããã®æé ã説æãã¾ãããããã§ãèªåã®ä½æããReactã³ã³ãã¼ãã³ããç°¡åã«å ±æããåä½ã確èªã§ããããã«ãªãã¾ãããã²è©¦ãã¦ã¿ã¦ãã ããï¼
ã³ã¡ã³ãã質åãããã°ãä¸è¨ã«ãé¡ããã¾ãããã£ã¼ãããã¯ããå¾ ã¡ãã¦ãã¾ãï¼