第三部分 - 打包篇:项目打包,并发布至 NPMcss
原文连接node
在前面的部分,咱们使用 React 等相关技术构建了库并对其进行了测试。如今,咱们准备对前面的代码进行打包,并将其发布至 NPM,方便其余人使用。react
本篇文章,是这个系列的第三篇::项目打包,并发布至 NPMwebpack
组件库开发到了这里,终于也到了最重要的部分,解决(文档 + 打包)的问题。git
在尝试了一些打包库(好比create-react-library),和文档库(React Styleguidist)以后,都没有达到想要的效果。es6
直到B站的一个视频:利用 umi-library 作组件打包,答案就变得简单而明显了,就是利用云谦大大开源的组件打包利器:umijs/father,来完成最后一步。github
由于目前整个打包工具会把src
做为入口。为了不前面路由,首页等代码被打包进去,这里对项目结构作出了较大的改动,新增长了 entry
做为路由的入口,而 src
则做为组件的入口。建议参考下 dantd 中的目录结构。web
项目初始化以后,接下来,用编辑器打开这个项目,并修改 package.json
中下面属性:npm
{
"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
安装依赖。在等待的同时,让咱们了解一下上述属性的具体含义:json
npm
包的入口文件,browser 环境和 node 环境都可使用npm
包的 ESM 规范的入口文件,browser 环境和 node 环境都可使用上面两个都是程序的入口,当咱们使用打包工具(webpack)进行打包的时候:一、若是它已经支持 pkg.module 字段则会优先使用 ES6 模块规范的版本 import,这样能够启用 Tree Shaking 机制。二、若是它还不识别 pkg.module 字段则会使用咱们已经编译成 CommonJS 规范的版本 require('package1'),也不会阻碍打包流程。
Antd
进行简单封装的,因此,在使用这个组件库的时候,也须要安装对应版本的 Antd
等依赖。这里,咱们来给:EmptyLine
加上文档便可。为了方便阅读,这里仍是放上了组件的全部相关代码。
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
了。🎉🎉🎉 可是,这个组件库须要写哪些组件进去,是咱们接下来须要考虑的。
若是您喜欢这个系列,欢迎评论,分享文章连接。此外,也欢迎多多吐槽,🙏 这些反馈对我来讲是很是宝贵的,以便我未来写出更优秀的文章。