从0到1搭建组件库

赛博架构师
• 阅读 1709

当学习成为了习惯,知识也就变成了常识。感谢各位的 点赞收藏评论

新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn

文章已收录到 github,欢迎 Watch 和 Star。

简介

从实现项目基本架构 -> 支持多规范打包 -> 实现按需加载 -> 发布 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

项目目录结构

从0到1搭建组件库

开始编码

目前我们只是为了验证架构设计,所以只会写一些简单的 demo

组件

在 packages 目录中新建两个目录,作为组件目录

从0到1搭建组件库

其实这个目录结构参考了 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": "https://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/lyn-comp-lib@1.0.0

测试

接下来我们新建一个测试项目去实际使用刚才发布的组件库,去验证其是否可用以及是否达到我们的预期目标

新建项目

  • 初始化项目目录
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,然后在浏览器打开,打开控制台,会发现输出如下内容:

从0到1搭建组件库

  • 是否按需加载

我们在 /src/index.js 中只引入和使用了 hello 方法,在 main.js 中搜索 hello functionlog function 会发现都能搜到,说明现在是全量引入,接下来根据 使用文档(README.md) 配置按需加载

从0到1搭建组件库

从这张图上也能看出,引入是 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

{
...
scripts: {

"build": "webpack --config webpack.config.js"

}
...
}


* 执行构建命令

npm run build


* 重复上面的第 4 步,会发现打包后的文件只有 `hello function`,没有 `log function`

![](https://gitee.com/liyongning/typora-image-bed/raw/master/202202071719323.jpg)

而且实际的包体积也小了

**OK,目标完成!!如有疑问欢迎提问,共同进步**

## 链接

* [组件库专栏](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzA3NTk4NjQ1OQ==&action=getalbum&album_id=2259813235891863559#wechat_redirect)

- [github](https://github.com/liyongning/lyn-comp-lib.git)



感谢各位的:**点赞**、**收藏**和**评论**,我们下期见。

---

**当学习成为了习惯,知识也就变成了常识。**感谢各位的 **点赞**、**收藏**和**评论**。

新视频和文章会第一时间在微信公众号发送,欢迎关注:[李永宁lyn](https://gitee.com/liyongning/typora-image-bed/raw/master/202202171742614.jpg)

文章已收录到 [github](https://github.com/liyongning/blog),欢迎 Watch 和 Star。
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
TurnipBit开发板DIY呼吸的吃豆人教程实例
  转载请以链接形式注明文章来源(MicroPythonQQ技术交流群:157816561,公众号:MicroPython玩家汇)  0x00前言  吃豆人是耳熟能详的可爱形象,如今我们的TurnipBit也集成了这可爱的图形,我们这就让他来呼吸了~。  0x01效果展示  先一起看下最终的成品演示视频:  http:/
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
赛博架构师
赛博架构师
Lv1
天地心从数点见,河山春借一枝回。
文章
3
粉丝
0
获赞
0