第三部分 - 打包篇:項目打包,併發布至 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
了。🎉🎉🎉 可是,這個組件庫須要寫哪些組件進去,是咱們接下來須要考慮的。
若是您喜歡這個系列,歡迎評論,分享文章連接。此外,也歡迎多多吐槽,🙏 這些反饋對我來講是很是寶貴的,以便我未來寫出更優秀的文章。