当前位置: 首页 > news >正文

使用 Gulp + Webpack 打造一个完整的 TypeScript 库构建流程

在前端开发中,我们经常需要开发自己的 工具函数库Hooks 库 或者 组件库,并发布到 npm。这样的库通常有几个常见的需求:

  1. 提供 ES Module(ESM)版本,方便现代项目 import 使用;
  2. 提供 CommonJS(CJS)版本,兼容 Node.js 或老项目 require 使用;
  3. 提供 类型声明文件(.d.ts),方便 TypeScript 用户;
  4. 额外提供一个 UMD 包,可以让用户直接通过 <script> 从 CDN 引入,全局访问;

本文将带你基于 Gulp + TypeScript + Babel + Webpack 打造一条完整的构建流水线 🚦。


🔧 为什么选择 Gulp + Webpack

  • Gulp:擅长文件处理和任务流,适合执行「清理 → 编译 → 转换 → 输出」一系列步骤(或更多自定义复杂步骤)。
  • Webpack:擅长打包成单个文件,特别是 UMD 格式,方便浏览器直接使用。

两者结合的好处是:
👉 Gulp 做 模块构建(ESM/CJS/d.ts),保证 npm 使用;
👉 Webpack 做 UMD 打包,保证浏览器/CDN 使用。

这样,我们的库就能“一鱼多吃”,覆盖所有使用场景。


