從0到1搭建組件庫
簡介
從實現項目基本架構 -> 支援多規範打包 -> 實現按需載入 -> 發布 npm 包,帶你從 0 到 1 搭建組件庫。
搭建項目
- 初始化項目目錄
mkdir lyn-comp-lib && cd lyn-comp-lib && npm init -y
- 新建 packages 目錄
packages 目錄為組件目錄,組件一個文件夾為單位,一個文件夾為一個組件
mkdir packages
- 新建 /src/index.js
/src/index.js 作為 commonjs 規範的打包入口
mkdir src && cd src && touch index.js
- 新建 webpack.common.js
commonjs 規範的 webpack 配置文件
touch webpack.common.js
- 新建 webpack.umd.js
umd 規範的 webpack 配置文件
touch webpack.umd.js
- 新建 publish.sh
負責構建項目 和 發布 npm 包
touch publish.sh
- 安裝 webpack、webpack-cli
npm i webpack webpack-cli -D
項目目錄結構
開始編碼
目前我們只是為了驗證架構設計,所以只會寫一些簡單的 demo
組件
在 packages 目錄中新建兩個目錄,作為組件目錄
其實這個目錄結構參考了 element-ui 組件庫,為支援 按需載入 做準備
- /packages/hello/src/index.js
// hello function
export default function hello (msg) {
console.log('hello ', msg)
}
- /packages/log/src/index.js
// log function
export default function log (str) {
console.log('log: ', str)
}
引入並導出組件
在 /src/index.js 中統一引入項目中的組件並導出
// 當組件變得龐大時這部分可自動生成,element-ui 就是採用自動生成的方式
import hello from '../packages/hello/src/index'
import log from '../packages/log/src/index'
export default {
hello,
log
}
編寫 webpack 配置文件
- /webpack.common.js
const path = require('path')
module.exports = {
entry: './src/index.js',
// 使用 開發者 模式,目的是為了一會兒的調試,實際開發中可改為 production
mode: 'development',
output: {
path: path.join(__dirname, './lib'),
filename: 'lyn-comp-lib.common.js',
// commonjs2 規範
libraryTarget: 'commonjs2',
// 將 bundle 中的 window 對象替換為 this,不然會報 window is not defined
globalObject: 'this',
// 沒有該配置項,組件會掛載到 default 屬性下,需要 comp.default.xxx 這樣使用,不方便
libraryExport: 'default'
}
}
- /webpack.umd.js
const path = require('path')
module.exports = {
// 實際開發時這部分可以自動生成,可採用 element-ui 的方式
// 按需載入 需要將入口配置為多入口模式,一個組件 一個入口
entry: {
log: './packages/log/src/index.js',
hello: './packages/hello/src/index.js'
},
mode: 'development',
output: {
path: path.join(__dirname, './lib'),
filename: '[name].js',
// umd 規範
libraryTarget: 'umd',
globalObject: 'this',
// 組件庫暴露出來的 全局變數,比如 通過 script 方式引入 bundle 時就可以使用
library: 'lyn-comp-lib',
libraryExport: 'default'
}
}
package.json
{
"name": "@liyongning/lyn-comp-lib",
"version": "1.0.0",
"description": "從 0 到 1 搭建組件庫",
"main": "lib/lyn-comp-lib.common.js",
"scripts": {
"build:commonjs2": "webpack --config webpack.common.js",
"build:umd": "webpack --config webpack.umd.js",
"build": "npm run build:commonjs2 && npm run build:umd"
},
"keywords": ["組件庫", "0 到 1"],
"author": "Li Yong Ning",
"files": [
"lib",
"package.json"
],
"repository": {
"type": "git",
"url": "//github.com/liyongning/lyn-comp-lib.git"
},
...
}
解釋
-
name
在 包 名稱前加自己的 npm 賬戶名,採用 npm scope 的方式,包目錄的組織方式和普通包不一樣,而且可以有效的避免和他人的包名衝突
-
main
告訴使用程式 ( import hello from ‘@liyongning/lyn-comp-lib’ ) 去哪裡載入組件庫
-
script
構建命令
-
files
發布 npm 包時告訴發布程式只將 files 中指定的 文件 和 目錄 上傳到 npm 伺服器
-
repository
程式碼倉庫地址,選項不強制,可以沒有,不過一般都會提供,和他人共享
構建發布腳本 publish.sh
shell 腳本,負責構建組件庫和發布組件庫到 npm
#!/bin/bash
echo '開始構建組件庫'
npm run build
echo '組件庫構建完成,現在發布'
npm publish --access public
README.md
一個項目必可少的文件,readme.md,負責告訴別人,如何使用我們的組件庫
構建、發布
到這一步,不出意外,開篇定的目標就要完成了,接下來執行腳本,構建和發布組件庫,當然發布之前你應該有一個自己的 npm 賬戶
sh publish.sh
執行腳本過程中沒有報錯,並最後出現以下內容,則表示發布 npm 包成功,也可以去 npm 官網 查看
...
npm notice total files: 5
npm notice
+ @liyongning/[email protected]
測試
接下來我們新建一個測試項目去實際使用剛才發布的組件庫,去驗證其是否可用以及是否達到我們的預期目標
新建項目
- 初始化項目目錄
mkdir test && cd test && npm init -y && npm i webpack webpack-cli -D && npm i @liyongning/lyn-comp-lib -S
查看 日誌 或者 package.json 會發現 組件庫 已經安裝成功,接下來就是使用了
- 新建 /src/index.js
import { hello } from '@liyongning/lyn-comp-lib'
console.log(hello('lyn comp lib'))
- 構建
npx webpack-cli --mode development
在 /dist 目錄會生成打包後的文件 mian.js,然後在 /dist 目錄新建 index.html 文件並引入 main.js,然後在瀏覽器打開,打開控制台,會發現輸出如下內容:
- 是否按需載入
我們在 /src/index.js 中只引入和使用了 hello 方法,在 main.js 中搜索 hello function
和 log function
會發現都能搜到,說明現在是全量引入,接下來根據 使用文檔(README.md) 配置按需載入
從這張圖上也能看出,引入是 commonjs 的包,而不是 “./node_modules/@liyongning/lyn-comp-lib/lib/hello.js
- 根據組件庫的使用文檔配置按需載入
安裝 babel-plugin-component
安裝 babel-loader、@babel/core
npm install --save-dev babel-loader @babel/core
// webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js',
mode: 'development',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
安裝 @babel/preset-env
{
"presets": ["@babel/preset-env"],
"plugins": [
[
"component",
{
"libraryName": "@liyongning/lyn-comp-lib",
"style": false
}
]
]
}
- 配置 package.json 的 script
json
json
{
…
scripts: {
“build”: “webpack –config webpack.config.js”
}
…
}
“`
- 執行構建命令
npm run build
- 重複上面的第 4 步,會發現打包後的文件只有
hello function
,沒有log function
而且實際的包體積也小了
OK,目標完成!!如有疑問歡迎提問,共同進步
鏈接
感謝各位的:點贊、收藏和評論,我們下期見。
當學習成為了習慣,知識也就變成了常識,掃碼關注微信公眾號,共同學習、進步。文章已收錄到 github,歡迎 Watch 和 Star。