From f74d8990cb23ccf905d78fdabd0803017dcf89bf Mon Sep 17 00:00:00 2001 From: windychen Date: Wed, 27 May 2026 14:28:02 +0800 Subject: [PATCH] Initial commit --- .gitignore | 23 ++++ .memory-bank/2026-05-25-session.md | 173 +++++++++++++++++++++++++++++ README.md | 101 +++++++++++++++++ array.js | 46 ++++++++ index.html | 120 ++++++++++++++++++++ index.js | 4 + object.js | 74 ++++++++++++ package.json | 22 ++++ storage.js | 168 ++++++++++++++++++++++++++++ test.js | 67 +++++++++++ webpack.config.js | 44 ++++++++ 11 files changed, 842 insertions(+) create mode 100644 .gitignore create mode 100644 .memory-bank/2026-05-25-session.md create mode 100644 README.md create mode 100644 array.js create mode 100644 index.html create mode 100644 index.js create mode 100644 object.js create mode 100644 package.json create mode 100644 storage.js create mode 100644 test.js create mode 100644 webpack.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d8e09c --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Dependencies +node_modules/ + +# Build output +dist/ + +# OS files +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Logs +*.log +npm-debug.log* + +# Environment +.env +.env.local diff --git a/.memory-bank/2026-05-25-session.md b/.memory-bank/2026-05-25-session.md new file mode 100644 index 0000000..8b0bebc --- /dev/null +++ b/.memory-bank/2026-05-25-session.md @@ -0,0 +1,173 @@ +# Windychen Utils 项目开发记录 + +**日期**: 2026-05-25 +**项目**: windychen-untils (v1.0.0) +**类型**: 轻量级 JavaScript 工具库 + +--- + +## 一、已完成功能模块 + +### 1. Object 扩展 (`object.js`) + +| 方法 | 功能 | 特性 | +|------|------|------| +| `getPro(path, defaultValue?)` | 安全获取嵌套属性 | 支持点分隔路径、特殊键名(含`.`)、混合路径、默认值回退 | +| `setPro(path, value)` | 设置嵌套路径值 | 自动创建中间对象,支持特殊键名 | + +**路径格式示例:** +```javascript +obj.getPro('a.b.c'); // 普通点分隔 +obj.getPro("['x.y'].z"); // 特殊键名 +obj.getPro("['a.b'].c['d']"); // 混合嵌套 +``` + +**优化点:** +- 提取 `_parsePath()` 公共函数消除重复代码 +- 使用正则 `\[['"]([^'"]+)['"]\]|[^.\[\]]+` 统一解析所有 key 格式 +- 最终代码量:26 行(原 47 行,精简 45%) + +--- + +### 2. Array 扩展 (`array.js`) + +6 个增强方法,均支持三种调用方式: + +| 方法 | 对应原生 | 说明 | +|------|---------|------| +| `findPro(a, b?)` | find() | 查找首个匹配项 | +| `filterPro(a, b?)` | filter() | 过滤所有匹配项 | +| `findIndexPro(a, b?)` | findIndex() | 返回索引 | +| `findLastPro(a, b?)` | findLast() | 从末尾查找 | +| **somePro(a, b?)** | some() | 任一满足 | +| **everyPro(a, b?)** | every() | 全部满足 | + +**三种调用模式:** +```javascript +// 模式1: 回调函数 +arr.findPro(item => item.id > 1); + +// 模式2: 单值精确匹配 +['aa','bb'].findPro('bb'); + +// 模式3: key-value 匹配(支持 getPro 嵌套路径) +arr.findPro('user.info.name', 'Alice'); +``` + +**优化点:** +- 提取 `_resolveMatcher()` 统一参数判断逻辑 +- 循环生成 6 个 Pro 方法,零重复代码 +- key-value 模式接入 `getPro` 支持深层路径访问 +- 处理 null/undefined 边界(`item != null && ...`) +- 最终代码量:12 行(原 64 行,精简 81%) + +--- + +### 3. Storage 存储 (`storage.js`) + +浏览器环境专用: + +| 类 | 存储后端 | 特点 | +|----|---------|------| +| `IDBStorage` | IndexedDB | 大容量存储 | +| `ILocalStorage` | localStorage + Map 缓存 | 兼容性好,启动时全量加载 | + +**自动选择策略:** +```javascript +window.indexedDB ? IDBStorage : (localStorage ? ILocalStorage : null) +``` + +**API:** +- `storage.set(key, value)` → Promise +- `storage.get(key, initValue)` → Promise + +--- + +## 二、工程化配置 + +### 构建系统 (Webpack) + +**配置文件**: `webpack.config.js`(单文件,多模式) + +```bash +npm run build # 全部 (CJS + ESM + UMD) +npm run build:cjs # CommonJS 格式 +npm run build:esm # ES Module 格式 +npm run build:umd # UMD 浏览器格式 +npm run dev # 开发模式 +``` + +**输出产物:** + +| 格式 | 文件 | 入口字段 | +|------|------|---------| +| CJS | dist/windychen-utils.cjs.js | main | +| ESM | dist/windychen-utils.esm.js | module | +| UMD | dist/windychen-utils.js | browser | + +**演进过程:** +1. 初始创建 3 个独立 webpack 配置文件 +2. 发现 `.esm.js` 后缀被 webpack-cli 误识别为 esm 加载器 +3. 重命名解决加载异常 +4. 发现 `experiments` 应在顶层而非 output 内 +5. **最终收敛为单文件 + --env 参数方案** + +--- + +### 项目结构 + +``` +e:\project\utils\ +├── index.js # 统一入口,聚合各模块 +├── object.js # Object 原型扩展 (getPro/setPro) +├── array.js # Array 原型扩展 (6个Pro方法) +├── storage.js # 浏览器存储封装 (IndexedDB/LS) +├── webpack.config.js # 打包配置 (单文件多模式) +├── package.json # 项目元信息 & 脚本 +├── .gitignore # Git 忽略规则 +├── test.js # Node/Bun 端测试 +├── index.html # 浏览器端测试页面 +├── README.md # 项目文档 +└── dist/ # 构建产物输出目录 +``` + +--- + +## 三、测试体系 + +### Node.js / Bun 测试 (`test.js`) +- 直接 require 源码运行 +- 彩色终端输出 (✓/✗) +- 覆盖全部 API 的核心场景 +- 失败时 process.exit(1) +- 命令: `npm test` + +### 浏览器测试 (`index.html`) +- 引入 dist/windychen-utils.js (UMD) +- 深色主题 UI 展示结果 +- 绿色通过 / 红色失败 +- 命令: `npm run build:umd && open index.html` + +**已修复 Bug:** +- array.js 中 `_resolveMatcher` 未处理 item 为 null/undefined 导致的 TypeError +- 修复: `item != null && item.getPro(...)` + +--- + +## 四、关键决策记录 + +1. **Prototype 扩展方式**: 直接扩展 Object/Array 原型,使用时无需导入,全局可用 +2. **路径解析设计**: 正则统一处理普通键和特殊键(含点号),避免分支逻辑 +3. **Array Pro 方法设计**: 参数重载(function/string+value/value)覆盖常见使用场景 +4. **Storage 自动降级**: IndexedDB → localStorage → null,最大化兼容性 +5. **Webpack 单配置**: 通过 --env format 参数控制输出,避免维护多个配置文件 + +--- + +## 五、待改进方向 + +- [ ] 添加单元测试框架(如 Jest/Vitest) +- [ ] 支持 TypeScript 类型声明 (.d.ts) +- [ ] Storage 模块添加 delete/clear 方法 +- [ ] 考虑添加更多工具方法(日期、字符串、数字等) +- [ ] CI/CD 自动化构建与发布 diff --git a/README.md b/README.md new file mode 100644 index 0000000..51b448d --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# Windychen Utils + +轻量级 JavaScript/TypeScript 工具库,提供对象、数组、存储等常用扩展方法。 + +## 安装 + +```bash +npm install windychen-untils +``` + +## 使用 + +### Node.js / Bun.js + +```javascript +require('windychen-untils'); + +// Object 扩展 +const obj = { a: { b: { c: 1 } } }; +obj.getPro('a.b.c'); // 1 +obj.setPro('x.y.z', 'hello'); + +// Array 扩展 +[{ id: '1' }, { id: '2' }].findPro('id', '2'); +``` + +### 浏览器 + +```html + +``` + +### ES Module + +```javascript +import from 'windychen-untils/dist/windychen-utils.esm.js'; +``` + +## API 参考 + +### Object + +| 方法 | 说明 | 示例 | +|------|------|------| +| `getPro(path, default?)` | 安全获取嵌套属性,支持特殊键名 | `obj.getPro('a.b.c')` / `obj.getPro("['x.y'].z")` | +| `setPro(path, value)` | 设置嵌套路径值,自动创建中间对象 | `obj.setPro('foo.bar', 1)` | + +**路径格式支持:** +- 普通点分隔:`'a.b.c'` +- 特殊键名:`"['key.with.dot']"` +- 混合:`"['a.b'].c['d.e']"` + +### Array + +| 方法 | 说明 | 示例 | +|------|------|------| +| `findPro(fn \| key, val?)` | 增强查找 | `arr.findPro('id', '2')` | +| `filterPro(fn \| key, val?)` | 增强过滤 | `arr.filterPro('user.name', 'Alice')` | +| `findIndexPro(fn \| key, val?)` | 增强索引查找 | `arr.findIndexPro('status', 1)` | +| `findLastPro(fn \| key, val?)` | 从末尾查找 | `arr.findLastPro('type', 'b')` | +| **somePro(fn \| key, val?)** | 任一匹配 | `arr.somePro('active', true)` | +| **everyPro(fn \| key, val?)** | 全部匹配 | `arr.everyPro('valid', true)` | + +**三种调用方式:** +```javascript +// 回调函数(同原生) +arr.findPro(item => item.id > 1); + +// 单值精确匹配 +['aa', 'bb'].findPro('bb'); + +// key-value 匹配(支持嵌套路径) +[{ user: { name: 'Bob' } }].findPro('user.name', 'Bob'); +``` + +### Storage(浏览器环境) + +自动选择存储后端: +- 支持 IndexedDB → 使用 `IDBStorage` +- 仅支持 localStorage → 使用 `ILocalStorage`(内存缓存) + +```javascript +import storage from 'windychen-untils'; + +await storage.set('key', { data: 123 }); +await storage.get('key', null); // { data: 123 } +``` + +## 构建 + +```bash +npm run build # 打包全部 (CJS + ESM + UMD) +npm run build:cjs # CommonJS +npm run build:esm # ES Module +npm run build:umd # UMD (浏览器) +npm test # 运行测试 +``` + +## License + +ISC diff --git a/array.js b/array.js new file mode 100644 index 0000000..48694ce --- /dev/null +++ b/array.js @@ -0,0 +1,46 @@ +/** + * 解析 Pro 方法的匹配器参数 + * @param {(Function|string|*)} a - 回调函数、属性键、或单值 + * @param {*=} b - 属性值(与 a 配合使用) + * @returns {function(*): boolean} 匹配函数 + * @private + */ +const _resolveMatcher = (a, b) => { + if (typeof a === 'function') return a; + if (typeof a === 'string' && b !== undefined) return (item) => item != null && item.getPro(a) === b; + return (item) => item === a; +}; + +/** @private @type {string[]} 支持增强方法的原始方法列表 */ +const _methods = ['find', 'filter', 'findIndex', 'findLast', 'some', 'every']; + +_methods.forEach((method) => { + /** + * 增强版数组遍历方法,支持三种调用模式 + * + * **模式1 - 回调函数**(同原生方法) + * @example + * arr.findPro(item => item.id > 1) + * arr.filterPro(item => item.active) + * + * **模式2 - 单值精确匹配** + * @example + * ['aa','bb','cc'].findPro('bb') + * [1,2,2,3].filterPro(2) + * + * **模式3 - key-value 匹配**(支持嵌套路径,通过 getPro 访问) + * @example + * [{ user: { name: 'Bob' } }].findPro('user.name', 'Bob') + * arr.filterPro('status', 1) + * + * @name ${method}Pro + * @memberof Array.prototype + * @method + * @param {(Function|string|*)} a - 回调函数、属性键、或单值 + * @param {*=} [b] - 属性值(当 a 为 string 时使用) + * @returns {*} 返回结果同对应原生方法 + */ + Array.prototype[`${method}Pro`] = function (a, b) { + return this[method](_resolveMatcher(a, b)); + }; +}); diff --git a/index.html b/index.html new file mode 100644 index 0000000..b0c8d70 --- /dev/null +++ b/index.html @@ -0,0 +1,120 @@ + + + + + Windychen Utils - 浏览器测试 + + + +