📂 项目构建需求

  1. 清理旧的构建产物(es/lib/dist/
  2. 输出 ESM 版本 → 放在 es/
  3. 输出 CJS 版本 → 放在 lib/
  4. 生成 类型声明文件 d.ts
  5. 复制 README.md 到子包目录
  6. 调用 Webpack 输出 UMD 包 → 放在 dist/

最终目录结构如下:

packages/hooks/
├── es/              # ESM 构建结果
├── lib/             # CJS 构建结果
├── dist/            # UMD 构建结果
│   └── index.umd.js 
├── README.md        # 子包说明文档
└── package.json

🛠️ 构建脚本

1. Gulp 脚本(gulpfile.js)

const gulp = require('gulp');
const del = require('del');
const babel = require('gulp-babel');
const ts = require('gulp-typescript');
const webpack = require('webpack');
const webpackConfig = require('./webpack.config.js');// 清理目录
gulp.task('clean', async () => {await del(['lib/**', 'es/**', 'dist/**']);
});// 编译 ESM
gulp.task('es', () => {const tsProject = ts.createProject('tsconfig.pro.json', { module: 'ESNext' });return tsProject.src().pipe(tsProject()).pipe(babel()).pipe(gulp.dest('es/'));
});// 编译 CJS
gulp.task('cjs', () => {return gulp.src('es/**/*.js').pipe(babel({ configFile: '../../.babelrc' })).pipe(gulp.dest('lib/'));
});// 类型声明
gulp.task('declaration', () => {const tsProject = ts.createProject('tsconfig.pro.json', {declaration: true,emitDeclarationOnly: true,});return tsProject.src().pipe(tsProject()).pipe(gulp.dest('es/')).pipe(gulp.dest('lib/'));
});// 复制 README
gulp.task('copyReadme', async () => {await gulp.src('../../README.md').pipe(gulp.dest('../../packages/hooks'));
});// 调用 webpack 打包 UMD
gulp.task('umd', (done) => {webpack(webpackConfig, (err, stats) => {if (err) console.error(err);console.log(stats?.toString({ colors: true }));done();});
});// 默认构建任务
exports.default = gulp.series('clean', 'es', 'cjs', 'declaration', 'copyReadme', 'umd');

2. Webpack 配置(webpack.config.js)

const path = require('path');module.exports = {entry: './src/index.js',output: {filename: 'index.umd.js',path: path.resolve(__dirname, 'dist'),libraryTarget: 'umd',   // 输出UMD格式globalObject: 'this',   // 兼容node和浏览器library: 'MyLibrary',   // 挂载到全局对象 window.MyLibrary},mode: 'production',resolve: {extensions: ['.ts', '.js', '.json'],},module: {rules: [{test: /\.(ts|js)$/,exclude: /node_modules/,use: 'babel-loader',},],},externals: {react: 'React', // react 作为外部依赖,不打包进来},
};

📦 构建产物 & 使用方式

构建产物包括三种:

  1. ESM(现代前端项目)

    import { useMyHook } from 'my-hooks/es';
    
  2. CJS(Node.js 或老项目)

    const { useMyHook } = require('my-hooks/lib');
    
  3. UMD(CDN / 浏览器脚本)

    <script src="https://cdn.xxx.com/my-hooks/dist/index.umd.js"></script>
    <script>const { useMyHook } = window.MyLibrary;
    </script>
    

⚡ 整体构建命令

# 编译 ESM/CJS/d.ts + 打包 UMD
gulp

这样一条命令,就完成了从 源码 → npm 包 → 浏览器包 的全流程。


✨ 总结

  • Gulp 控制任务流,适用于多产物输出(ESM / CJS / d.ts);
  • Webpack 打包成一个独立的 UMD 文件,方便 CDN 与浏览器使用;
  • 两者结合,覆盖所有使用场景,构建过程既灵活又全面。

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏或留言交流 😊


文章转载自:

http://VGbkNFG1.xcdph.cn
http://KRKZ0dvb.xcdph.cn
http://FC8kz6NZ.xcdph.cn
http://jX116Ws2.xcdph.cn
http://PKlKC0DN.xcdph.cn
http://bpiVYoqs.xcdph.cn
http://ry8jCCLt.xcdph.cn
http://SUHfZw5l.xcdph.cn
http://hhSgiIvZ.xcdph.cn
http://ibhdgsh5.xcdph.cn
http://OYmVZBPJ.xcdph.cn
http://CNYJr63y.xcdph.cn
http://q7fc3eMh.xcdph.cn
http://nIH809XS.xcdph.cn
http://ew4xoREh.xcdph.cn
http://M3i4eOYq.xcdph.cn
http://Q8T5DXEV.xcdph.cn
http://qT0efLbQ.xcdph.cn
http://tzCCvL9z.xcdph.cn
http://6hYyTnmE.xcdph.cn
http://KEPMBOpe.xcdph.cn
http://isexkkjF.xcdph.cn
http://LvuNKces.xcdph.cn
http://FkQaINfj.xcdph.cn
http://VdGkvuxG.xcdph.cn
http://OemC2OD8.xcdph.cn
http://CS6fMJPV.xcdph.cn
http://DFyNVySG.xcdph.cn
http://uAnyUmqF.xcdph.cn
http://re6XmwiO.xcdph.cn
http://www.dtcms.com/a/363188.html

相关文章:

  • STL库——deque/priority_queue
  • Mysql安全之 TDE ,列加密,审计日志
  • SpringCloud(6)-优雅实现远程调用-OpenFeign
  • 基于springboot的“衣依”服装销售平台
  • git通过https和SSH上传gitee仓库
  • MongoDb(①免安装)
  • ​​​​​​​Blender 重拓扑修改器实战指南:从基础操作到细节优化​
  • Meta AIUCSD放大招:DeepConf 让大语言模型推理既快又准,84.7%的token节省+近乎完美的准确率!
  • WMT2014:机器翻译领域的“奥林匹克盛会“
  • 大模型RAG项目实战:RAG技术原理及核心架构
  • (TMLR-2024)DINOv2:在无监督条件下学习鲁棒的视觉特征
  • 【Element-Plus】媒体预览模态框优化实战:从复杂到简洁的设计之路
  • WHAT - HTMLRewriter 介绍(页面优化、SEO、广告注入)
  • C++入门自学Day17-- 模版进阶知识
  • 从程序员到「认识罕见病 DAO」发起人,他用 Web3 承载爱与责任
  • C# 简述委托,Func与Action委托。 他们之前有什么区别?
  • MCU上跑AI—实时目标检测算法探索
  • 将css中的线性渐变,径向渐变,锥心渐变,转成canvas中的渐变
  • 【高并发内存池】三、线程缓存的设计
  • SpringBoot3中使用Caffeine缓存组件
  • Ruoyi-vue-plus-5.x第三篇Redis缓存与分布式技术:3.2 缓存注解与使用
  • 悬停头部的实现方式之一 css: position: sticky
  • SQL Server-查询事务日志
  • 血缘元数据采集开放标准:OpenLineage Guides 在 Spark 中使用 OpenLineage
  • B2B营销面临的一些主要问题
  • 3025. 人员站位的方案数 I
  • HDI线路板与普通板有何区别?厂家生产难度在哪?
  • 【leetcode】236. 二叉树的最近公共祖先
  • 《“人工智能+”行动意见》深度解析:从智能红利到产业落地,直播SDK的技术价值与应用路径
  • Kafka:Java开发的消息神器,你真的懂了吗?