第三部分 - 打包篇:项目打包,并发布至 NPM
原文连接css
在前面的部分,咱们使用 React 等相关技术构建了库并对其进行了测试。如今,咱们准备对前面的代码进行打包,并将其发布至 NPM,方便其余人使用。node
本篇文章,是这个系列的第三篇::项目打包,并发布至 NPMreact
组件库开发到了这里,终于也到了最重要的部分,解决(文档 + 打包)的问题。webpack
在尝试了一些打包库(好比create-react-library),和文档库(React Styleguidist)以后,都没有达到想要的效果。git
直到B站的一个视频:利用 umi-library 作组件打包,答案就变得简单而明显了,就是利用云谦大大开源的组件打包利器:umijs/father,来完成最后一步。es6
由于目前整个打包工具会把src
做为入口。为了不前面路由,首页等代码被打包进去,这里对项目结构作出了较大的改动,新增长了 entry
做为路由的入口,而 src
则做为组件的入口。建议参考下 dantd 中的目录结构。github
项目初始化以后,接下来,用编辑器打开这个项目,并修改 package.json
中下面属性:web
{ "main": "lib/index.js", "module": "es/index.js", "typings": "lib/index.d.ts",c "files": [ "dist", "lib", "es" ], "scripts": { "start": "father doc dev", "doc:build": "father doc build", "doc:deploy": "father doc deploy", "lib:build": "father build" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0", "antd": ">=3.21.0" }, "devDependencies": { "babel-plugin-import": "^1.13.0", "father": "^2.29.2", "fs-extra": "^8.1.0", "klaw-sync": "^6.0.0" }, "dependencies": { "antd": "^3.21.0", "classnames": "^2.2.6", "lodash": "^4.17.15" }, }
添加好以后,运行:npm install
安装依赖。在等待的同时,让咱们了解一下上述属性的具体含义:npm
npm
包的入口文件,browser 环境和 node 环境都可使用npm
包的 ESM 规范的入口文件,browser 环境和 node 环境都可使用上面两个都是程序的入口,当咱们使用打包工具(webpack)进行打包的时候:一、若是它已经支持 pkg.module 字段则会优先使用 ES6 模块规范的版本 import,这样能够启用 Tree Shaking 机制。二、若是它还不识别 pkg.module 字段则会使用咱们已经编译成 CommonJS 规范的版本 require('package1'),也不会阻碍打包流程。
Antd
进行简单封装的,因此,在使用这个组件库的时候,也须要安装对应版本的 Antd
等依赖。这里,咱们来给:EmptyLine
加上文档便可。为了方便阅读,这里仍是放上了组件的全部相关代码。json
export { default as EmptyLine } from './empty-line';
import './style/index.less'; import EmptyLine from './EmptyLine'; export default EmptyLine;
--- name: EmptyLine route: /empty-line menu: 组件 --- import { Playground } from 'docz'; import EmptyLine from './index'; ## EmptyLine > 组件名称:空行(EmptyLine),自定义组件 ,宽度 100% ### 代码演示 #### 复制信息 <Playground> <p>第一行文字</p> <EmptyLine /> <p>第二行文字</p> </Playground> ## API |参数|说明|类型|默认值| |:--|:--|:--|:--| |height|空行的高度|number?|20|
import React from 'react'; import './style/index.less'; export interface IEmptyLineProps { height?: number; } const EmptyLine = ({ height = 20 }: IEmptyLineProps) => { return <div className="empty-line" style={{ height }} />; }; export default EmptyLine;
.empty-line { width: 100%; height: 20px; }
export default { // cssModules: true, // 默认是 .module.css 走 css modules,.css 不走 css modules。配置 cssModules 为 true 后,所有 css 文件都走 css modules。(less 文件同理) extractCSS: true, esm: 'babel', cjs: 'babel', umd: { name: 'dantd', sourcemap: true, globals: { react: 'React', antd: 'antd' }, }, extraBabelPlugins: [ ['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }], ], entry: 'src/index.tsx', lessInBabelMode: true, doc: { base: '/dantd/', menu: [ '首页', '组件' ] }, }
更多配置项,欢迎探索文档:umijs/father
{ "compilerOptions": { "baseUrl": "./src", "paths": { "antd": ["src/index.tsx"], "antd/es/*": ["src/*"] }, "strictNullChecks": true, "moduleResolution": "node", "esModuleInterop": true, "experimentalDecorators": true, "jsx": "preserve", "noUnusedParameters": true, "noUnusedLocals": false, "noImplicitAny": true, "target": "es6", "lib": ["dom", "es2017"], "skipLibCheck": true }, "exclude": ["node_modules", "lib", "es"] }
添加这些文件以后,运行 npm start
,就能够看到下面的界面了。
若是想引入 Antd
,直接引入就行,上面的配置中,已经增长了:extraBabelPlugins
。能够按需加载 antd。
组件中引入代码:
import { Card, Typography } from 'antd';
ES6 打包代码:
import "antd/es/card/style"; import _Card from "antd/es/card"; import "antd/es/typography/style"; import _Typography from "antd/es/typography";
CommonJS 打包代码:
require("antd/es/card/style"); var _card = _interopRequireDefault(require("antd/es/card")); require("antd/es/typography/style"); var _typography = _interopRequireDefault(require("antd/es/typography"));
首先,运行 father build
打包代码。
能够看到,father
会分别根据:umd、cjs、es 这三种格式进行打包,打包以后会看到多出了下面这些文件。
├── dist | ├── empty-line | | ├── EmptyLine.d.ts | | ├── index.d.ts | | └── style | | └── index.d.ts | ├── index.d.ts | ├── index.umd.css | ├── index.umd.js | ├── index.umd.js.map | ├── index.umd.min.css | ├── index.umd.min.js | └── index.umd.min.js.map ├── es | ├── empty-line | | ├── EmptyLine.js | | ├── index.js | | └── style | | ├── index.css | | └── index.js | └── index.js ├── lib | ├── empty-line | | ├── EmptyLine.js | | ├── index.js | | └── style | | ├── index.css | | └── index.js | └── index.js
此时,能够看到三种类型的包,已经被成功打出来了。那是否是这个时候就能够上传至 npm
了呢?
还不行,对比 Antd
的 npm
包以后,会发现 es
和 lib
两个目录下,尚未类型文件。须要将 dist
目录下的文件拷贝过来,并把文件中的 .less
改为 .css
。这里准备写2个脚本 hack 一下。
安装依赖:
npm install klaw-sync fs-extra -D
增长2个脚本:
const path = require('path'); const klawSync = require('klaw-sync'); const fs = require('fs'); const filesRegex = /.d.ts$/; const declarePaths = klawSync(path.resolve(__dirname, '../dist'), { nodir: true }).filter(pathItem => filesRegex.test(pathItem.path)) declarePaths.forEach((pathItem) => { const esPath = pathItem.path.replace('/dist', '/es'); const libPath = pathItem.path.replace('/dist', '/lib'); fs.copyFileSync(pathItem.path, esPath); fs.copyFileSync(pathItem.path, libPath); }) console.log('.d.ts 文件拷贝成功!');
const path = require('path'); const klawSync = require('klaw-sync'); const fs = require('fs'); const filesRegex = /(.js|.d.ts)$/; const fileFilterFn = item => { const basename = path.basename(item.path); return filesRegex.test(basename) || basename.indexOf('.') < 0; } const esPaths = klawSync(path.resolve(__dirname, '../es'), { filter: fileFilterFn, nodir: true }).map(item => item.path) const libPaths = klawSync(path.resolve(__dirname, '../lib'), { filter: fileFilterFn, nodir: true }).map(item => item.path) const allPaths = esPaths.concat(libPaths); allPaths.forEach((fileItem) => { const fileContent = fs.readFileSync(fileItem, 'utf8'); const newFileContent = fileContent.replace(/.less/gi, '.css'); fs.writeFileSync(fileItem, newFileContent, 'utf8'); }) console.log('.less => .css 文件后缀改写成功!');
修改打包命令:
"build": "father build && node ./scripts/moveDeclare.js && node ./scripts/changeLess2Css.js"
运行:npm run build
此次打包以后的文件,就能够上传至 npm
了。
首先登录 npm
:
使用 git 提交全部代码,而后修改版本号,并发布代码:
npm version patch git push npm publish
这里若是包名已经被注册,或者npm源不对,会报403错误,须要自行处理下
到了这里,咱们的第一个属于本身的组件库就被上传至 npm
了,咱们可使用:npm install dantd
下载咱们的安装包,并在项目中使用里面的组件了。
首先,在 package.json
文件中,添加 git
地址,便于以后文档的发布:
"repository": { "type": "git", "url": "https://github.com/jokingzhang/dantd" },
运行下面命令打包文档:
npm run doc:build
运行下面命令发布文档:
npm run doc:deploy
而后访问对应的地址就能够看到咱们发布到线上的组件文档了:dantd
属于咱们本身的第一个组件库,就这样被发布到 npm
了。🎉🎉🎉 可是,这个组件库须要写哪些组件进去,是咱们接下来须要考虑的。
若是您喜欢这个系列,欢迎评论,分享文章连接。此外,也欢迎多多吐槽,🙏 这些反馈对我来讲是很是宝贵的,以便我未来写出更优秀的文章。