前提:你得懂点前端的东西,略懂就行,不懂就别看了,学不会的,因为你可能要踩坑🙃。
一、初始化项目
新建你的项目文件夹,然后把你的项目文件夹初始化。
npm init
在使用初始化命令时,会提示输入项目的名称、版本号、关键词、作者等,如果还没想好这些信息那就combo回车,后续在package.json文件也可进行进行修改。然后你的文件夹就会出现这个package.json文件。
然后顺手添加三个开发、打包相关文件,demo、lib和src,如下
├── demo # 开发时预览代码
├── src # 示例代码目录
├── index.jsx/tsx # 入口 jsx/tsx 文件
├── index.html # 入口 html 文件
└── index.less # 样式文件
├── lib # 组件打包结果目录
├── src # 组件源代码目录
└── index.tsx # 组件源代码
二、安装依赖
2.1 安装React相关依赖
npm i react react-dom -D
2.2 安装Webpack相关依赖(想看其他打包方式的就别往下看了,浪费生命)
提下这个webpack-merge包:生产环境和开发环境做区分,不重复写配置,保留一个 "common( 公共 )" 配置。配置合并。此工具会引用 “common” 配置,so就没必要再在环境特定env的配置中编写重复代码。
npm i webpack webpack-cli webpack-dev-server webpack-merge -D
顺手在你的项目文件下创建webpack配置相关文件,新增config文件夹,该文件夹下增加三个js配置文件,如下:
├── config # webpack配置
├── webpack.base.js # 公共配置
├── webpack.dev.config.js # 开发环境配置
└── webpack.prod.config.js # 生产-打包发布环境配置
2.3 安装css相关依赖
npm i postcss postcss-loader postcss-preset-env style-loader css-loader less-loader less mini-css-extract-plugin -D
2.4 安装babel相关依赖
npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react -D
2.5 安装typescript相关依赖
npm i @types/react @types/react-dom ts-loader @babel/preset-typescript
npm i babel-loader -D
到目前为止你的文件目录应该如下:
├── node_modules
├── config # webpack配置
├── webpack.base.js # 公共配置
├── webpack.dev.config.js # 开发环境配置
└── webpack.prod.config.js # 生产-打包发布环境配置
├── demo # 开发时预览代码
├── src # 示例代码目录
├── index.jsx/tsx # 入口 jsx/tsx 文件
├── index.html # 入口 html 文件
└── index.less # 样式文件
├── lib # 组件打包结果目录
├── src # 组件源代码目录
└── index.tsx # 组件源代码
├── package.json
└── package-lock.json
三、配置webpackconfig
3.1 配置webpack.base.js
module.exports = {
resolve: {
// 定义 import 引用时可省略的文件后缀名
extensions: [".js", ".jsx", ".ts", ".tsx"],
},
module: {
rules: [
{
// 编译处理 js 和 jsx 文件
test: /(\.js(x?))$/,
use: [
{
loader: "babel-loader",
},
],
exclude: /node_modules/, // 只解析 src 目录下的文件
},
{
// 编译处理 js 和 jsx 文件
test: /(\.ts(x?))$/,
use: [
{
loader: "ts-loader",
},
],
exclude: /node_modules/, // 只解析 src 目录下的文件
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: "url-loader",
// options: {
// name: 'images/[name].[ext]',
// esModule: false,
// },
},
],
// type: 'javascript/auto'
},
],
},
};
3.2 配置webpack.dev.config.js
const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.js'); // 公共配置
const devConfig = {
mode: 'development', // 开发模式
entry: path.join(__dirname, "../demo/src/index.jsx"), // 入口,处理资源文件的依赖关系
output: {
path: path.join(__dirname, "../demo/src/"),
filename: "dev.js",
},
module: {
rules: [
{
test: /.less$/,
exclude: /.min.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: {
mode: "global"
}
}
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// 其他选项
},
],
],
},
},
},
{ loader: 'less-loader' }
]
},
{
test: /.min.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
]
},
]
},
devServer: {
static: path.join(__dirname, '../demo/src/'),
compress: true,
host: '127.0.0.1',
port: 6666, // 启动端口
open: true // 打开浏览器
},
};
module.exports = merge(devConfig, baseConfig); // 合并配置
3.3 配置webpack.prod.config.js
const path = require("path");
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base.js"); // 引用公共的配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 用于将组件的css打包成单独的文件输出到`lib`目录中
const prodConfig = {
mode: "production", // 生产模式
entry: {
index: path.join(__dirname, "../src/index.tsx"),
},
output: {
path: path.join(__dirname, "../lib/"),
filename: "index.js",
libraryTarget: "umd", // 采用通用模块定义
libraryExport: "default", // 兼容 ES6 Module、CommonJS 和 AMD 模块规范
},
module: {
rules: [
{
test: /.less$/,
exclude: /.min.css$/,
use: [
{ loader: "style-loader" },
{ loader: MiniCssExtractPlugin.loader },
{
loader: "css-loader",
options: {
modules: {
mode: "global",
},
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{
// 其他选项
},
],
],
},
},
},
{
loader: "less-loader",
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "index.min.css", // 提取后的css的文件名
}),
],
externals: {
// 定义外部依赖,避免把react和react-dom打包进去
react: {
root: "React",
commonjs2: "react",
commonjs: "react",
amd: "react",
},
"react-dom": {
root: "ReactDOM",
commonjs2: "react-dom",
commonjs: "react-dom",
amd: "react-dom",
},
},
};
module.exports = merge(prodConfig, baseConfig); // 合并配置
3.4 添加并配置.babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
]
}
配置完成之后需要修改package.json的sctrpts中的本地运行和打包命令换成上面的修改的配置,命令如下:
"scripts": {
...
"dev": "webpack-dev-server --config config/webpack.dev.config.js",
"build": "webpack --config config/webpack.prod.config.js"
},
到目前为止 接下来就是紧张刺激的组件开发环节了。先给项目添加相关文件,如下(之前写的漏了啥给忘了,尬,忽略吧)
补充 tsconfig文件配置-来自评论区
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"esModuleInterop":true,
"allowJs":true,
"jsx": "react"
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"demo/**/*.tsx",
"demo/**/*.ts"
],
}
四、组件开发
4.1 开发组件(就像你正常开发一样哈,不赘述)
在src/index.tsx中开发你的组件,在src/index.less开发你的样式
import React from 'react';
function YourCom() {
return <div className="yourcom">YourCom</div>
}
export default YourCom
.yourcom {
background:#dad;
}
4.2 本地调试组件(也像你正常开发一样,不赘述,如果你对你的组件很自信,这一步pass)
就像你正常开发一样,开发时实时预览组件的效果你是不是得本地运行,不是请pass,在demo目录下新建index.html和index.jsx/tsx两个文件,index.html的内容以下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>YourCom</title>
<style>
html, body, p {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="root"></div>
//这里引用dev环境配置里面打包的对象文件
<script src="dev.js"></script>
</body>
</html>
index.jsx/tsx内容就是应用你组件的react项目根节点,内容如下:
import React from "react"
import { createRoot } from 'react-dom/client';
import YourCom from '../../src/index';//你的组件
import './index.less' //这个是demo的index,别搞错了哈,这个样式文件自己随意写吧
const App = () => {
return (
<div className="container" style={{height:"100%",width:"100%"}}>
<div className="text">
<p>Demo</p>
</div>
<YourCom />
</div>
);
}
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
如上文件的代码编写完,就可在根目录下打开cmd,执行npm run dev命令,进你的主页面(host和port在配置文件有,也可以自己配),能看到你组件,那就成功了,如果没有,要么你组件写的有问题,要么你上面配置没配对(抄作业都抄不好?)
4.3 打包和测试组件
在打包发布之前,还有一个坑要填写,如果你用的是严格模式"strict": true,你还得把你组件申明写好了!!!。不然你在引用的时候会提示,没有TS类型!!
首先修改你的tsconfig.json中"noEmit"字段改成false,
然后在src下和组件index同级添加index.d.ts文件,如下:
declare module 'yourcomname'
declare module '*.less' {
const content: any;
export default content;
}
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.gif'
declare module '*.bmp'
declare module '*.tiff'
1.打包组件
完成组件的开发,在发包以前,需要对本身组件的功能进行打包和测试。前面已经在package.json中添加了打包组件的命令,然而在执行npm run build以前,还需要在package.json中修改main字段,用作是声明组件的入口文件。
"main": "lib/index.js",
再给package.json润色下打包的配置,package.json的代码如下:
{
"name": "yourcomname", //你组件名字
"version": "0.0.1", //组件版本,npm pub的版本每次都得不一样
"description": "HelloWorld", // √ 组件简介
"main": "lib/index.js", //√ 打包之后的主入口就是你的lib
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack-dev-server --config config/webpack.dev.config.js",
"build": "webpack --config config/webpack.prod.config.js"
},
"keywords": [
"react",
"text-auto",
"width-auto",
"text-width-auto"
], // √ 组件的关键词,便于搜索
"author": "jacky010", //作者原则上是你自己
"license": "ISC", //协议
... ...
接下来,则可使用npm run build命令打包开发好的组件,如果失败了,很遗憾你抄作业有抄错了,怎么肥四,如果成功,项目根目录的lib目录下会出现index.js文件(如果组件含有样式文件,那将会出现index.min.css文件,就是而配置文件中压缩的css这是个大坑,后面使用要填)。
2.测试打包组件
使用npm link把打包以后的组件引入到全局node-modules中;
然后进入demo/src文件夹下,执行npm link yourcomname命令(注意:这里的name一定要是package.json配置的name,必须一致!!!!!!);而后修改demo/src/index.jsx/tsx的内容:
// import YourCom from '../../src/index'; // 注释它引入组件
import YourCom from 'yourcomname'; // √ 引入node-modules中的组件
如果现在的页面和你之前直接开发编译的页面一样那么恭喜你,离成功还有一步之遥!!!!
五、编写Readme文档(不想写或者后期可以补的,直接pass)
手写也行用插件也行,这里采用的是readme-md-generator插件,readme自动生成工具。
执行npx readme-md-generator命令,接着可以做一些配置,也可以一路enter键,最后再去生成的文件中做详细配置。这个你自己去玩吧,下一步!!
六、发布!!!
发布npm包需要登录npm账号
npm adduser
按提示信息输入本身的用户名、密码及邮箱后,若是命令行输出Logged in as <user> on https://registry.npmjs.org/,则说明帐号注册并登录成功。
若是已经有npm帐号,则直接使用npm login登录。
切换你要上传的npm仓库地址,可使用npm config list查看当前使用的源地址。以下是官方地址。
npm config set registry http://registry.npmjs.org
使用命令npm pub默认的发包方式,执行package.json中的脚本:
npm pub
如果成功了那么恭喜你结束了,可以去搜搜你发布的组件了!!!
当然你可以把你的组件上传到git仓库,方便用户查看和提issue或者star
七、使用组件
找个空白的项目,安装你的组件。
npm i yourcomname
import YourCOm from "yourcomname";
import 'yourcomname/lib/index.min.css' //没有样式文件就不要,有的话得加你压缩的css,不然你样式就丢了