使用Rollup,TypeScript,SCSS配置React组件库

本文最后更新于:2023年1月12日 下午

本篇为翻译的文章,由于笔者能力有限,倘若阅读体验不好,可点击原文地址查看,原文地址:Rollup Config for React Component Library With TypeScript + SCSS

前言

在这篇文章中,我将尝试覆盖在构建React组件库时使用Rollup配置发挥作用的关键领域(特别是TypeScriptSCSS)。

同时,我将会为使用到的Rollup插件写一些说明,来说明插件的作用。

我绝对不是Rollup的大师,也不是构建React组件库的权威指南。我仅仅只是分享了用于构建我自己的React组件库(Codefee-Kit)时的Rollup配置,这只是我自己的一个笔记,或许能帮到一些人。

顺便说一下,组件库托管在Github

动机

在此之前,我使用webpack去构建库。当时,我在获得第一个工作版本时遇到了很多麻烦。我仍然记得有个属性叫”library”,为了让webpack对库收集信息,你需要显示设置。我很傻,在我明白整个事情之前我在谷歌上搜索了很多信息。在整个踩坑过程中投入了大量时间。我当然不喜欢那里的配置文件的复杂性。嗯,是谁?哈哈哈

尽管如此,当时的工作版本并没有得到很好的优化。我的意思是,没有配置任何代码分割,构建的输出总是一个越来越大的index.js文件

最近,我终于又有了一些空闲时间!因此,我决定重新审视这个话题。在Webpack中对如何进行代码拆分进行了一些深挖,我只是觉得它太麻烦了。

最后,我决定彻底停止,然后跳到另一个流行的构建库的选择——Rollup!而且,它的配置简单得多,而且节省了我很多时间!天啊,我为什么不早点跳过去?!去我的!

有一句话是这样说的,”Rollup for libraries, Webpack for apps”。事实证明,在这一点上,它仍然非常重要!

“Rollup for libraries, Webpack for apps” https://medium.com/@PepsRyuu/why-i-use-rollup-and-not-webpack-e3ab163f4fd3

主题范围

请跳转到你感兴趣的部分

  1. Rollup 配置文件
  2. Rollup 代码分割
  3. Rollup 插件说明

Rollup 配置文件

这是适用于我的配置文件。那里有相当多的活动部件,但我尽可能地把它清理干净,这样就不会太伤眼睛了哈哈。。。😛

rollup.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';

import postcss from "rollup-plugin-postcss";
import visualizer from 'rollup-plugin-visualizer';
import { terser } from 'rollup-plugin-terser';
import { getFiles } from './scripts/buildUtils';

const extensions = ['.js', '.ts', '.jsx', '.tsx'];

export default {
input: [
'./src/index.ts',
...getFiles('./src/common', extensions),
...getFiles('./src/components', extensions),
...getFiles('./src/hooks', extensions),
...getFiles('./src/utils', extensions),
],
output: {
dir: 'dist',
format: 'esm',
preserveModules: true,
preserveModulesRoot: 'src',
sourcemap: true,
},
plugins: [
resolve(),
commonjs(),
typescript({
tsconfig: './tsconfig.build.json',
declaration: true,
declarationDir: 'dist',
}),
postcss(),
terser(),
visualizer({
filename: 'bundle-analysis.html',
open: true,
}),
],
external: ['react', 'react-dom'],
};

正如你所看到的,为了让Rollup工作,你仅仅只需要导出一个JSON对象。当然,如果你有多个配置需要配置,你也能导出一个数组。例如构建不同的目标文件时,像umd,cjs

我在这里配置了4个属性:

  • input - 打包文件的入口。可以是字符串或者字符串数组
  • output - 打包文件的输出配置,例如配置打包输出的文件夹,配置sourcemap生成等
  • plugins - 外部包调用,帮助操作、更改构建行为,例如TypeScript, SCSS
  • external - 不需要打包进构建包中的包,通常是指peerDependencies中设置的包,在我的例子中,,就是reactreact-dom两个包

TypeScript 配置

以下是我的tsconfig文件。我有2个,一个是Rollup用于构建,另一个类似于基本配置,主要是用于开发

背后的原因是,我想排除我的Storybook stories filesTypeScript转译。它只用于开发时,我需要tsconfig。因此,创建了一个带有excludes的单独的配置文件

