🎉纯干货不废话,用rollup搭建组件库,再用vite搭建测试环境

本篇文章分享如何和用 rollup 来构建一个组件库,以及使用vite搭建一个测试环境

rollup 在构建组件库上,相较于 webpack 有什么优点呢

rollup 基于 esm 模块作为输入模式,在构建组件库时具有更快的构建速度、更简洁的配置,更好的代码质量和更低的内存占用等优点。这些优点让 rollup 成为构建组件库的首选

下面我们来看看如何使用 rollup 构建一个组件库

准备两个组件

首先准备两个组件,Button 和 Input

Button

jsx 复制代码
import { useState } from "react"

const Button = (props: { content: string }) => {
	const [count, setCount] = useState(0);
	return <div><button onClick={() => setCount(count + 1)}>count: {count}</button>
		<div>{props.content}</div>
	</div>
}

export default Button;

Input

jsx 复制代码
const Input = () => {
  return <div>
    <span>input anything: </span>
    <input></input>
  </div>
}

export default Input;

代码都很简单,都是非常基础的代码

然后在 src 根目录下的 index 文件,将这些文件都导入并导出

jsx 复制代码
import Button from "./Button";
import Input from "./Input"

// 导出组件文件中的非default导出
export * from './Button';
export * from './Input';

// 导出组件本身
export {
  Button,
  Input
}

组件准备好了,下面就开始打包了

配置 rollup

先在项目的根目录中创建一个 rollup 配置文件:rollup.config.js

jsx 复制代码
/**@type {import('rollup').RollupOptions} */
module.exports = {
	input: "./src/index.tsx",
	output: {
		dir: "./dist",
		format: "esm",
		sourcemap: true,
	},
	plugins: [
		//...
	],
	external: ["react", "react-dom","react/jsx-runtime"],
};

小技巧:如果希望在 js 文件中,还可以获得像 ts 的编译器提示,可以使用 jsDoc,像上面的/**@type */

配置中,需要指出构建的入口./src/index.tsx,以及构建产物的目录./dist,格式,是否生成 sourcemap 等信息。

rollup 不仅可以打包成 esm 格式,还可以打包成 esm 格式,umd 格式,不过对于组件库而言,其应用场景是在 node 环境中的其他项目中引入,所以一般是打包成 esm。不过为了多环境的支持性,会构建 esm 和 umd 两种类型的产物

plugins 中就是放插件,添加额外功能的地方了。external 表示哪些包不放进构建产物中,若它的值是["react", "react-dom"],那就表示 reactreact-dom, 以及 react 运行时依赖react/jsx-runtime,均不打包进构建产物中

添加插件

rollup 作为一个构建工具,只提供一些非常基础的能力,像 commonjs 模块解析,json 解析,ts 解析,css 解析等,都不支持。好在 rollup 提供了方便简单的插件机制,并且有非常多的生命周期 hook,使得开发人员为其添加额外的功能颇为方便

1

先添加@rollup/plugin-commonjs, 赋予 rollup 加载第三方依赖的功能,添加@rollup/plugin-commonjs, 赋予rollup将cjc模块转成esm模块的能力

powershell 复制代码
npm i @rollup/plugin-commonjs @rollup/plugin-commonjs -D

2

添加@rollup/plugin-typescript, 赋予rolllup解析typescript的能力,还要添加相关的依赖: typescript

powershell 复制代码
npm i typescript @rollup/plugin-commonjs -D

因为需要用 typescript 生成类型文件,所以还需要配置 ts 的配置文件:tsconfig.json

json 复制代码
{
  "compilerOptions": {
    "rootDir": "./src",
    "baseUrl": "./",
    "jsx": "react-jsx",
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "./dist/types",
    "lib": [
      "es2020"
    ]
  }
}

这里有几个和构建有关的,我需要重点提一下:

  • declaration 表示生成类型文件,emitDeclarationOnly 表示只生成类型文件。因为 rollup 是借助 babel 做编译,所以只需要 ts 提供类型文件的输出即可
  • outDir 的值是./dist/types表示 tsc 的编译产物放到当前目录下的 dist 文件夹下的 types 目录
  • rootDIr,默认是 src,即包含所有的 ts 文件。也可以手动指定。

