背景
最近在研究一个ngptcommit命令行工具,然后想通过Rollup
+Typescript
去编译的时候,发现对Rollup
和Typescript
的编译配置有点陌生,所以希望通过本文能够对其有个系统的认知。
本文主要是项目编译基础知识,明白其为什么要这么配置,同时能够将项目完整跑起来。
参考项目地址为:node-gptcommit。
为什么不用Webpack
和Vite
呢?因为这两个对于一个命令行工具来说有点过于重了,有点啥像杀鸡焉用宰牛刀的感觉。
Rollup
Rollup是JavaScript模块打包工具,可以将现代化代码编译成更加复杂的代码,如:库或应用。默认使用 JavaScript ES6 修订版中包含的代码模块的新标准化格式,而不是以前的特殊解决方案,如 CommonJS 和 AMD等。 —— Rollup 官网
了解Rollup的打包核心思想:主要是将代码编译成符合ES模块规范的代码包,当然也可以用其相关的插件实现CommonJS规范。
接下来我们将通过下面几个步骤去完整了解Rollup:
Rollup组成部分
Rollup执行构建原理流程
结合Typescript实战
组成部分
一般我们实际使用场景是不会通过命令行去编译某个文件,而是针对整个项目去编译构建,因此一个完整
Rollup
构建项目主要有以下几个部分组成:rollup
npm包,用于执行构建命令源头,可以安装本地项目,也可以安装全局命令,但是一般是跟着项目走rollup.config.js
roll的配置文件,是所有命令的入口,也是学习Rollup的核心基础之一插件部分,rollup有丰富的插件生态,如:Babel 编译代码,运行 JSON 文件等,可以让rollup完成更多复杂构建功能
输出插件,在rollup代码分析完成之后,才可以修改代码相关事项
这基本上就是Rollup
项目构建所组成的部分了,接下来我们进行一一学习。
Rollup命令
在项目中,我们常用的命令有以下几种:
rollup -c
使用配置文件(如果使用参数但是值没有 指定, 默认就是 rollup.config.js)执行构建rollup -c -w
监听入口文件并在文件改变时重新构建rollup -c --environment BUILD:production
可以设置环境变量,会设置process.env.BUILD = 'production'
通过我们会在package.json
中的scripts
设置如下命令:
1 | { |
基本上就已经满足绝大部分项目需求了,如果有些项目需要更多命令配置,可以到官网查看命令行参数:Rollup命令行参数说明。
非命令行使用Rollup
还有一种Rollup
的使用,就是通过代码引用Rollup
实现,比如在scripts/build.js
,去引用rollup
,然后深度参与Rollup构建前后的一些事项,满足项目构建的自定义功能。
一般代码如下:
1 | const rollup = require('rollup'); |
然后package.json
中的scripts
设置如下命令:
1 | { |
配置文件
rollup.config.js
一般会放在项目根目录下,如果放在其他目录下,需要在命令行上指定对应路径,如:rollup -c xxx/rollup.config.js
。
Rollup配置文件中,我们需要关心的配置项主要有以下几个:
input
入口文件,Rollup将从这里去扫描解析代码,生成代码依赖树,支持多个output
输出配置项,主要是指的Rollup编译输出什么格式的代码,这里涉及多个配置项plugins
依赖的插件列表,需要哪些插件去扩展Rollup构建能力,不同插件配置内容也不同,后面会讲述常用的几个插件external
忽略打包模块列表,如:有些公共库,我们不需要构建进来cache
构建缓存,是否开启构建缓存,提高构建速度,依据配置内容可以才去不同缓存策略
需要注意的一个点,Rollup
是支持多套配置,比如:用来生成umd
规范的代码文件用来支持浏览器,再就生成cjs
给node使用的js文件。
针对上面几个常用的配置项,我们来一一分析它们的用法,其他的配置项可以到官网查看:Rollup完整配置项。
input
input最常见的问题就是多个入口文件,毕竟单一入口文件就很简单解决了,那么遇到有多个入口文件的时候,input
该如何配置:
1 | export default { |
结果:
input
配置的key值会作为output
中配置entryFileNames
中name
的值- 最终会输出两个文件
entry-a.js
和entry-b/index.js
output
output
相比较input
会复杂很多,但是我们所关心的主要配置项如下:
output.dir
, 构建好的代码文件放d到哪个文件夹中output.file
,针对单一入口,指定生成的文件名,如:index.esm.js
index.cjs.js
等output.format
,按照哪个代码规范去生成,目前主要有:cjs
为CommonJS规范,适用于 Node 环境和其他打包工具es
为ES规范,适用于其他打包工具以及支持<script type=module>
标签的浏览器umd
通用模块定义,生成的包同时支持amd
、cjs
和iife
三种格式- 其他有
amd
iife
等
output.globals
,用来忽略打包(umd 或 iife 规范)后的代码的代码依赖,比如:代码中依赖jquery
,且jquery
在代码使用$
标识,则可以配置:1
2
3
4
5
6
7
8
9{
...
output:{
globals: {
jquery: '$'
}
}
...
}output.name
, 以umd 或 iife 规范打包后的代码,需要注册在全局对象中的名字output.plugins
,针对输出后的代码需要进行插件扩展,如:压缩代码output.chunkFileNames
,对代码分割中产生的 chunk 文件自定义命名,默认值是:[name]-[hash].js
output.exports
,指定导出模式,有几个值:default
,等于最终导出等于export default xxx
,这里适用于单个文件入口named
,等于export default {xxx1, xxx2}
,适用于多个入口文件none
,没有export
,适用于打包web应用,不需要对外抛出对象
output.externalLiveBindings
, 是否给外部依赖生成动态绑定代码,简单的说就是是否需要将外部依赖的npm包通过转义来引入output.freeze
指定是否使用 Object.freeze() 冻结动态访问的引入对象的命名空间,禁止修改外部的依赖对象属性output.sourcemap
是否生成sourcemap文件
Typescript主要知识点:
plugins
Rollup plugin有很多,这里我们分成两块去学习,一个是如何配置plugin,另外一个是如何开发一个plugin。
配置plugin
这块内容就相对比较简单了,主要在于如何找到适合的plugin,以及它们的配置项是怎么样的。
第一个问题,到哪里找插件,Rollup官网提供一个地方去找对应plugin,awesome Rollup插件
第二个文件,如何配置plugin,具体如下:
1 | import typescript from 'rollup-plugin-typescript2'; |
开发plugin
在官网有详细的教程,这里我们简单学会如何快速完成一个插件。
首先,我们需要对Rollup执行流程有一个完整的理解,如下图生命周期钩子函数所示:
Rollup对外提供的生命周期钩子函数:
- 读取配置项 options
- 开始构建 buildStart
- 解析代码 resolveId,这里可以自定义一个解析代码器
- 加载代码 load
- 加载缓存模块 shouldTransformCacheModule
- 转义代码中 transform
- 将代码解析ES模块化后 modulePared
- 解析异步加载,如:import(()=> xxx) resolveDynamicImport
- 构建结束 buildEnd
- 监听改变中 watchChange
- 关闭监听后 closeWatcher
接下来我们来完成一个插件,就是在代码构建前,将__helloworld__
换成"hello qborfy!"
,避免代码解析出错,代码如下:
1 |
|
有两种方式去管理插件,一个是在项目直接管理维护,另外一种是通过发布npm包管理,这个取决插件是否有公用性即可。
Typescript
在本文中不讨论Typescript的具体用法,我们将学习如何将Typescript代码转为JavaScript。
如何将一个Typescript代码转义为JavaScript呢?Typescript本身提供了一个工具typescript
,因此我们针对其来学习一番。
如何使用typescript呢? 可以到官网TypeScript使用说明文档。
我们这里简单总结一下,在项目中使用Typescript,构建工具一般有以下几个步骤:
npm install typescript -D
安装Typescript工具npm install @babel/core -D
结合babel对Typescript进行转义- 配置文件
tsconfig.json
,配置一些Typescript编译功能 npm install eslint -D
,结合eslint
对代码语法做检测- 配置文件
eslint.json
,配置代码检测标准
tsconfig.json
tsconfig.json一般是放到项目根目录,如果放到其他目录,需要修改对应地址, 配置文件主要几个部分:
compilerOptions
编译时的一些配置内容watchOptions
当监听文件变化时候需要配置一些内容include
哪些文件需要编译,如:"include": ["src/**/*", "tests/**/*"]
exclude
对某些文件进行忽略,不做编译,如:"exclude": ["src/js/*"]
extends
继承其他配置文件,如:"extends": ["./base.json"]
目前我们主要使用的还是compilerOptions
,里面主要的配置项有:
paths
将部分路径进行缩写,比如:"@App/*": ["src/*"]
,后续使用@App
,就会解析成src
target
代码转义哪个ES标准下,如:ES2017,ES2018,ES2019等module
代码模块化遵循哪个标准,如:ESNext,CommonJS等strict
是否使用严格模式检测代码质量lib
编译的有时候需要依赖一些全局变量,比如:Document对象,这个时候需要设置为DOM
,或者使用Map
对象,这个时候需要ESNext
declaration
是否给每个文件都生成 声明文件.d.ts
noImplicitOverride
设置后可以提醒继承类override
同名方法时候,需要标注override
关键字noUnusedLocals
不允许有未使用的变量esModuleInterop
可以修复由于ES规范和其他规范混合使用导致的引用错误useUnknownInCatchVariables
支持catch中error设置为Unknown类型resolveJsonModule
支持json文件引入为一个模块
对Rollup
和Typescript
都有一定了解后,接下来我们就来实战Rollup
+Typescript
工程化项目。
实战
- 初始化项目
新建一个文件夹demo-rollup
,后续命令如下:
1 | mkdir demo-rollup |
- 安装依赖
- 安装rollup相关依赖
1 | pnpm add rollup -D |
- 安装Typescript相关依赖
1 | pnpm add typescript tslib -D |
- 安装babel
1 | pnpm add @babel/core @babel/preset-env @babel/plugin-proposal-class-properties -D |
- 安装rollup相关插件
1 | pnpm add @rollup/plugin-babel -D #babel插件 |
- 安装其他依赖
1 | pnpm add rimraf -D |
- 配置rollup.config.js
1 | import typescript from 'rollup-plugin-typescript2'; // 处理typescript |
- 配置tsconfig.json
1 | { |
- 配置package.json
添加dev和build命令脚本,如下所示:
1 | { |
- 编写demo代码
1 | // sum.ts |
- 测试运行
1 | pnpm run dev |
查看生成dist/index.js
和 dist/index.esm.js
。
完整项目源码地址:demo-rollup
- 本文作者: Qborfy
- 本文链接: https://www.qborfy.com/today/20230222.html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!