Windychen Utils 测试结果

+
+ + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..0e6909b --- /dev/null +++ b/index.js @@ -0,0 +1,4 @@ +require('./object'); +require('./array'); + +try { require('./storage'); } catch (e) {} // 仅浏览器环境生效 diff --git a/object.js b/object.js new file mode 100644 index 0000000..6b30941 --- /dev/null +++ b/object.js @@ -0,0 +1,74 @@ +/** + * 获取值的类型字符串 + * @param {*} val - 任意值 + * @returns {string} 类型名称,如 'String' 'Number' 'Array' 'Null' 'Undefined' + * @example + * Object.getTypeString('hello') // 'String' + * Object.getTypeString(123) // 'Number' + * Object.getTypeString(null) // 'Null' + */ +Object.getTypeString = function (val) { + return Object.prototype.toString.call(val).replace(/\[object |]/g, ''); +}; + +/** + * 解析路径字符串为键数组 + * @param {string} path - 路径字符串,支持点分隔、特殊键名、混合格式 + * @returns {string[]} 键数组 + * @private + */ +const _parsePath = (path) => { + const keys = []; + const keyRegex = /\[['"]([^'"]+)['"]\]|[^.\[\]]+/g; + let match; + while ((match = keyRegex.exec(path)) !== null) { + keys.push(match[1] || match[0]); + } + return keys; +}; + +/** + * 安全获取对象嵌套属性 + * @param {string} path - 属性路径,支持多种格式: + * - 普通点分隔: 'a.b.c' + * - 特殊键名: "['key.with.dot']" + * - 混合: "['a.b'].c['d.e']" + * @param {*=} defaultValue - 路径不存在或值为 undefined 时返回的默认值 + * @returns {*} 找到的属性值或默认值 + * @example + * { a: { b: { c: 1 } } }.getPro('a.b.c') // 1 + * { a: { b: { c: 1 } } }.getPro('a.x.y', 'default') // 'default' + * { 'x.y': { z: 2 } }.getPro("['x.y'].z") // 2 + */ +Object.prototype.getPro = function (path, defaultValue) { + let result = this; + for (const key of _parsePath(path)) { + if (result == null) return defaultValue; + result = result[key]; + } + return result !== undefined ? result : defaultValue; +}; + +/** + * 设置对象嵌套路径值(自动创建中间对象) + * @param {string} path - 属性路径,格式同 getPro + * @param {*} value - 要设置的值 + * @returns {void} + * @example + * const obj = {}; + * obj.setPro('a.b.c', 1); // obj => { a: { b: { c: 1 } } } + * obj.setPro("['x.y'].z", 2); // obj => { a: {...}, 'x.y': { z: 2 } } + */ +Object.prototype.setPro = function (path, value) { + const keys = _parsePath(path); + let target = this; + + for (let i = 0; i < keys.length - 1; i++) { + if (target[keys[i]] == null || typeof target[keys[i]] !== 'object') { + target[keys[i]] = {}; + } + target = target[keys[i]]; + } + + target[keys[keys.length - 1]] = value; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..58dc1ed --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "windychen-untils", + "version": "1.0.0", + "main": "dist/windychen-utils.cjs.js", + "module": "dist/windychen-utils.esm.js", + "browser": "dist/windychen-utils.js", + "scripts": { + "build": "webpack --mode production", + "build:cjs": "webpack --mode production --env format=cjs", + "build:esm": "webpack --mode production --env format=esm", + "build:umd": "webpack --mode production --env format=umd", + "dev": "webpack --mode development", + "test": "node test.js" + }, + "author": "windychen", + "license": "ISC", + "description": "", + "devDependencies": { + "webpack": "^5.90.0", + "webpack-cli": "^5.1.4" + } +} \ No newline at end of file diff --git a/storage.js b/storage.js new file mode 100644 index 0000000..b247bb1 --- /dev/null +++ b/storage.js @@ -0,0 +1,168 @@ +/** @type {Function} 日志输出 */ +var log = console.warn; + +/** + * 判断值是否为 String 类型 + * @param {*} str - 待检测值 + * @returns {boolean} + * @private + */ +var isString = function (str) { return Object.getTypeString(str) === 'String'; }; + +/** + * IndexedDB 存储实现(大容量存储优先选择) + * + * @class IDBStorage + * @example + * const storage = new IDBStorage('myDb', 'myStore', 1); + * await storage.set('key', { data: 123 }); + * await storage.get('key', null); + */ +class IDBStorage { + /** + * 创建 IndexedDB 存储实例 + * @param {string} [dbName='dbName'] - 数据库名称 + * @param {string} [storeName='storeName'] - 对象存储名称 + * @param {number} [version=1] - 数据库版本号 + */ + constructor(dbName, storeName, version) { + /** @type {number} 数据库版本号 */ + this.version = version || 1; + /** @type {string} 数据库名称 */ + this.dbName = dbName || 'dbName'; + /** @type {string} 对象存储名称 */ + this.storeName = storeName || 'storeName'; + + var request = indexedDB.open(this.dbName, this.version); + /** @type {Promise} 数据库连接 Promise */ + this.requestPromise = new Promise(function (resolve, reject) { + request.onupgradeneeded = function (e) { + if (e && e.target && !request.result.objectStoreNames.contains(this.storeName)) { + request.result.createObjectStore(this.storeName, { keyPath: 'key' }) + .createIndex('key', 'key', { unique: false }); + } + log('[Index][open]-upgrade'); + resolve(request.result); + }.bind(this); + request.onsuccess = function () { log('[IndexDB][open]-success'); resolve(request.result); }; + request.onerror = function (e) { log('[IndexDB][open]-error', 2); reject(e); }; + }.bind(this)); + } + + /** + * 获取存储值 + * @template T + * @param {string} key - 键名 + * @param {T} initValue - 默认值(未找到时返回) + * @returns {Promise} 存储的值或默认值 + */ + get(key, initValue) { + var _this = this; + return new Promise(async function (resolve) { + var db = await _this.requestPromise; + var transaction = db.transaction(_this.storeName, 'readonly'); + var objectStore = transaction.objectStore(_this.storeName); + var req = objectStore.get(key); + req.onsuccess = function () { resolve(req.result ? req.result.value : (initValue || null)); }; + req.onerror = function (e) { log('[indexDB][get]-error', 2, e); resolve(initValue || null); }; + }); + } + + /** + * 设置存储值 + * @template T + * @param {string} key - 键名 + * @param {T} value - 要存储的值 + * @returns {Promise} 返回写入的值 + */ + set(key, value) { + var _this = this; + return new Promise(async function (resolve) { + var db = await _this.requestPromise; + var transaction = db.transaction(_this.storeName, 'readwrite'); + var objectStore = transaction.objectStore(_this.storeName); + var req = objectStore.put({ key: key, value: value }); + req.onsuccess = function () { resolve(value); }; + req.onerror = function (e) { log('[indexDB][set]-error', 2, e); resolve(value); }; + }); + } +} + +/** + * localStorage 存储实现(兼容性好,带内存缓存) + * + * @class ILocalStorage + * @example + * const storage = new ILocalStorage(); + * await storage.set('key', { data: 456 }); + * await storage.get('key', null); + */ +class ILocalStorage { + constructor() { + /** @type {Map} 内存缓存 */ + this.cache = new Map(); + this.load(); + } + + /** 从 localStorage 全量加载到缓存 */ + load() { + var _this = this; + Object.entries(localStorage).forEach(function (entry) { + var key = entry[0], value = entry[1]; + try { + _this.cache.set(key, JSON.parse(value)); + } catch (error) { + log('[localStorage][load]-error', 2, error, key, value); + } + }); + } + + /** + * 从缓存获取值 + * @template T + * @param {string} key - 键名 + * @param {T} initValue - 默认值 + * @returns {Promise} 缓存的值或默认值 + */ + get(key, initValue) { + return new Promise(function (resolve) { + resolve(this.cache.get(key) !== undefined ? this.cache.get(key) : initValue); + }.bind(this)); + } + + /** + * 写入 localStorage 并更新缓存 + * @template T + * @param {string} key - 键名 + * @param {T} value - 要存储的值 + * @returns {Promise} 返回写入的值 + */ + set(key, value) { + return new Promise(function (resolve) { + var _value = isString(value) ? value : ''; + try { + _value = JSON.stringify(value); + } catch (e) { + log('[localStorage][set]-error', 2, e); + } + localStorage.setItem(key, _value); + this.cache.set(key, _value); + resolve(value); + }.bind(this)); + } +} + +// 浏览器环境自动选择存储方式 +if (typeof window !== 'undefined') { + /** + * 当前环境可用的存储类(IDBStorage 或 ILocalStorage) + * @type {Function|null} + * @global + */ + window.IStorage = window.indexedDB ? IDBStorage : (window.localStorage ? ILocalStorage : null); + if (typeof module !== 'undefined') { + module.exports = new window.IStorage(); + } +} else if (typeof module !== 'undefined') { + module.exports = null; +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..ddadf89 --- /dev/null +++ b/test.js @@ -0,0 +1,67 @@ +require('./index'); + +let passed = 0; +let failed = 0; + +function assert(desc, condition) { + if (condition) { + console.log(`\x1b[32m ✓ ${desc}\x1b[0m`); + passed++; + } else { + console.log(`\x1b[31m ✗ ${desc}\x1b[0m`); + failed++; + } +} + +function group(name) { + console.log(`\n\x1b[36m─── ${name} ───\x1b[0m`); +} + +// ===== Object.getPro ===== +group('Object.getPro'); +const obj = { a: { b: { c: 1 } }, 'x.y': { z: 2 } }; +assert("getPro('a.b.c') === 1", obj.getPro('a.b.c') === 1); +assert("getPro('a.b.d', 'default') === 'default'", obj.getPro('a.b.d', 'default') === 'default'); +assert("getPro(\"['x.y'].z\") === 2", obj.getPro("['x.y'].z") === 2); +assert("getPro('missing', 42) === 42", obj.getPro('missing', 42) === 42); + +// ===== Object.setPro ===== +group('Object.setPro'); +const obj2 = {}; +obj2.setPro('foo.bar.baz', 'hello'); +assert("setPro 嵌套赋值", obj2.foo.bar.baz === 'hello'); +obj2.setPro("['a.b'].c", 99); +assert("setPro 特殊键名", obj2['a.b'].c === 99); + +// ===== Array Pro 方法 ===== +const arr = [ + { user: { name: 'Alice' } }, + { user: { name: 'Bob' } }, + null, + { user: { name: 'Charlie' } }, +]; + +group('Array.findPro'); +assert("回调 findPro(t=>t>1)", [1, 2, 3].findPro((t) => t > 1) === 2); +assert("key-value findPro('user.name','Bob')", arr.findPro('user.name', 'Bob').user.name === 'Bob'); +assert("单值 findPro('cc')", ['aa', 'bb', 'cc'].findPro('cc') === 'cc'); + +group('Array.filterPro'); +assert("key-value filterPro", arr.filterPro('user.name', 'Alice').length === 1); +assert("单值 filterPro(2)", [1, 2, 2, 3].filterPro(2).length === 2); + +group('Array.findIndexPro'); +assert("findIndexPro", arr.findIndexPro('user.name', 'Charlie') === 3); + +group('Array.findLastPro'); +assert("findLastPro", arr.findLastPro('user.name', 'Bob').user.name === 'Bob'); + +group('Array.somePro / everyPro'); +assert("somePro", arr.somePro('user.name', 'Alice') === true); +assert("everyPro false", arr.everyPro('user.name', 'Alice') === false); +assert("everyPro true", ['a', 'a'].everyPro('a') === true); + +// 汇总 +console.log(`\n\x1b[33m共 ${passed + failed} 项,${passed} 通过,${failed} 失败\x1b[0m`); + +process.exit(failed > 0 ? 1 : 0); diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..cf1c28a --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,44 @@ +const path = require('path'); + +const configs = { + cjs: { + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'windychen-utils.cjs.js', + libraryTarget: 'commonjs2', + }, + }, + esm: { + experiments: { outputModule: true }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'windychen-utils.esm.js', + libraryTarget: 'module', + }, + }, + umd: { + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'windychen-utils.js', + library: { name: 'WindychenUtils', type: 'umd', export: 'default' }, + }, + }, +}; + +module.exports = (env = {}) => { + const format = env.format; + + if (!format || format === 'all') { + return Object.keys(configs).map((key) => ({ + name: key, + entry: './index.js', + ...configs[key], + })); + } + + if (!configs[format]) { + throw new Error(`不支持的格式: ${format},可选值: cjs, esm, umd`); + } + + return { entry: './index.js', ...configs[format] }; +};