tsconfig.build.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"extends": "./tsconfig.json",
"exclude": [
"node_modules",
"build",
"dist",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/stories/**"
]
}

tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"compilerOptions": {
"module": "esnext",
"target": "es5",
"lib": [ "es6", "dom" ],
"sourceMap": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"esModuleInterop": true,
"baseUrl": "src/",
"paths": {
"common": ["src/common/*"],
"components": ["src/components/*"],
"hooks": ["src/hooks/*"],
"utils": ["src/utils/*"]
}
},
"exclude": [
"node_modules",
"build",
"dist",
"scripts",
"acceptance-tests",
"webpack",
"jest"
],
"types": ["typePatches"]
}

Rollup 代码分割

在上面的配置中,我实际上使用了Rollup的代码分割 (code-splitting) 功能。

如果您注意到,我导出的JSON对象中的input属性实际上是字符串数组,而不是单个字符串。这实际上告诉Rollup将这些字符串中的每一个作为构建的单独入口点。所以,这就是代码分割构建。

数组中的所有这些字符串实际上是我在src文件夹中拥有的单个.ts.tsx文件的相对路径。getFiles方法是我编写的一个实用方法,它帮助我深入检索所有扩展名为.js、.jsx、.ts.tsx的文件。

下面是getFiles方法的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const fs = require('fs');

export const getFiles = (entry, extensions = [], excludeExtensions = []) => {
let fileNames = [];
const dirs = fs.readdirSync(entry);

dirs.forEach((dir) => {
const path = `${entry}/${dir}`;

if (fs.lstatSync(path).isDirectory()) {
fileNames = [
...fileNames,
...getFiles(path, extensions, excludeExtensions),
];

return;
}

if (!excludeExtensions.some((exclude) => dir.endsWith(exclude))
&& extensions.some((ext) => dir.endsWith(ext))
) {
fileNames.push(path);
}
});

return fileNames;
};

Rollup 插件说明

以下是我在上面的配置文件中使用的插件,以及使用它们后我的一些解释和理解。

@rollup/plugin-node-resolve

对于Rollup,在node_modules中查找和捆绑第三方依赖项。这里所指的依赖关系是package.json文件中列出的依赖关系(dependencies)。

@rollup/plugin-commonjs

对于Rollup,将CommonJS模块转换为ES6,以便将其包含在Rollup捆绑包中。它通常与@rollup/plugin-node-resolve 一起使用,以捆绑CommonJS依赖项。

@rollup/plugin-typescript

帮助以更简单的方式与TypeScript集成。包括将TypeScript转换为JavaScript等内容。

rollup-plugin-postcss

PostCSS集成。对于我的用例,它有助于将CSSSCSS文件分别构建为*.CSS.js*.SCSS.js文件。然后,当导入相应的组件时,这些文件会相应地注入HTML head标签(依赖于style-inject

在我目前的开发中,我已经改用样式化组件,而倾向于在JS模式中尝试CSS

rollup-plugin-visualizer

此插件用于帮助我们分析捆绑输出。它将为我们的检查生成一个很酷的可视化。在进行捆绑包大小优化时,它特别有用,因为它可以让我们可视化捆绑包文件的各个大小。

rollup-plugin-terser

它基本上是一个插件,用于集成terser的用法。它有助于缩小和压缩我们的输出JavaScript文件。

总结

在使用RollupWebpack构建使用TypeScriptSCSSReact组件库之后。。。我不得不说,只是为了这个目的而疯狂地使用Rollup。与Webpack相比,它更易于配置。

单是配置的复杂性就足以让我跳过去。我希望有一个配置文件,我可以在任何时间点轻松推理,而不是一些冗长复杂的东西,我可能会在几周内忘记正在做什么!

然而,我可能不一定对应用程序开发有同样的感觉,因为Webpack具有真正强大的热模块替换功能。这绝对是一个救命稻草,也是应用程序开发的必备工具。

构建工具的前景正在发生变化,如果第二天出现另一个事实上的bundler,并在社区中掀起风暴,这可能并不奇怪!但至少现在,Rollup是我的新情人😛

参考

  1. https://github.com/rollup/plugins
  2. https://rollupjs.org/guide/en/
  3. https://marcobotto.com/blog/compiling-and-bundling-typescript-libraries-with-webpack/
  4. https://github.com/HarveyD/react-component-library
  5. https://github.com/rollup/rollup-plugin-commonjs

使用Rollup,TypeScript,SCSS配置React组件库
https://www.yxlazy.xyz/2023/01/03/使用Rollup-TypeScript-SCSS配置React组件库/
作者
yxlazy
发布于
2023年1月3日
更新于
2023年1月12日
许可协议