在material-ui基础上分装自己的组件库并发布到npm
一. webpack构建项目,创建一个项目文件,文件结构如下
package.json
注意:所有依赖都安装在 devDependencies中;
这里有用到peerDependencies,这里的意思是避免重复依赖,比如@material-ui/core在我的组件库被引入一次,在使用项目中又会再次被引入,避免两次安装冗余,以及两个版本差异带来的分险,所以用到了peerDependencies,具体左右可百度。
{ "name": "test-library-hybird-libs", "version": "1.0.5", "description": "",
//包的入口地址 "main": "dist/src/widget/index.js", "files": [ "dist" ], "keywords": [], "author": "", "license": "MIT", "private": false,
//仓库地址 "repository": { "type": "git", "url": "https://www.npmjs.com/package/test-library-hybird-libs" },
//包的主页url "homepage": "https://www.npmjs.com/package/test-library-hybird-libs", "scripts": { "start": "webpack-dev-server --config webpack.dev.config.js", "dev": "webpack-dev-server --config webpack.dev.config.js", "build": "rimraf ./dist & rimraf ./dist.zip && md dist && webpack --config webpack.prod.config.js " }, "dependencies": { }, "devDependencies": { "@babel/core": "7.15.8", "@babel/plugin-transform-runtime": "7.16.0", "@babel/preset-env": "7.2.3", "@babel/preset-react": "7.16.0", "@babel/runtime": "7.16.0", "babel-loader": "8.2.2", "css-loader": "0.28.9", "eslint-config-airbnb-base": "14.2.1", "eslint-plugin-eslint-plugin": "3.6.1", "file-loader": "6.2.0", "html-webpack-plugin": "^5.5.0", "prop-types": "15.7.2", "style-loader": "0.19.1", "webpack": "5.58.1", "webpack-cli": "4.9.0", "webpack-dev-server": "^4.5.0", "react": "17.0.2", "react-dom": "17.0.2", "copy-webpack-plugin": "^4.6.0", "@date-io/moment": "1.3.13", "@material-ui/core": "4.12.2", "@material-ui/data-grid": "4.0.0-alpha.37", "@material-ui/icons": "4.11.2", "@material-ui/lab": "4.0.0-alpha.60", "@material-ui/pickers": "3.3.10", "@material-ui/styles": "4.11.4", "@material-ui/system": "4.12.1", "@mui/x-data-grid": "4.0.0", "@mui/x-data-grid-pro": "4.0.0" }, "peerDependencies": { "react": "17.0.2", "react-dom": "17.0.2", "@date-io/moment": "1.3.13", "@material-ui/core": "4.12.2", "@material-ui/data-grid": "4.0.0-alpha.37", "@material-ui/icons": "4.11.2", "@material-ui/lab": "4.0.0-alpha.60", "@material-ui/pickers": "3.3.10", "@material-ui/styles": "4.11.4", "@material-ui/system": "4.12.1", "@mui/x-data-grid": "4.0.0", "@mui/x-data-grid-pro": "4.0.0" } }
webpack.prod.config.js
const path = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { mode: 'production',
// 配置 entry 属性,即构建时的入口。例如:此时组件入口是widget下的index.js。 entry: { main: './src/widget/index.js', }, output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist', filename: 'build.js',
// 配置 library 和 libraryTarget 属性 library: 'test-library-hybird-libs', libraryTarget: 'umd', }, resolve: { extensions: ['.js', '.jsx'], }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'], }, { test: /\.(js|jsx)$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', }, }, { test: /\.(woff|woff2|ttf|eot|ico)$/, use: [ { loader: 'file-loader', }, ], }, ], }, plugins: [ new CopyWebpackPlugin([ { from: path.resolve(__dirname, './src'), to: path.resolve(__dirname, './dist/src'), }, ]), ], };
二.编写组件
widget/index.js
import Checkbox from './Checkbox'; export { Checkbox };
widget/Checkbox.js
import React from 'react'; import { Checkbox as HACheckbox } from '@material-ui/core'; import PropTypes from 'prop-types'; import checkoutStyles from './style'; import theme from '../../themes/theme'; const CheckBox = ({ className, ...props }) => { const classes = checkoutStyles(props); return <HACheckbox className = {`${classes.checkboxRoot} ${className}`} inputProps={{"aria-label":'checkbox'}} checked={props.checked} onChange={props.onChange} color={['default','info','secondary','warning'].indexOf(props.color)>-1?props.color:'default'} /> }; CheckBox.propTypes = { /** * Checkbox color */ color: PropTypes.oneOf(Object.keys(theme.themeColorList)), /** * Checkbox width */ width: PropTypes.number, /** * Optional checked */ checked: PropTypes.bool, /** * Optional default Checked */ defaultChecked: PropTypes.bool, /** * class Name */ className: PropTypes.string, /** * Optional change handler */ onChange: PropTypes.func, }; CheckBox.defaultProps = { defaultChecked: false, checked: false, color: 'default', }; export default CheckBox;
widget/style.js
import { makeStyles } from '@material-ui/core/styles'; const checkoutStyles = makeStyles((theme) => ({ checkboxRoot: { padding: '2px', '@global': { '.MuiSvgIcon-root': { fill: (props) => theme.themeColorList[props.color] || theme.themeColorList.Primary, width: (props) => props.width || '20px', height: (props) => props.width || '20px' } } } })); export default checkoutStyles;
三.安装依赖并打包组件
npm i npm run build
四. 本地模拟发布
打包完成后,继续在组件源码根目录下,执行命令:
npm pack
命令执行后,会在根目录下生成一下.tgz包,然后在需要引入组件的项目中执行以下命令:npm install 本地包路径,本地包路径为刚才生成的.tgz包路径,注意命令中斜杠方向!!!
安装后,package中会出现一条依赖,但本条记录会显示文件路径,因为是本地模拟安装的。
到这一步就可以直接测试组件
五.发布组件到npm
1. 注册npm账号,这里不多说了
2. 切换到需要发包的项目根目录下,登录npm账号,输入用户名、密码、邮箱
npm login //登录 npm publish //发布
每次发布到npm上需要更改版本号,即package.json 里的 version 字段不可与已发布的包版本号相同
3.安装组件
npm install 组件名称
六,使用组件
import { MuiThemeProvider, CssBaseline } from '@material-ui/core'; import {CheckBox} from 'test-library-hybird-libs'; import theme from './themes/theme'; import GlobalStyles from './themes/GlobalStyles'; function App() { console.log(CheckBox) return ( <MuiThemeProvider theme={theme}> <CssBaseline /> <GlobalStyles /> test <CheckBox color="Primary" checked/> </MuiThemeProvider> ); } export default App;