# 用rollup打包typescript编写的库
# rollup or webpack
# rollup
- rollup配置少,开箱即用,支持treeshaking,打包后比较干净
- 适合构建第三方库
# webpack
- rollup能做的webpack也能做,但是添加额外的内容较多,配置相对繁琐
- 适合构建webapp
我要做的是webgl库,肯定选择rollup
# 所需插件
import typescript from 'rollup-plugin-typescript2'; // 处理typescript
import babel from 'rollup-plugin-babel'; // 处理es6
import resolve from '@rollup/plugin-node-resolve'; // 你的包用到第三方npm包
import commonjs from '@rollup/plugin-commonjs'; // 你的包用到的第三方只有commonjs形式的包
import builtins from 'rollup-plugin-node-builtins'; // 如果你的包或依赖用到了node环境的builtins fs等
import globals from 'rollup-plugin-node-globals'; // 如果你的包或依赖用到了globals变量
import { terser } from 'rollup-plugin-terser'; // 压缩,可以判断模式,开发模式不加入到plugins
# 发布配置
export default {
input: 'src/index.ts', // 源文件入口
output: [
{
file: 'dist/index.esm.js', // package.json 中 "module": "dist/index.esm.js"
format: 'esm', // es module 形式的包, 用来import 导入, 可以tree shaking
sourcemap: true
}, {
file: 'dist/index.cjs.js', // package.json 中 "main": "dist/index.cjs.js",
format: 'cjs', // commonjs 形式的包, require 导入
sourcemap: true
}, {
file: 'dist/index.umd.js',
name: 'GLWidget',
format: 'umd', // umd 兼容形式的包, 可以直接应用于网页 script
sourcemap: true
}
],
plugins: plugins
}
这样就可以同时发布3种格式的包供其他人选择使用
# 发布ts声明文件
tsconfig.json
{
"compilerOptions": {
"declaration": true // 生成*.d.ts
...
}
...
}
如果rollup-plugin-typescript2没有额外配置的话,会在dist文件夹生成对应的声明文件,在package.json中指定types 字段,那其他人用typescript开发时就可以获取提示了
{
"types": "dist/index.d.ts"
...
}
# 自定义插件
在开发中我有个需求,想要模块化glsl,这样可以更好的组织shader代码,另一方面编写glsl文件可以获得编辑器的提示和高亮辅助
# 已有方案
现在有比较知名的库glslify来做模块化,我为什么没用呢
- 因为我想做webgl库,把glslify整个打包进来没有必要,我的glsl应该在编译好后就不会有太大变更了
那怎么不用glslify的rollup插件在打包阶段解决呢
- glslify其实做的是模块化,我的需求更多的是类似include把代码插入的功能
那听起来和scss做的模块化类似,可以@import 变量进来,那我就仿照scss的方式写一个简单的rollup插件解决自己的需求
# 插件形式
function includeText(userOptions = {}) {
return {
name: 'include-text',
async transform(source, id) { // hooks
let transformedCode = xxx(souce) // 按你的方式改变code
return { code: `export default ${JSON.stringify(transformedCode.toString())}`, map: { mappings: '' }};
}
}
module.exports = includeText;
# 主要功能
我主要用了transform这个hook,source是代码,id是这个代码对应的文件,我要做的就是
- 找到代码里的@import "**/*.glsl";
- 递归把代码替换到相应的位置
- 压缩glsl代码,去掉注释、空行、代码段的回车等
- 因为glsl代码不是js,为了后续正常处理,将代码转成string,export出去当做js的string变量来处理
# 监听文件变化
到这里基本功能就完成了,在使用中会发现,你修改js中import的glsl中代码,是可以触发自动编译打包的,但是glsl中import的glsl文件是无法触发的,那么就要用到addWatchFile这个api
async transform(source, id) {
this.addWatchFile(xxx)
}
递归的将所有找到的@import文件全部进行addWatchFile操作
# 总结
以上就是在GLWidget项目中用到rollup相关内容,完成了用typescript编写,发布3种形式npm包的步骤,在过程中编写了处理glsl文件的插件。