没有发布过npm包的同窗,可能会对NPM对开发有一种蜜汁敬畏,以为这是一个很高大上的东西。甚至有次面试,面试官问我有没有发过npm包,当时只用过还没写过,我想应该挺难的,就小声说了没有,而后就让我回去了o(╯□╰)o。css
其实,在如今的我看来,npm包就是一个咱们平时常常写的一个export出来的模块而已,只不过跟其它业务代码耦合性低,具备较高的独立性。 固然,要发布一个npm包,除了写的模块组件外,还须要作一些基础的包装工做。 下面我就以最近开发的react-loading组件为例 源码地址,若是对你有帮助的话但愿不要吝啬你的 Starhtml
本文主要记录一下如何开发react组件(以react-loding为例),并在 npm 上发布。废话很少说,进入正题node
在github上新建一个仓库,名字能够本身取。确保你建立的组件名称没有在 npm 上被使用过, 这里咱们用 wsm-loading做为示例。打开编辑器将项目拉到本身本地并初始化react
git clone https://github.com/xxx/wsm-loading.git
cd wsm-loading
npm init
复制代码
运行npm init问题提示列表能够根据本身的我的爱好填写,也能够采起默认的选项。webpack
我么须要开发的是一个React的loading组件,因此咱们要先在项目中安装react依赖git
npm i react react-dom -Des6
咱们的项目将经过webpack4进行构建,安装项目所需的webpack依赖github
npm i webpack webpack-cli webpack-dev-server html-webpack-plugin style-loader css-loader babel-core babel-loader babel-preset-env babel-preset-react -Dweb
在项目中咱们常常会用到scss做为css的编译,所以咱们在安装webpack面试
npm install sass sass-loader node-sass webpack -D
这时上面安装的依赖已经被添加到根目录下的 package.json中了,接下来咱们添加一个 start的脚本,用于启动咱们本地开发的服务器, start以下:
{
"name": "wsm-loading",
"version": "0.0.1",
"description": "这是一个react-loading组件",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --mode development",
},
复制代码
如今让在咱们的项目中建立组件和示例代码目录,目录树结构以下
├── examples // 示例代码存放目录
│ └── src
├── node_modules
├── package.json
└── src // 组件源代码和样式存放目录
└── .babelrc // es6及jsx语法编译
└── .gitignore // git提交管理
└── package-lock.json
└── package.json
└── webpack.config.js webpack配置
复制代码
lodaing组件接收两个props,一个size控制loading的大小,一个color控制loading的颜色
/*** src/index.js ***/
import React, { Component } from "react";
import "./index.scss";
export default class MyComponent extends Component {
render() {
const { color, size } = this.props;
const sizeStyle = {
width: `${size}px`,
height: `${size}px`
};
const colorStyle = {
border: `1px solid ${color}`,
borderColor: `${color} transparent transparent transparent`
};
const ringStyle = Object.assign({}, colorStyle, sizeStyle);
return (
<div className="loading" style={sizeStyle}>
<div className="loading__ring" style={ringStyle} />
<div className="loading__ring" style={ringStyle} />
<div className="loading__ring" style={ringStyle} />
</div>
);
}
}
MyComponent.defaultProps = {
size: '36',
color: '#000'
}
复制代码
loading组件的样式这里就不给了,能够直接从个人代码库中复制到你的项目里css。
接下来咱们添加一个演示demo
<!-- examples/src/index.html -->
<html>
<head>
<title>My Component Demo</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/index.js ***/
import React from 'react';
import { render} from 'react-dom';
import MyComponent from '../../src';
const App = () => (
<MyComponent size='36' color='red' />
);
render(<App />, document.getElementById("root"));
复制代码
以上就完成了一个基本的loading组件,可是咱们还有一个疑问,就是如今引入的loading是在类名为root的元素之中,而一些被普遍使用的UI框架中的loading组件确实在body层,不管你在哪里引入,这样就能够防止loading组件受到父组件的样式的干扰。
咱们哎src目录下新建一个newPortal/newPortal.js文件
import React from 'react';
import ReactDOM from 'react-dom';
class NewPortal extends React.Component {
constructor(props) {
super(props)
this.node = document.createElement('div');
document.body.appendChild(this.node);
}
render() {
const { children } = this.props;
return ReactDOM.createPortal(
children,
this.node,
);
}
}
export default NewPortal
复制代码
将其引入到咱们的loading组件中
import NewPortal from './newPortal/newPortal'
并对组件进行一层包裹
<NewPortal>
<div className="loading" style={sizeStyle}>
<div className="loading__ring" style={ringStyle} />
<div className="loading__ring" style={ringStyle} />
<div className="loading__ring" style={ringStyle} />
</div>
</NewPortal>
复制代码
这里做者是参考这篇文章对组件进行优化的。你们感兴趣能够去了解下。
接下来配置 webpack, 在项目根路径下建立 webpack.config.js文件。关于webpack配置不太了解或不熟悉的能够参考我以前之篇文章webpack详细配置,这里讲不在一一讲解。
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const htmlWebpackPlugin = new HtmlWebpackPlugin({
template: path.join(__dirname, "examples/src/index.html"),
filename: "./index.html"
});
module.exports = {
entry: path.join(__dirname, "examples/src/index.js"),
output: {
path: path.join(__dirname, "examples/dist"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: "babel-loader",
exclude: /node_modules/
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
},
plugins: [htmlWebpackPlugin],
resolve: {
extensions: [".js", ".jsx"]
},
devServer: {
port: 3001
}
};
复制代码
最后须要指定 Babel 须要对哪些文件进行编译,毫无疑问 React 中使用的 JSX 文件须要被编译,让它转换成被主流浏览器都支持的 ES5 ,通用的配置也很简单,只须要添加一对 presets,在项目根目录下添加文件.babelrc
{
"presets": ["env", "react"]
}
复制代码
接下来运行 demo
npm start 启动完成后打开浏览器输入 http://localhost:3001,你将会在页面上看到你写的组件,你能够修改你的代码并保存,页面将会自动刷新,咱们的开发环境已经处于监控模式
咱们要发布被 babel 编译且被压缩后的版本,要让没有使用 babel 的项目也可以正常的使用,好比不能出现 JSX 语法。 首先须要安装 babel cli
npm i babel-cli -D
如今咱们添加 transpile脚本,以便使用 Babel 编译咱们的源代码,同时拷贝一些静态文件(如:css 文件)到目标打包目录dist下 同时指定被编译后的版本为组件的主入口,更改后的 package.json以下
{
"name": "test",
"version": "1.0.0",
"description": "ceshi",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --mode development",
"transpile": "babel src -d dist --copy-files"
},
复制代码
尝试编译
npm run transpile
最后让咱们在项目的根目录下添加.npmignore文件,告诉 npm,咱们项目中哪些文件和文件夹是在发布的包中被忽略掉的
# .npmignore
src
examples
.babelrc
.gitignore
webpack.config.js
复制代码
发布咱们的组件到 npm 上
npm publish
提交npm以前须要去npm上开通本身的帐号,并验证邮箱,这样才能正常的提交上去。在终端使用npm login登录本身的信息
项目上传到git以前,咱们须要配置下.gitignore,在项目的根目录下添加.npmignore文件
# .gitignore
node_modules
dist
复制代码
这样咱们上传时,不会上传node_modules和dist的目录
git add .
git commit -m 'react-loading组件'
git push
复制代码
当咱们不停的陷于业务代码的开发中,何不尝抽出一点时间来作点本身喜欢作的事呢,好比将本身的业务组件抽出来作成一个npm,开源组件库不只能够提升本身还能接触到原来接触不到东西。这只是一个简单的教程,但愿能对你有所启发。
感谢你的阅读!