詳解從 0 發(fā)布 react 組件到 npm 上

我發(fā)布了我的第一個 npm 組件项滑,一個基于 react 的 3d 標簽云組件费韭。在這途中我也是遇到了很多的坑茧球,花在完善整個發(fā)布流程的時間遠多于寫這個組件本身的時間,所以我記錄下我覺得一個正常的 react 組件的發(fā)布流程

最后記錄這篇文章花的時間比我完成整個組件的時間都多星持,最終希望能給新手帶來幫助

在整個發(fā)布組件的過程我做了如下幾件事兒:

  1. 開發(fā)組件
  2. 編寫 Readme
  3. 推送到 github抢埋,并且把 demo 放到 github page 上
  4. 發(fā)布組件到 npm 上

開發(fā)組件

創(chuàng)建項目文件夾并初始化 npm package ,確保你創(chuàng)建的組件名稱沒有在 npm 上被使用過督暂, 這里我們用 react-demo 作為示例

mkdir react-demo
cd react-demo
npm init

npm init 是生成初始的 package.json 的命令揪垄,在 npm init 的時候,你可以根據(jù)你自己的需要進行填寫你的組件信息逻翁〖⑴或者直接使用 npm init -y 采用默認的,后面自己再去修改八回。

首先安裝 react 相關的包:

npm i react react-dom -D

采用 babel 編譯相關的依賴:

npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react -D

采用 webpack 做構建酷愧,webpack-dev-server 作為本地開發(fā)服務器,所以需要安裝如下依賴:

npm i webpack webpack-cli webpack-dev-server -D

我這里為了簡單演示缠诅,只安裝 babel-loader 用來編譯 jsx溶浴,其他 loader 安裝自己的需要自己安裝。

npm i babel-loader -D

另外再安裝一個 webpack 插件 html-webpack-plugin 管引,用來生成 html:

npm i html-webpack-plugin -D

然后再添加上常規(guī)的 startbuild 腳本戳葵,package.json 如下:

{
  "name": "react-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

當然,你也可以直接把我這個 package.json 復制過去汉匙,然后 npm install 進行依賴的安裝,也可以一個一個的安裝生蚁。

一個最基本的組件只需要編譯 jsx噩翠,所以我這里沒有安裝 css 以及處理其他的 loader,這篇文章的重點不是講 webpack 的邦投,所以其他的自行解決伤锚,有 webpack 問題可以私聊我。

然后我們再創(chuàng)建如下的目錄結構:

├── example // 示例代碼志衣,在自己測試的時候可以把測試文件放到 src 里
│   └── src // 示例源代碼
│       ├── index.html // 示例 html
│       └── app.js // 添加到 react-dom 的文件
├── package.json 
├── src // 組件源代碼
│   └── index.js // 組件源代碼文件
├── .babelrc
├── .editorconfig // 不必須的屯援,但是建議有
├── .gitignore // 如果要放到 github 上猛们,這個是需要有的
└── webpack.config.js

下面我們再創(chuàng)建一個最簡單的組件,來進行演示:

/*** src/index.js ***/
import React from 'react';
const ReactDemo = () => (
 <h1>這是我的第一個 react npm 組件</h1>
);
export default ReactDemo;

接下來添加一個 demo

<!-- examples/src/index.html -->
<html>
<head>
    <title>My First React Component</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
    <div id="root"></div>
</body>
</html>
/*** examples/src/app.js ***/
import React from 'react'
import { render } from 'react-dom'
import ReactDemo from '../../src'

const App = () => <ReactDemo />
render(<App />, document.getElementById('root'))

注意 demo 中的 ReactDemo 是從 ../../src 中導入的

接下來配置非常簡單的 webpack, 在項目根路徑下創(chuàng)建 webpack.config.js 文件

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
    template: path.join(__dirname, "./example/src/index.html"),
    filename: "./index.html"
});

module.exports = {
    entry: path.join(__dirname, "./example/src/app.js"),
    output: {
        path: path.join(__dirname, "example/dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [{
            test: /\.(js|jsx)$/,
            use: "babel-loader",
            exclude: /node_modules/
        }]
    },
    plugins: [htmlWebpackPlugin],
    resolve: {
        extensions: [".js", ".jsx"]
    },
    devServer: {
        port: 3001
    }
};

Webpack 的配置文件主要做了如下事情:

  • 使用 example/src/index.js 作為項目入口狞洋,處理資源文件的依賴關系
  • 通過 babel-loader 來編譯處理 js 和 jsx 文件
  • 通過 html-webpack-plugin 自動注入編譯打包好的腳本文件
  • 為 demo 啟動端口為 3001 的服務