那rootDIr是用来干什么的呢?rootDir 是和 outDir 结合起来用的。如果 rootDir 的值是./src,那么构建之后的产物就是这样的:

即 src 下面的文件结构直接铺在 types 文件夹下面

那如果 rootDir 的值是./,就会变成这样:

即 types 文件夹下面还嵌套着一层 src。这就是 rootDir 的作用

使用了@rollup/plugin-typescript,在 rollup build 的时候,就会使用 tsc 对文件进行编译,所以当我仅执行了 rollup -c 后,types 会自动产生


3

添加@rollup/plugin-babel, 赋予 rollup 可以解析 jsx,降级 js 语法的能力。还要添加相关的依赖:@babel/core, @babel/preset-react。

因为是react 组件库,所以还需要安装 react , react-dom,@types/react, @types/react-dom

powershell 复制代码
npm i react react-dom @types/react @types/react-dom -D
npm i @babel/core @babel/preset-react -D
npm i @rollup/plugin-babel -D

如果需要使用 babel 对 js 语法做降级处理,就需要安装@babel/preset-env, @babel/plugin-transform-runtime

4

添加rollup-plugin-postcss, postcss, 赋予 rollup 解析 css,scss,sass 的能力

powershell 复制代码
npm i rollup-plugin-postcss postcss -D

完善 rollup 配置

需要的功能都差不多了,完善下 rollup 配置文件吧

javascript 复制代码
const resolve = require("@rollup/plugin-node-resolve");
const postcss = require("rollup-plugin-postcss");
const typescript = require("@rollup/plugin-typescript");
const commonjs = require("@rollup/plugin-commonjs");
const { babel } = require("@rollup/plugin-babel");

/**@type {import('rollup').RollupOptions} */
module.exports = {
	input: "./src/index.tsx",
	output: {
		dir: "./dist",
		format: "esm",
		sourcemap: true,
	},
	plugins: [
		resolve(),
		commonjs(),
		postcss(),
		typescript(),
		babel({
			presets: ["@babel/preset-react"],
			exclude: /nodex_module/,
		}),
	],
	external: ["react", "react-dom"],
};

配置文件做好了,下面测试一下,看看 rollup 构建是什么样子

先添加一个 npm script

javascript 复制代码
// package.json
{
	"scripts": {
		"build": "rollup -c",
	}
}

-c的意思是,执行 rollup 时,使用 rollup 配置文件中的配置

执行npm run build

构建好了,花费 1.1s。 因为组件简单,就很快

这是构建产物的结构:

有 types 类型文件,还有 index.js 和对应的 index.js.map

再看看 index.js 里面长什么样子:

两个组件都被置于 index 文件中,并且格式是 esm,符合预期

不 bundle 构建

不过传统的 esm 都是不 bundle 的,也就是不打包成单个文件的,再改改 rollup.config.js:

javascript 复制代码
{
	output: {
		dir: "./dist",
		format: "esm",
		sourcemap: true,
		//rollup只编译,不打包
		preserveModules: true,
	},
}

再次执行npm run build

文件结构变成了这个样子:

index.js 的内容:

好了,构建文件做好了,该怎么测试它的可用性呢?

使用 vite 搭建测试环境

测试的思路是使用 vite 新建一个 react demo 项目,然后用 npm link 的方式来测试上面的构建产物

shell 复制代码
mkdir use-rollup
cd use-rolllup
npm init -y
npm i vite react react-dom @types/react @types/react-dom @vitejs/plugin-react typescript

先创建一个测试项目的文件夹,然后在其中安装必要的依赖

配置 vite.config.js 文件

javascript 复制代码
import viteReact from "@vitejs/plugin-react";

/**@type {import('vite').UserConfig} */
export default {
	plugins: [viteReact()],
	server: {
		port: 8080,
		open: "/",
	},
};

vite 自身支持丰富的功能,所以这里仅需要 react 插件即可。还另外配置了本地服务器

配置 tsconfig.json

json 复制代码
{
  "compilerOptions": {
    "jsx": "react-jsx",
  }
}

因为需要用到 react,所以这里配置不用引入 react 的 ts 配置,其他 ts 配置用默认的就好

编写 index.tsx

