使用 Vite 开发前端库实践前言 最近需要做个内部的反馈系统(最终效果如下图所示),需要能在其他 React 前端应用
前言
最近需要做个内部的反馈系统(最终效果如下图所示),需要能在其他 React 前端应用中接入,所以需要开发一个库。经过几番考虑,最终选择了用 Vite 来做开发和打包。原因是 Vite 可以很方便的支持开发时的预览,同时也支持构建 库模式,相比于使用 Rollup 从零开始搭建可以省去很多工作。

在开发过程中总结了一套开发模版,👉 github地址。 其中包含的功能如下:
- 支持 Typescript,支持打包时输出 TS 类型文件
- 支持使用 Less 语法
- 支持导入 SVG 组件语法,即
import { ReactComponent as IconSvg } from './icon.svg'
- 支持函数及组件的测试
- Eslint、Prettier 配置,提交 commit 时自动进行语法检查 功能很简单,但已经可以满足一般的需求了~ 总的来说,模版功能很少很基础,但也很简洁。
下面详细讲讲使用 Vite 来开发库的一些实践经历。
实践🌟
(1)初始化项目
使用脚手架直接创建即可 yarn create vite
,最后选择 react-ts ,即默认配置好 react 和 typescript 的环境。
(2)库模式
为了运行 yarn build
时构建库模式,我们需要做一些配置。
build.lib
这里主要是配置打包入口和指定打包模式,如 es,cmd,umd。如果只想打包为 es ,则可以使用如下配置。
{
entry: './src/index.tsx', // 打包入口
formats: ['es'], // 指定打包模式为 es
fileName: (format) => `index.${format}.js` // es 模式打包文件名为 index.es.js
}
build.rollupOptions
覆盖 rollup 的一些默认配置。我们是开发基于 React 的库,所以需要将 react 设置为外部依赖,这样在构建时 rollup 就不会把 react 的源码打包进去。
{
external: ['react'], // 外部依赖
}
相应的,我们需要在 package.json 文件中配置 peerDependencies 字段,来告知外部项目我们需要的依赖。
{
"peerDependencies": {
"react": ">=17.0.0"
}
}
build.outdir
构建结果的输出目录,默认为 dist ,我们可以改名为 lib。
{
outDir: 'lib' // 默认为 dist
}
(3)输出 TS 类型文件
为了在外部引用这个库时能看到相关函数和变量的类型,我们需要在构建时输出 TS 类型。但 Vite 并不支持输出 TS 类型文件,我们可以通过 tsc 命令来完成这一工作 。
我们可以创建一个 tsconfig.build.json
的文件,如下所示:
{
"extends": "./tsconfig.json", // 拓展 tsconfig.json 的配置
"compilerOptions": {
"noEmit": false, // 允许生成文件
"declaration": true, // 需要设置为 true 来支持类型
"emitDeclarationOnly": true, // 只生成类型文件
"declarationDir": "lib" // 类型文件的导出目录
},
"include": ["src"] // 编译目标仅为 src 文件夹下的文件
}
接着将默认的 package.json 中默认的 build 命令 tsc && vite build
改为 vite build && tsc -p tsconfig.build.json
即可。
"scripts": {
"dev": "vite",
"build": "vite build && tsc -p tsconfig.build.json"
}
两者的区别是,后者执行 tsc
命令时使用的是 tsconfig.build.json 中的配置,以生成类型文件。需要注意,tsc
命令还有另一个重要功能,就是做 ts 代码的类型检查,而 Vite 仅执行 .ts
文件的转译工作,这也是为什么默认的 build 命令会包含 tsc
的原因。
最后,还需要在 package.json 中声明 es 模块和类型文件的位置,这样外部在引入这个库时才能找到相应的文件。
{
"module": "./lib/index.es.js", // es 模块入口
"types": "./lib/index.d.ts", // 类型文件位置
}
(4)CSS
CSS 的处理可以参考官方说明 CSS。官方建议使用 PostCSS 插件来帮助编写符合未来规范的 CSS,不过如果想用 less,sass 这些预处理器也是很方便的,只需要安装对应的预处理器依赖。如使用 less 只需要 yarn add -D less
即可。
(5)eslint 配置
为了让我们编写的 JS 代码更规范,配置 eslint 是很有必要的。我们可以使用 npx eslint --init
命令来可视化选择我们需要的配置。
这样就不用我们一个个自己去配了。最后,我们再添加一个 react-hook 的语法检查插件就好了,👉 eslint-plugin-react-hooks。
(6)StyleInject
默认的构建结果中 JS 和 CSS 文件是分开的,如下所示:
这样的做法就导致了在引入这个库时还需要额外引入它的CSS,如:
import Button from 'x-button';
import 'x-button/lib/style.css';
另一种做法是直接将源码中的 CSS 样式用 style 标签导入,从而外部引入时就不需要额外引入 CSS 文件了。实现方式如下:
// rollup-plugin-postcss 插件中导入 CSS 的函数
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = '.a{\n background:blue;}'
styleInject(css_248z);
关于库模式下CSS 可否作为样式被注入有这样一个 issue,Can css be styleInjected in library mode?。当前 Vite 并没有对此进行支持,不过我们可以通过一些其他方法进行实现。
(7)导入 svg 为 React Component
即支持这样的导入方式:
import { ReactComponent as SendSvg } from './send.svg';
这也有一个相关的 issue: import SVG directly as a React Component,Vite 开发者表明这是 React 中的特性,只能用插件来实现。
当前社区中有一个很多插件实现了这一功能,比如 vite-plugin-svgr,我们只需按文档引入即可。
(8)测试
我们使用 jest 和 react-testing-library 来进行 JS 和 React 组件的测试。按照 官方文档 安装相关依赖并配置相应文件即可。
setup.js
对于一些所有测试文件都需要的公共项,我们可以将其添加到 test/setup.js 中,如引用通用库,设置全局变量等。比如一个非常有用的库 jest-dom ,它可以用来判断一些 DOM 的状态,如 tobeVisible,toBeDisabled。我们就可以在 setup.js 中引入它:
import '@testing-library/jest-dom';
并在 jest.config.js 中设置:
{
setupFilesAfterEnv: ['<rootDir>/test/setup.js']
}
mock 静态文件
在开发中我们可能会引入一些 JS 外的文件,如 css,svg 等,这些在测试中其实没有任何作用,所以我们可以安全的 mock 掉它们。
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
moduleNameMapper: {
'\.svg': '<rootDir>/test/__mocks__/svgrMock.js',
'\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/__mocks__/fileMock.js',
'\.(css|less)$': '<rootDir>/test/__mocks__/styleMock.js'
}
};
// test/__mocks__/svgrMock.js
export default 'SvgrURL';
export const ReactComponent = 'div';
(9)检查提交代码
一个好的开发实践是,在提交一个分支的代码前对修改的代码进行检查,以防止错误的代码被提交。
我们可以使用 husky 和 lint-staged 来帮助我们完成这个工作。通过 husky 可以方便的添加 git 事件的钩子,比如在执行 git commit
时执行某些命令(测试/代码检查)。lint-staged 可以定位即将被 ”commit“ 的文件,从而只在修改了的文件上执行代码检查,这样可以缩短检查时间。
配置 husky
# 安装 husky 依赖
yarn add husky -D
# 执行 hsuky install,这样 git hooks 才会生效。此命令会生成 .husky 文件夹
yarn husky install
在 package.json 中添加 prepare
命令,这样每次运行 npm install
或 yarn add
安装依赖时都会自动执行 husky install
。
"scripts": {
"prepare": "husky install"
}
最后,添加一个 commit hook,它将创建一个 .husky/pre-commit 文件。
npx husky add .husky/pre-commit "npm test"
到这一步,我们在提交 commit 时就会自动执行 .husky/pre-commit 中的脚本了。
配置 lint-staged
在 package.json 中添加 “lint-staged”,如下:
{
"scripts": {
// ...
"prepare": "husky install" // prepare 命令
"lint": "tsc && eslint . --ext '.js,.jsx,.ts,.tsx'",
"test": "jest",
},
"lint-staged": {
"*.{js,ts,tsx,jsx}": "npm run lint" // 对 committed 的 js,ts,tsx,jsx 文件执行 lint 命令
}
}
接着将 .husky/pre-commit 中的 "npm test" 命令修改为下面的内容:
npm run test && npx lint-staged
现在,在提交 commit 时,就会自动运行测试和语法检查了。
(10)开发预览&打包
参考一些开源库的做法,我们在 src 目录下编写源码,在 example 目录下编写使用示例。 在 Vite 中,我们需要设置 src/index.tsx 作为构建的入口,example/index.tsx 作为开发的入口。
// vite.config.js
{
build: {
lib: {
entry: './src/index.tsx', // 构建入口
}
}
}
// index.html
<script type="module" src="/example/index.tsx"></script> // 开发入口
这样就可以运行 yarn dev
进行开发预览,运行 yarn build
来进行打包构建了。
(11)调试
在库的功能完成并打包构建后,我们可以通过 yarn link
(或 npm link
)来做最后的发布调试。
在当前库的根目录下执行 yarn link
,之后我们在其他项目中使用 yarn link package-name
后就可以正常导入这个库了。
"package-name" 和上图中的 x-button 即库的 package.json 中的 name 字段的值。
如果一个库存在外部依赖,如 React,那么我们还需要多做几步操作。比如需要调试的库是A,它有一个外部依赖 React,引入它的项目是 B,那么依次的操作为:
- 在库 A 中执行
yarn link
- 在库 B 中执行
yarn link A
安装库 A - 在库 B 中执行
cd node_modules/react && yarn link
,来创建 B 中安装的 react 的链接 - 最后一步,在库 A 中执行
yarn link react
来链接库 B 中安装的 react
上述 yarn link
也可用于开源库的调试,在 clone 项目后,使用 yarn link
,我们可以在其他项目中引入并调试开源库的代码了😺。
转载自:https://juejin.cn/post/7050743861492056078