然后再配置一下 babel弯淘,咱們的 babel 主要做兩件事,將 jsx 編譯成 es5吉懊,然后再加一個通用的 env庐橙,所以 .babelrc 配置如下:

{
    "presets": ["@babel/preset-env", "@babel/preset-react"]
}

可以看到之前的 package.json ,我這里 babel 安裝的是 7.x借嗽,那么 babel-loader 就應該是 8.x 才行态鳖,然后 babel 7.x 相對于之前的配置是不同的,要用這個配置恶导,版本一定要跟我的相同浆竭,不然配置可能會不一樣。

然后現(xiàn)在執(zhí)行 npm start惨寿,然后再訪問 localhost:3001 就可以訪問到了邦泄。

編寫 README

編寫 README,如果你不知道該如何編寫缤沦,我給你提幾點建議虎韵,你可以選擇你覺得必要的點來寫:

  1. logo
  2. 官方主頁
  3. 介紹
  4. 安裝
  5. 快速開始
  6. 功能列表
  7. 截圖
  8. todoList
  9. 不足之處
  10. FAQ
  11. Change Log(更新日志)

添加徽章

當你寫完 README 之后,我們將添加一些來自 shields.io 的時髦徽章缸废,讓人們知道我們又酷又專業(yè)包蓝。

image

想添加什么樣的徽章看自己喜歡吧,種類有很多企量。

可以點擊這里看我之前寫的 3d 標簽云的 README测萎。

現(xiàn)在基本上可以發(fā)布了,但是要是能提供一個在線的 demo 讓別人在用這個組件的時候可以看到效果就更好了届巩。

在 GitHub Pages 上發(fā)布一個在線 demo

發(fā)布在線 demo 可以直接用 Github Pages 來幫助我們托管硅瞧,通過 webpack 構建生產環(huán)境版本,然后發(fā)到 Github 上去即可恕汇。

首先去 Github 創(chuàng)建一個用來存放你組件代碼的倉庫腕唧。

然后把你的項目初始化成 git 項目:

git init

再添加遠程倉庫,將本地倉庫和遠程倉庫關聯(lián)起來瘾英。

git remote add origin git@github.com:crazylxr/react-demo.git

接下來我們可以安裝 gh-pages 來幫助我們發(fā)布到 github pages:

npm i gh-pages -D

為了方便記憶枣接,后續(xù)能更快的發(fā)布,這些命令我們可以寫成 npm-scriprt缺谴,所以我們增加兩個腳本:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "deploy": "gh-pages -d examples/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

添加了 deploy 腳本和 publish-demo但惶,以后需要發(fā)布 demo 的時候只需要 npm run publish-demo 即可。

然后我們就可以 build 項目之后再將 expamples/dist 發(fā)布到 gh-pages 分支:

npm run build
npm run deploy

或者直接

npm run publish-demo

注意:這里只會將 expample/src 下的文件發(fā)布到 ph-pages 分支,master 分支依然沒有到 github 上膀曾,如果你要把源碼放到 github 的 master 或者其他分支上县爬,還是需要自己 push 的。

這個時候添谊,我們可以通過 crazylxr.github.io/react-demo 訪問到我們寫的 demo财喳。crazylxr 是 github 的 username,react-demo 是倉庫名碉钠,注意改成你自己的纲缓。

編譯源碼

我們現(xiàn)在的源碼是 jsx 的,所以我們需要通過 babeljsx 編譯為正常瀏覽器能訪問的代碼喊废。我們可以通過 babel-cli 來編譯我們代碼祝高,直接編譯 src 目錄,到 lib 文件夾污筷。更多命令見 babel-cli

npx babel src --out-dir lib

執(zhí)行完這個命令工闺,就把生成一個 lib 文件夾,然后里面的 index.js 就是編譯過后的文件瓣蛀,是可以直接發(fā)布到 npm 的文件陆蟆。

然后將這個編譯命令寫到 script 里,package.json 如下:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "compile": "npx babel src --out-dir lib",
    "deploy": "gh-pages -d example/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

那么以后要編譯 src 下面的代碼惋增,只需要執(zhí)行:

npm run compile

現(xiàn)在我們已經有編譯好的代碼了叠殷,接下來就可以發(fā)布到 npm 供其他人使用了。

發(fā)布 npm 包

在發(fā)布以前我們是需要一些準備:

注冊 npm 賬戶:

在這里](https://www.npmjs.com/) 注冊一個 npm 賬號诈皿。

登錄

在終端輸入:

npm adduser

也可以用:

npm login

然后你會得到一個讓你輸入username林束、password 和 **email ** 的提示,把它們填在相應的位置稽亏。

關于 package.json 需要注意的點

package.json 里面的配置信息非常重要壶冒,我解釋一下幾個重要的配置。

  • name: 包名截歉,如果你學習的話建議加一個 scoped胖腾,就是我上面的 @taoweng/react-demo 而不是 react-demo,因為 npm 包特別的多瘪松,很容易重復咸作。這樣這個包就會是私有的,可以通過 npm publish --access=public 將這個包變?yōu)楣灿械陌?/p>

  • version: 包的版本宵睦,每次發(fā)布包的版本不能和上次一樣性宏。詳細規(guī)范可見這里

  • description:包的簡介。

  • repository:適合寫 Github 地址状飞,建議寫成::username/:repository

  • license:認證。不知道該用什么的诬辈,就寫MIT 吧酵使。

  • main:包的入口文件。就是引入這個包的時候去加載的入口文件焙糟。

  • keywords:添加一些關鍵詞更容易使你的包被搜索到口渔。

更詳細的 package.json 配置可見官網

我這里簡單的添加了這些信息:

{
  "name": "@taoweng/react-demo",
  "version": "1.0.0",
  "description": "react demo",
  "main": "lib/index.js",
  "repository": "crazylxr/react-demo",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open development",
    "build": "webpack --mode production",
    "compile": "npx babel src --out-dir lib",
    "deploy": "gh-pages -d example/dist",
    "publish-demo": "npm run build && npm run deploy"
  },
  "keywords": ["react", "demo"],
  "author": "taoweng",
  "license": "MIT",
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "gh-pages": "^2.0.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "webpack": "^4.29.0",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {}
}

這些配置信息都會在 npm 包的頁面顯示出來的穿撮,所以能填還是填一下:

image

最后我們在項目中添加 .npmignore 文件缺脉,跟 .gitignore 的作用一樣,就是在發(fā)布 npm 的時候需要忽略的文件和文件夾:

# .npmignore 
src
examples
.babelrc
.gitignore
webpack.config.js

這個時候我們就可以發(fā)布到 npm 了:

npm publish

如果你是私有包悦穿,可以這樣發(fā)布:

npm publish --access=public

結語

以后發(fā)布新版本的時候攻礼,只需要更改一下 package.json 里面的 version 版本號,然后執(zhí)行 npm publish 和 npm run publish-demo 就可以同步 npm 和 demo栗柒。

不過如果想讓你的組件在社區(qū)里給更多人用礁扮,你需要把 README 寫得更好一點,然后添加好自動化測試瞬沦,不然別人不太敢用太伊。

另外在寫組件之前可以先了解下有沒有類似的組件了,如果有就直接用吧逛钻,咱們就站在巨人的肩膀上僚焦,把自己寶貴的時間放在創(chuàng)造價值上。

最后整個項目的源代碼見 github

參考文章

另外

同時你也可以在這些地方找到這篇文章:

  1. 個人網站
  2. github blog

另外有興趣可以關注我的公眾號:前端桃園

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屡江,隨后出現(xiàn)的幾起案子芭概,更是在濱河造成了極大的恐慌,老刑警劉巖惩嘉,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罢洲,死亡現(xiàn)場離奇詭異,居然都是意外死亡文黎,警方通過查閱死者的電腦和手機惹苗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耸峭,“玉大人桩蓉,你說我怎么就攤上這事±湍郑” “怎么了院究?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵洽瞬,是天一觀的道長本鸣。 經常有香客問我枢冤,道長,這世上最難降的妖魔是什么浊伙? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任样漆,我火速辦了婚禮为障,結果婚禮上,老公的妹妹穿的比我還像新娘放祟。我一直安慰自己鳍怨,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布跪妥。 她就那樣靜靜地躺著鞋喇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骗奖。 梳的紋絲不亂的頭發(fā)上确徙,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音执桌,去河邊找鬼鄙皇。 笑死,一個胖子當著我的面吹牛仰挣,可吹牛的內容都是我干的伴逸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼膘壶,長吁一口氣:“原來是場噩夢啊……” “哼错蝴!你這毒婦竟也來了?” 一聲冷哼從身側響起颓芭,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤顷锰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亡问,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體官紫,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年州藕,在試婚紗的時候發(fā)現(xiàn)自己被綠了束世。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡床玻,死狀恐怖毁涉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情锈死,我是刑警寧澤贫堰,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布穆壕,位于F島的核電站,受9級特大地震影響严嗜,放射性物質發(fā)生泄漏粱檀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一漫玄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧压彭,春花似錦睦优、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至询一,卻和暖如春隐孽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背健蕊。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工菱阵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缩功。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓晴及,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嫡锌。 傳聞我的和親對象是個殘疾皇子虑稼,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355