jsx 复制代码
import ReactDOM from 'react-dom/client'
import { Button } from 'rollup-build'

const App = () => {
  return <div>
    App
  </div>
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />)

准备一个 index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=, initial-scale=1.0" />
		<title>use-rollup</title>
		<script type="module" src="./src/index.tsx" defer></script>
	</head>
	<body>
		<div id="root"></div>
	</body>
</html>

将 index.html 作为 vite 启动的入口文件

好了,到这里所有的东西都准备好了,这是现在的文件结构:

启动项目

先添加一个 npm script:

json 复制代码
"scripts": {
		"start": "vite"
	},

执行npm run start:

启动成功,修改几个字符看看

页面也刷新了。

项目没问题,下面开始测试构建产物

测试构建产物

首先要做到的是修改组件库项目的 package 的 main 和 types 文件指向:

json 复制代码
{
  "main": "./dist/index.js",
	"types": "./dist/types",
}

mian 和 types 都指向 dist 文件夹,也就是构建产物的文件夹

然后在组件库项目根目录终端执行: npm link

再在 demo 目录执行npm link rollup-build

link 成功之后,就可以在 index.tsx 中引入对应的组件

保存,刷新页面:

测试成功,没有问题

优化测试的体验

在使用 npm link 测试后,发现了个问题,Button 的 content 的属性名不对,应该是 contents,少了个 s,这时候就要修改组件库的代码了

修改组件库代码之后,还需要 build,构建之后才能在 demo 项目里看见变化。

那这个体验就很糟糕了,有没有什么办法可以像 vite 本地开发服务器一样,一旦文件保存,就可以在测试端看见变化呢?

当然是有办法的

rollup 支持 watch 模式,一旦文件变动,就会自动地单独重新构建这个文件

给组件库添加一个新的 npm script:

json 复制代码
{
  "build:watch": "rollup -c -w"
}

-w的意思就是开启 watch

下面来试试:

修改 Button 的属性

javascript 复制代码
const Button = (props: { contents: string }) => {
  const [count, setCount] = useState(0);
  return <div><button onClick={() => setCount(count + 1)}>count: {count}</button>
  <div>{props.contents}</div>
  </div>
}

ctrl + s 保存后,主要看看这两个文件有没有变化:

这是构建之后的 Button/index.js

这是 types/Button/index.d.ts

均已发生变化!!

很不错,看看 demo 项目中的 src/index.tsx:

ts 已经提示报错了

总结:

这篇文章分享了如何用 rollup 来构建一个组件库。介绍了 rollup 配置的基本用法以及相关的插件。

为了测试构建产物,还用 vite 来搭建一个 demo 环境,使用 npm link 来测试构建产物的可用性和正确性。

最后为了测试的体验,借助了 rollup 的 watch 模式,可以在监听到文件变化后,自动重新构建。

构建组件库有了,测试教程也有了,但是测试环境是依托于其他消费端项目的。组件库本身却没有一个开发环境,这个留待下篇文章来分享吧

这篇文章看完,大家有什么收获吗,欢迎在评论区留言哦

相关推荐
T^T尚3 小时前
uniapp H5上传图片前压缩
前端·javascript·uni-app
出逃日志3 小时前
JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)
开发语言·前端·javascript
XIE3924 小时前
如何开发一个脚手架
前端·javascript·git·npm·node.js·github
山猪打不过家猪4 小时前
React(五)——useContecxt/Reducer/useCallback/useRef/React.memo/useMemo
前端·javascript·react.js
前端青山4 小时前
React事件处理机制详解
开发语言·前端·javascript·react.js
科技D人生4 小时前
Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive
前端·vue.js·vue ref·vue ref 响应式·vue reactive
对卦卦上心4 小时前
React-useEffect的使用
前端·javascript·react.js
练习两年半的工程师4 小时前
React的基本知识:事件监听器、Props和State的区分、改变state的方法、使用回调函数改变state、使用三元运算符改变state
前端·javascript·react.js
啵咿傲4 小时前
在React中实践一些软件设计思想 ✅
前端·react.js·前端框架
GIS好难学4 小时前
《Vue零基础入门教程》第二课:搭建开发环境
前端·javascript·vue.js·ecmascript·gis·web