【前端工程化】tsup入门

定义

tsup 是一个基于 ESBuild 实现在零配置的情况下快速打包 Typescript 模块的库,支持 .ts、.tsx的转换~

它基于esbuild,但是同时也选择融合其他的构建工具共同参与,弥补了esbuild的不足。比如tree shaking的功能依赖的是rollup~

基本使用

npm i react react-dom
npm i @types/react @types/react-dom -D
npm i tsup -D

新建index.tsx

import * as React from 'react'
import * as Server from 'react-dom/server'

let Greet = () => <h1>Hello, world!</h1>
console.log(Server.renderToString(<Greet />))

新建tsup.config.ts:

import { defineConfig } from 'tsup'

export default defineConfig({
  // 入口文件
  entry: ['index.tsx'],
  // 是否生成对应的调试源文件
  sourcemap: true,
  // 打包之前是否先清空dist文件
  clean: true,
})

执行:

npm run tsup

就会生成下列文件:

- dist
  - index.js
  - index.js.map

压缩代码

export default defineConfig ((options) => {
  return {
    // ...
    // 是否压缩代码
    minify: true,
  }
})

是否拆分打码

// content.ts
export const str = 'Hello tsup';

// index.ts
const str = import('./content');
console.log({ str });

默认情况下打包是拆分文件的,即有两个文件:

import { defineConfig } from 'tsup'

export default defineConfig ({
  // 入口文件
  entry: ['index.ts'],
  // 是否生成对应的调试源文件
  sourcemap: false,
  // 打包之前是否先清空dist文件
  clean: true,
  // 是否压缩代码
  // minify: true,
  // 输出格式
  format: "esm"
})

如果想让两个文件输出变成一个文件输出,可以修改为:

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 输出格式
  format: "esm",
  // 是否进行拆分
  splitting: false,
})

Tree Shaking

官网说可以通过如下配置达到tree shaing

export default defineConfig({
  treeshake: true,
})

但是我发现我不配置的话也是可以的(设置成false也是可以的):

// index.ts
function test() {
  console.log(123);
}
let name = '测试测试';
function fn() {
  console.log(name);
}

fn();

打包出来的结果删除了test函数。

另外这里的tree shaking就是借助的是rollup而非esbuild。顺带一提,由于 ESBuild 天生不支持到 es5 的语法降级,所以这里借助的是SWC,在由 esbuild 将代码编译为 es2020 后由 SWC 接管语法降级部分再次编译降级为 es5 语法。

开启监听模式

"scripts": {
    "dev": "npx tsup --watch"
  },

执行npm run dev,修改index.ts之后会自动编译。

增加忽略监听的配置:

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 忽略监听的文件
  ignoreWatch: ['assets', 'public']
})

这样执行的时候会显示:

CLI Watching for changes in "."
CLI Ignoring changes in "**/{.git,node_modules}/**" | "dist" | "assets" | "public"

抹平 cjsmjs

由于在 cjs 中就需要用到 __dirnamemjs 则需要用到 import.meta.url,所以需要开启注入垫片,编译后的代码才可以正常工作。

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 是否开启垫片
  shims: true
})

复制文件

新建public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="./index.js"></script>
</body>
</html>

配置:

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 复制文件到dist目录中
  publicDir: './public
})

这样打包的dist文件中为:

- dist
  - index.html
  - index.js

支持环境变量

// package.json
"scripts": {
    "dev": "npx tsup --watch --env.NODE_ENV development",
    "build": "npx tsup --env.NODE_ENV production"
 },

// ts.config.js
import { defineConfig } from 'tsup'

export default defineConfig ((options: {[key: string]: any}) => {
  const { NODE_ENV } = options.env;
  console.log('NODE_ENV', NODE_ENV, NODE_ENV === 'production');

  return {
    // ...
    minify: NODE_ENV === 'production',
    // ...
  }
})


是否生成DTS文件

// index.ts
export const name: string = 'Armouy';

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 是否生成dts文件
    dts: true
})

这样打包出来的文件就多了一个index.d.ts

declare const name: string;

export { name };

指定外部模块

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 指定哪些模块应该被视为外部模块
  external: ['react', 'react-dom']
})

配置loader

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  loader: {
    // .png 为后缀的文件将按 base64 处理
    '.png': 'base64',
    // .webp为后缀的文件将按 file 处理
    '.webp': 'file',
    // ...
  },
})

成功回调

import { defineConfig } from 'tsup'

export default defineConfig ({
  // ...
  // 打包成功后的回调函数
    async onSuccess() {
      console.log('success')
    },
})

ts.config.ts

import { defineConfig } from 'tsup'

export default defineConfig ((options: {[key: string]: any}) => {
  const { NODE_ENV } = options.env;
  console.log('NODE_ENV', NODE_ENV, NODE_ENV === 'production');

  return {
    // 入口文件
    entry: ['index.ts'],
    // 是否生成对应的调试源文件
    sourcemap: false,
    // 打包之前是否先清空dist文件
    clean: true,
    // 是否压缩代码
    minify: NODE_ENV === 'production',
    // 输出格式
    format: "cjs",
    // 是否进行拆分
    splitting: true,
    // 忽略监听的文件
    ignoreWatch: ['assets', 'public'],
    // 是否开启垫片
    shims: true,
    // 复制文件到dist目录中
    publicDir: './public',
    // 是否生成dts文件
    dts: true,
    // 指定哪些模块应该被视为外部模块
    external: ['react', 'react-dom'],
    loader: {
      // .png 为后缀的文件将按 base64 处理
      '.png': 'base64',
      // .webp为后缀的文件将按 file 处理
      '.webp': 'file',
    },
    // 打包成功后的回调函数
    async onSuccess() {
      console.log('success')
    },
  }
})

参考链接


如有错误欢迎指出,感谢阅读~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值