虽说现在市面上组件库相当多了,但是还有一些组件特定场景市面上没有,公司内部一些不同项目,有类似相同组件可以直接复用,避免重复造轮子,就可以直接制作一个npm包,下次直接使用。
注意:文中的每一步都很重要,都是踩过的坑
一、准备前提
1、注册npm账号
地址:https://www.npmjs.com/signup
注意:注册完后,记得验证你的邮件地址!一定!否则会在提交组件包的时候报403错误,那是因为没有验证你的邮箱。
二、创建空工程
1、创建新的文件夹
2、进入该文件夹,使用cmd命令,npm进入安装项目流程
//安装
npm init
3、对应的字段:
package name: 组件包名称,注意不能和npm上面已经存在的同名
version: (1.0.0) 版本
description: 描述
entry point: (index.js) 入口文件,默认为index
test command: (可以为空)
git repository: (可以为空)
keywords: (可以为空)
author: 作者
license: (ISC)
创建完成后,该目录下会多一个package.json文件,内容如下
上面截图的文件可随意修改,但是发布时候需遵守规则:
1、版本号必须每次都修改
2、名称保持和上一次不变
三、安装工程需要的依赖包
npm install react react-dom -D
npm install @babel/cli @babel/core @babel/plugin-syntax-jsx @babel/plugin-transform-runtime @babel/preset-env @babel/preset-react -D
npm install style-loader css-loader babel-loader less-loader less -D
npm install html-webpack-plugin webpack webpack-cli webpack-dev-server -D
上面的安装依赖我把它分为4部分好理解:
1、react基础部分,react依靠react、react-dom(vue的话可以自行查看需要啥)
react :react语法
react-dom:react和页面的dom打交道依赖
2、编译必须要的模块
@babel/cli
@babel/core: 把开发的nodejs编译成前端可以运行的js代码
@babel/preset-react: 把react编译成可执行js
@babel/preset-env
@babel/plugin-transform-runtime
@babel/plugin-syntax-jsx
3、项目各种loader依赖
style-loader:处理 dom style 标签里面的css(处理行内样式)
css-loader:处理css样式
less-loader :处理less样式
less:less样式依赖(样式我用less,需要scss的同学自行安装scss)
babel-loader:负责调用上面所有@babel的依赖模块
4、webpack脚手架
webpack:webpack主程序 ,webpack-cli:webpack编译工具脚手架
html-webpack-plugin: 插件,处理html的工具
webpack-dev-server: 编译运行工具,npm run start 实际调用的方法
其中 - D的意思是将依赖安装到devDependencies这里,一般来会默认安装到dependencies字段里,区别是dependencies会在打包时候进dist文件夹
有需要可以自行安装自己要的依赖,上面几个是我写组件必要的几个依赖,因为我没有写对应的依赖版本所以安装时候会以最新版本安装。
四、开始配置工程
1、新建如下目录结构和文件
#目录结构如下
├── package.json 依赖包管理文件
├── .gitignore 上传git时候忽略不传的文件
├── public
├── index.html html静态页面
└── app.js webpack入口文件
└── src 组件包源码文件夹
├── index.jsx
├── index.less
├── index.js 暴露你的组件入口文件,即引用组件包时的入口文件,文件名和package.json中main字段同名
├── webpack.config.js webpack配置文件
├── babel.config.js @babel的配置文件(webpack4版本的叫做.babelrc )
2、编写webpack.config.js的配置,以下是最基础的配置
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
/**
* webpack插件将打包好的文件注入到html模板里
* @type {HtmlWebpackPlugin}
*/
const htmlWebpackPlugin = new HtmlWebpackPlugin({
template: path.join(__dirname, "./public/index.html"),
filename: "./index.html"
});
module.exports = {
mode: 'development',
entry: path.join(__dirname, "./public/app.js"), //入口文件
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {
rules: [{
test: /\.js$|.jsx/, //正则匹配文件名称
use: "babel-loader", //会去调用babel.config.js里的所有babel的配置
exclude: /node_modules/
}, {
test: /\.css|l.ess$/,
use: ["style-loader", "css-loader", "less-loader"]
}]
},
plugins: [htmlWebpackPlugin], //插件:自动注入编译打包好的文件
resolve: {
extensions: [".js", ".jsx"]
},
devServer: {
port: 3001, //端口号
open: true, // 自动打开浏览器
compress: true, // 启动gzip压缩
}
};
上面的less-loader没有启用lessmodules模块化比较不好,假设现在项目有好几个组件,那么模块化就可以避免我们不同组件的样式污染,如果不开启就不生效,如下例子:
// index.jsx文件
import './exp1.less'; //普通用法
import styles from './exp2.less'; //less module写法
如果没有启用模块化这种写法样式将不生效,dom元素上不会有class样式
所以得将webpack.config.js修改如下:
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
/**
* webpack插件将打包好的文件注入到html模板里
* @type {HtmlWebpackPlugin}
*/
const htmlWebpackPlugin = new HtmlWebpackPlugin({
template: path.join(__dirname, "./public/index.html"),
filename: "./index.html"
});
module.exports = {
mode: 'development', //这个值有3种:production、development、none
entry: path.join(__dirname, "./public/app.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {
rules: [{
test: /\.js$|.jsx/,
use: "babel-loader",
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{loader: "style-loader"},
{loader: "css-loader"}], //打包处理css样式表的第三方loader
}, {
//只为less启用模块化
test: /\.less$/,
use: [
{loader: "style-loader"},
{
loader: "css-loader", options: {
modules: {localIdentName: "[path][name]-[local]-[hash:5]"}
}
},
{loader: "less-loader"},
]
}]
},
plugins: [htmlWebpackPlugin], //插件:自动注入编译打包好的文件
resolve: {
extensions: [".js", ".jsx"]
},
devServer: {
port: 3001, //端口号
open: true, // 自动打开浏览器
compress: true, // 启动gzip压缩
}
};
接下来往babel.config.js添加编译时候需要的loader配置:
module.exports = {
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/plugin-syntax-jsx", "@babel/plugin-transform-runtime"]
}
3、编写组件
这个是核心部分,就是说这里是你的组件
------------- ./src/index.jsx
import React, {Component, useState, memo} from 'react';
import styles from './index.less';
function Index() {
return
组件包测试
}
export default memo(Index);
------------- ./src/index.less
.color {
color: red;
}
4、对外暴露组件,编辑根目录下的index.js文件
我这里叫Test,使用组件包引入时候就是Test组件。别人在引用组件包时候会从该文件作为入口(package.json的main字段可以配置),这个文件有两种写法,第一种:
'use strict';
var Test = require('./src/index.jsx');
module.exports = Test;
第二种:
import Test from './src/index.jsx'
export default Test
5、编写webpack读取的入口文件 public/app.js
webpack启动、编译、打包都会从这个文件作为入口(webpack那边配置的)
import React from 'react'
import {render} from 'react-dom'
import ReactDemo from '../src/index.jsx' //引入组件
const App = () => {
return
// return 1111111111111
};
render( , document.getElementById('root')); //获取虚拟dom的挂载节点
6、编写html模板,public/index.html文件。
我们知道spa单页面都是依据一个html模板上面引入js创建虚拟dom生成到这个html上面,所以需要有一个挂载的实例模板。
第一个组件包
7、编写.gitignore文件
这个文件可以配置git上传时候忽略哪些文件不想传上去,同时发布组件包的时候它也会按照这个文件来,忽略哪些不上传。
# Created by .ignore support plugin (hsz.mobi)
node_modules/
dist/
8、添加项目启动命令:修改package.json文件
给该文件的scripts里添加两个系统命令,一个是启动命令,一个是打包命令(制作组件包用的比较少)。注意webpack4的版本可能不是 webpack server --mode development,这个需要自己对应版本。
"scripts": {
"start": "webpack server --mode development",
"build": "webpack --mode development"
},
接下来本地启动试下看下效果,命令:npm run start ,如果启动时候报错:[webpack-cli] ReferenceError: BigInt is not defined
说明是node版本问题,需要安装高点版本的node,可以使用nvm来管理node版本,这里不多说,我切换为node 12.0.0版本就可以。
五、发布
到此为止,我们已经配置好了工程,接下来需要把组件包发布上去
1、发布规则
1、组件包名称不能与npm上已经存在的一致,必须唯一性
2、每次发布必须修改版本号
3、发布的源必须是npm,有的设置了淘宝或者其他源,需要设置回npm源。
例如你是淘宝源你需要:
查看设置过的所有的源:npm config get registry
设置当前源为npm:npm config set registry https://registry.npmjs.org/
发布完成后设置回淘宝源:npm config set registry https://registry.npm.taobao.org
2、发布流程
1、登录注册好的npm账号:npm login
输入对应的账号、密码、邮箱即可
2、发布上去:npm publish
没有报错则表示成功