从零开始搭建react组件并且发布npm(三)

401 阅读3分钟

10写一个组件

1、src/components/example 下新建两个文件index.tsx 和 index2.tsx (为什么要新建两个,一会就知道了)

2、src/components/example/index.tsx 
这个我们用hooks模式写

import React, { useState } from 'react';
export interface Props {
  text: string
}

const Example= (props: Props) => {
  const [num, setNum] = useState<number>(0);
  const { text } = props;

  const a = () => {
    console.log(num)
    setNum(num + 1)
  };

  return (
    <div className="wrap" onClick={a}>
      {text}--{num}
    </div>
  );
};

export default Example;


2、src/components/example/index2.tsx
这个我们用class模式写

import React, { Component } from 'react'
type State = {
  num: number
}

type Props = {
  text: string
}
export default class Example2 extends Component<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state = {
      num: 0
    }
  }

  a = () => {
    this.setState({
      num: 1
    })
  }

  render() {
    return (
      <div className="wrap" onClick={this.a}>
        {this.props.text}--{this.state.num}
      </div>
    )
  }
}

3、本地开发在App.tsx 引入组建测试ok

import React, { useState } from 'react';
import './index.scss';
import Example from './components/example'

export interface Props {
  updateModalVisible: boolean;
  text: string
}

const App= (props: Props) => {
  const [name, setName] = useState<number[] | boolean>([]);
  const [arr, setArr] = useState<[]>([]);
  const { text } = props;

  const a = ():string => {
    setName([1,2,3])
    return 's'
  };

  return (
    <div className="wrap" onClick={a}>
      <Example text='d' />
    </div>
  );
};

export default App;

4、src/components/index.tsx 新建一个总入口
先测试class模式
export { default as Example } from './example/index2';

5、开始配置webpack.prod.config

const path = require('path')

module.exports = {
  mode: 'production', // 生产模式会压缩代码
  entry: path.resolve(__dirname, '../src/components/index.tsx'), // 指定打包入口文件
  output: {
    filename: 'index.js', // 打包后的文件名称
    path: path.resolve(__dirname, '../dist'), // 输出路径
    libraryTarget: 'commonjs2', // 需要指定类型,默认是var(感兴趣的可以自行搜索一下)
    library: 'dragon-mobile'
  },

  resolve: {
    // 解决导入的文件可以不用添加后缀名
    extensions: ['.tsx', '.ts', 'jsx', '.js'],
  },

  module: {
    rules: [
      {
        test: /\.(j|t)sx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader',
          options: {
            // transpileOnly: true
          }
        }
      }
    ]
  }
}

5、package.json script 添加 "build": "rm -rf dist && webpack --config config/webpack.prod.config.js",
rm -rf 是我全局的ramrif命令,大家可以自行安装,后期我会改成依赖,写一个脚本

6、修改package.json
设置
{
    "name": "dragon-mobile", // 自己定义,这里自己演示
    "version": "1.0.0",
    "description": ".....",
    "main": "./dist/index.js", // 模块引用的入口文件
    "files": [
        "dist"
    ], 
}

name:发布的包名,默认是上级文件夹名。不得与现在npm中的包名重复。包名不能有大写字母/空格/下滑线!
version:你这个包的版本,默认是1.0.0。对于npm包的版本号有着一系列的规则,模块的版本号采用X.Y.Z的格式,具体体现为:
  1、修复bug,小改动,增加z。
  2、增加新特性,可向后兼容,增加y
  3、有很大的改动,无法向下兼容,增加x
files 字段用于描述我们使用 npm publish 命令后推送到 npm 服务器的文件列表,如果指定文件夹,则文件夹内的所有内容都会包含进来
我们这里上传dist文件夹,指定这个,

package.json 说明 https://javascript.ruanyifeng.com/nodejs/packagejson.html

请自行百度,网上有更多详细的说明

7、npm run build 生成dist/index.js

11 发布npm

1、创建npm 账号(自行创建 https://www.npmjs.com/)

2、本机第一次发布npm
在终端输入npm adduser,提示输入账号,密码和邮箱,然后将提示创建成功,具体如下图。

3、非第一次 npm login 输入你创建的账号和密码,和邮箱,登陆

4、npm publish

自行百度更加详细规则,下面给个例子
https://www.jianshu.com/p/7bba18925fbf

5、发布成功,查看一下自己的npm仓库,是否有npm包

⚠️本地的仓库需要是npm, 否则登录不成功

npm config set registry registry.npmjs.org

12 测试发布的npm包

1、找一个react 项目, npm i xxxxxx 
我这里是npm i dragon-mobile
2、导入包
import { Example } from 'dragon-mobile'

3、页面加载

<Example text='d' />

 ok,正常显示

此时我们已经完成了一个react项目从 框架配置--> 组件 --> 打包 --> 发布的全流程,但是还有很多细节没有注意,而且我们这里只发布了js还没有样式的,下一章接着写打包样式和hooks模式