詳解從 0 發佈 react 組件到 npm 上

我發佈了個人第一個 npm 組件,一個基於 react 的 3d 標籤雲組件。在這途中我也是遇到了不少的坑,花在完善整個發佈流程的時間遠多於寫這個組件自己的時間,因此我記錄下我以爲一個正常的 react 組件的發佈流程javascript

最後記錄這篇文章花的時間比我完成整個組件的時間都多,最終但願能給新手帶來幫助css

在整個發佈組件的過程我作了以下幾件事兒:html

  1. 開發組件
  2. 編寫 Readme
  3. 推送到 github,而且把 demo 放到 github page 上
  4. 發佈組件到 npm 上

開發組件

建立項目文件夾並初始化 npm package ,確保你建立的組件名稱沒有在 npm 上被使用過, 這裏咱們用 react-demo 做爲示例前端

mkdir react-demo
cd react-demo
npm init
複製代碼

npm init 是生成初始的 package.json 的命令,在 npm init 的時候,你能夠根據你本身的須要進行填寫你的組件信息。或者直接使用 npm init -y 採用默認的,後面本身再去修改。java

首先安裝 react 相關的包:node

npm i react react-dom -D
複製代碼

採用 babel 編譯相關的依賴:react

npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react -D
複製代碼

採用 webpack 作構建,webpack-dev-server 做爲本地開發服務器,因此須要安裝以下依賴:webpack

npm i webpack webpack-cli webpack-dev-server -D
複製代碼

我這裏爲了簡單演示,只安裝 babel-loader 用來編譯 jsx,其餘 loader 安裝本身的須要本身安裝。git

npm i babel-loader -D
複製代碼

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

npm i html-webpack-plugin -D
複製代碼

而後再添加上常規的 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 問題能夠私聊我。

而後咱們再建立以下的目錄結構:

├── example // 示例代碼,在本身測試的時候能夠把測試文件放到 src 裏
│   └── src // 示例源代碼
│       ├── index.html // 示例 html
│       └── app.js // 添加到 react-dom 的文件
├── package.json 
├── src // 組件源代碼
│   └── index.js // 組件源代碼文件
├── .babelrc
├── .editorconfig // 沒必要須的,可是建議有
├── .gitignore // 若是要放到 github 上,這個是須要有的
└── webpack.config.js
複製代碼

下面咱們再建立一個最簡單的組件,來進行演示:

/*** 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, 在項目根路徑下建立 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 相對於以前的配置是不一樣的,要用這個配置,版本必定要跟個人相同,否則配置可能會不同。

而後如今執行 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 的時髦徽章,讓人們知道咱們又酷又專業。

想添加什麼樣的徽章看本身喜歡吧,種類有不少。

能夠點擊這裏看我以前寫的 3d 標籤雲的 README。

如今基本上能夠發佈了,可是要是能提供一個在線的 demo 讓別人在用這個組件的時候能夠看到效果就更好了。

在 GitHub Pages 上發佈一個在線 demo

發佈在線 demo 能夠直接用 Github Pages 來幫助咱們託管,經過 webpack 構建生產環境版本,而後發到 Github 上去便可。

首先去 Github 建立一個用來存放你組件代碼的倉庫。

而後把你的項目初始化成 git 項目:

git init
複製代碼

再添加遠程倉庫,將本地倉庫和遠程倉庫關聯起來。

git remote add origin git@github.com:crazylxr/react-demo.git
複製代碼

接下來咱們能夠安裝 gh-pages 來幫助咱們發佈到 github pages:

npm i gh-pages -D
複製代碼

爲了方便記憶,後續能更快的發佈,這些命令咱們能夠寫成 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,之後須要發佈 demo 的時候只須要 npm run publish-demo 便可。

而後咱們就能夠 build 項目以後再將 expamples/dist 發佈到 gh-pages 分支:

npm run build
npm run deploy
複製代碼

或者直接

npm run publish-demo
複製代碼

注意:這裏只會將 expample/src 下的文件發佈到 ph-pages 分支,master 分支依然沒有到 github 上,若是你要把源碼放到 github 的 master 或者其餘分支上,仍是須要本身 push 的。

這個時候,咱們能夠經過 crazylxr.github.io/react-demo 訪問到咱們寫的 demo。crazylxr 是 github 的 username,react-demo 是倉庫名,注意改爲你本身的。

編譯源碼

咱們如今的源碼是 jsx 的,因此咱們須要經過 babeljsx 編譯爲正常瀏覽器能訪問的代碼。咱們能夠經過 babel-cli 來編譯咱們代碼,直接編譯 src 目錄,到 lib 文件夾。更多命令見 babel-cli

npx babel src --out-dir lib
複製代碼

執行完這個命令,就把生成一個 lib 文件夾,而後裏面的 index.js 就是編譯事後的文件,是能夠直接發佈到 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 下面的代碼,只須要執行:

npm run compile
複製代碼

如今咱們已經有編譯好的代碼了,接下來就能夠發佈到 npm 供其餘人使用了。

發佈 npm 包

在發佈之前咱們是須要一些準備:

註冊 npm 帳戶:

在這裏](www.npmjs.com/) 註冊一個 npm 帳號。

登陸

在終端輸入:

npm adduser
複製代碼

也能夠用:

npm login
複製代碼

而後你會獲得一個讓你輸入usernamepassword 和 **email ** 的提示,把它們填在相應的位置。

關於 package.json 須要注意的點

package.json 裏面的配置信息很是重要,我解釋一下幾個重要的配置。

  • name: 包名,若是你學習的話建議加一個 scoped,就是我上面的 @taoweng/react-demo 而不是 react-demo,由於 npm 包特別的多,很容易重複。這樣這個包就會是私有的,能夠經過 npm publish --access=public 將這個包變爲共有的包。

  • version: 包的版本,每次發佈包的版本不能和上次同樣。詳細規範可見這裏

  • 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 包的頁面顯示出來的,因此能填仍是填一下:

最後咱們在項目中添加 .npmignore 文件,跟 .gitignore 的做用同樣,就是在發佈 npm 的時候須要忽略的文件和文件夾:

# .npmignore 
src
examples
.babelrc
.gitignore
webpack.config.js
複製代碼

這個時候咱們就能夠發佈到 npm 了:

npm publish
複製代碼

若是你是私有包,能夠這樣發佈:

npm publish --access=public
複製代碼

結語

之後發佈新版本的時候,只須要更改一下 package.json 裏面的 version 版本號,而後執行 npm publish 和 npm run publish-demo 就能夠同步 npm 和 demo。

不過若是想讓你的組件在社區裏給更多人用,你須要把 README 寫得更好一點,而後添加好自動化測試,否則別人不太敢用。

另外在寫組件以前能夠先了解下有沒有相似的組件了,若是有就直接用吧,我們就站在巨人的肩膀上,把本身寶貴的時間放在創造價值上。

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

參考文章

另外

同時你也能夠在這些地方找到這篇文章:

  1. 我的網站
  2. github blog

另外有興趣能夠關注個人公衆號:前端桃園

相關文章
相關標籤/搜索