coda-builder 1.0.0 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,7 +66,7 @@ npm i coda-builder --dev-save
66
66
 
67
67
  在你的业务项目根目录下创建 webpack.config.ts:
68
68
 
69
- 1. node服务 配置示例
69
+ node服务 配置示例
70
70
 
71
71
  ```TypeScript
72
72
  import * as path from 'path';
@@ -89,85 +89,52 @@ const webpackConfig: Configuration = resolveWebpackConfig(config);
89
89
  export default webpackConfig;
90
90
  ```
91
91
 
92
- 2. node命令行工具 配置示例
92
+ chrome插件 配置示例
93
93
 
94
94
  ```TypeScript
95
95
  import * as path from 'path';
96
- import * as fs from 'fs';
97
96
  import type {Configuration} from 'webpack';
98
97
  import {resolveWebpackConfig, CodaUserConfig} from 'coda-builder';
99
98
 
100
- /**
101
- * 递归扫描 src 目录,自动获取所有 index.ts 作为入口
102
- */
103
- function getEntries(srcDir: string) {
104
- let entries: Record<string, string> = {};
105
-
106
- function scan(dir: string) {
107
- const files = fs.readdirSync(dir, {withFileTypes: true});
108
- files.forEach(file => {
109
- const fullPath = path.join(dir, file.name);
110
- if (file.isDirectory()) {
111
- if (file.name !== 'tmpl' && file.name !== 'templates') {
112
- scan(fullPath);
113
- }
114
- } else if (file.name === 'index.ts' || file.name === 'index.js') {
115
- const relativePath = path.relative(srcDir, fullPath);
116
- const entryKey = relativePath.replace(/\\/g, '/').replace(/\.tsx?$/, '');
117
- entries[entryKey] = fullPath;
118
- }
119
- });
120
- }
121
-
122
- scan(srcDir);
123
- return entries;
124
- }
125
-
126
- const srcPath = path.resolve(__dirname, 'src');
127
-
128
99
  const config: CodaUserConfig = {
129
- techRoute: 'typescript',
130
- platformTarget: 'nodejs-cli',
131
- entry: getEntries(srcPath),
132
- mode: 'development',
100
+ platformTarget: 'chrome-ext',
101
+ techRoute: 'web',
102
+ entry: {
103
+ background: './src/background.ts',
104
+ sidepanel: './src/sidepanel.ts',
105
+ },
106
+ mode: 'production',
107
+ devtool: false, //一定要关闭
108
+ optimization: {
109
+ runtimeChunk: false, //一定要关闭
110
+ splitChunks: false, //一定要关闭
111
+ },
133
112
  output: {
134
113
  path: path.resolve(__dirname, 'dist'),
135
114
  },
136
- maxChunks: 1,
137
115
  alias: {
138
- '@': path.resolve(__dirname, 'src'),
139
- },
140
- extensionAlias: {
141
- '.js': ['.ts', '.js'],
142
- '.ts': ['.ts', '.js'],
116
+ 'chat-shared-ui': path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources'),
143
117
  },
118
+ extensions: ['.ts'],
144
119
  copyRules: [
145
- // 复制根目录基础文件
146
- {
147
- type: 'single',
148
- from: path.resolve(__dirname, 'package.json'),
149
- to: 'package.json',
150
- },
151
120
  {
152
121
  type: 'single',
153
- from: path.resolve(__dirname, 'README.md'),
154
- to: 'README.md',
155
- },
156
- // 复制目录
157
- {
158
- type: 'directory',
159
- from: path.resolve(__dirname, 'src', 'config'),
160
- to: 'config',
122
+ from: path.resolve(__dirname, 'manifest.json'),
123
+ to: 'manifest.json',
161
124
  },
162
125
  {
163
- type: 'directory',
164
- from: path.resolve(__dirname, 'src', 'service'),
165
- to: 'service',
126
+ type: 'template',
127
+ from: path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources/chat.html'),
128
+ to: 'sidepanel.html',
129
+ data: {
130
+ '{{styleUri}}': 'main.css',
131
+ '{{scriptUri}}': 'sidepanel.js',
132
+ },
166
133
  },
167
134
  {
168
- type: 'directory',
169
- from: path.resolve(__dirname, 'templates'),
170
- to: 'templates',
135
+ type: 'single',
136
+ from: path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources/main.css'),
137
+ to: 'main.css',
171
138
  },
172
139
  ],
173
140
  };
@@ -177,7 +144,7 @@ const webpackConfig: Configuration = resolveWebpackConfig(config);
177
144
  export default webpackConfig;
178
145
  ```
179
146
 
180
- 3. chrome扩展程序 配置示例
147
+ vscode插件 配置示例
181
148
 
182
149
  ```TypeScript
183
150
  import * as path from 'path';
@@ -185,91 +152,125 @@ import type {Configuration} from 'webpack';
185
152
  import {resolveWebpackConfig, CodaUserConfig} from 'coda-builder';
186
153
 
187
154
  const config: CodaUserConfig = {
188
- platformTarget: 'chrome-ext',
189
- techRoute: 'web',
190
- entry: {
191
- background: './src/background.ts',
192
- sidepanel: './src/sidepanel.ts',
193
- },
155
+ techRoute: 'typescript',
156
+ platformTarget: 'vscode-ext',
157
+ entry: './src/extension.ts',
194
158
  mode: 'production',
195
159
  output: {
196
160
  path: path.resolve(__dirname, 'dist'),
161
+ filename: 'extension.js',//vscode专属脚本名称
162
+ libraryTarget: 'commonjs',//一定要设置成commonjs
197
163
  },
198
164
  alias: {
199
- 'chat-shared-ui': path.resolve(__dirname, '../../coda-ui/resources'),
165
+ 'chat-shared-ui': path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources'),
200
166
  },
201
167
  copyRules: [
202
168
  {
203
169
  type: 'single',
204
- from: path.resolve(__dirname, 'manifest.json'),
205
- to: 'manifest.json',
170
+ from: path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources/chat.html'),
171
+ to: 'main.html',
206
172
  },
207
173
  {
208
- type: 'template',
209
- from: path.resolve(__dirname, '../../coda-ui/resources/chat.html'),
210
- to: 'sidepanel.html',
211
- data: {
212
- '{{styleUri}}': 'main.css',
213
- '{{scriptUri}}': 'sidepanel.js',
214
- },
174
+ type: 'single',
175
+ from: path.resolve(__dirname, '../../coda-ui/chat-shared-ui/resources/main.css'),
176
+ to: 'main.css',
215
177
  },
216
178
  {
217
179
  type: 'single',
218
- from: path.resolve(__dirname, '../../coda-ui/resources/main.css'),
219
- to: 'main.css',
180
+ from: path.resolve(__dirname, 'resources', 'main.js'),
181
+ to: 'main.js',
182
+ },
183
+ {
184
+ type: 'single',
185
+ from: path.resolve(__dirname, 'resources', 'icon.svg'),
186
+ to: 'icon.svg',
220
187
  },
221
188
  ],
222
189
  };
223
190
 
224
191
  const webpackConfig: Configuration = resolveWebpackConfig(config);
225
192
 
226
- export default webpackConfig
193
+ export default webpackConfig;
194
+
227
195
  ```
228
196
 
229
- 4. vs code扩展程序 配置示例
197
+ 命令行工具 配置示例
230
198
 
231
199
  ```TypeScript
232
200
  import * as path from 'path';
201
+ import * as fs from 'fs';
233
202
  import type {Configuration} from 'webpack';
234
203
  import {resolveWebpackConfig, CodaUserConfig} from 'coda-builder';
235
204
 
205
+ function getEntries(srcDir: string) {
206
+ let entries: Record<string, string> = {};
207
+
208
+ function scan(dir: string) {
209
+ const files = fs.readdirSync(dir, {withFileTypes: true});
210
+ files.forEach(file => {
211
+ const fullPath = path.join(dir, file.name);
212
+ if (file.isDirectory()) {
213
+ if (file.name !== 'tmpl' && file.name !== 'templates') {
214
+ scan(fullPath);
215
+ }
216
+ } else if (file.name === 'index.ts' || file.name === 'index.js') {
217
+ const relativePath = path.relative(srcDir, fullPath);
218
+ const entryKey = relativePath.replace(/\\/g, '/').replace(/\.tsx?$/, '');
219
+ entries[entryKey] = fullPath;
220
+ }
221
+ });
222
+ }
223
+
224
+ scan(srcDir);
225
+ return entries;
226
+ }
227
+
228
+ const srcPath = path.resolve(__dirname, 'src');
229
+
236
230
  const config: CodaUserConfig = {
237
231
  techRoute: 'typescript',
238
- platformTarget: 'vscode-ext',
239
- entry: './src/extension.ts',
240
- mode: 'production',
232
+ platformTarget: 'nodejs-cli',
233
+ entry: getEntries(srcPath),
234
+ mode: process.env.NODE_ENV === 'development' ? 'development' : 'production',
235
+ devtool: process.env.NODE_ENV === 'development' ? 'source-map' : 'cheap-module-source-map',
236
+ gzip: false,
241
237
  output: {
242
238
  path: path.resolve(__dirname, 'dist'),
243
- filename: 'extension.js',
244
- libraryTarget: 'commonjs',
239
+ clean: false,
245
240
  },
241
+ maxChunks: 1,
246
242
  alias: {
247
- 'chat-shared-ui': path.resolve(__dirname, '../../coda-ui/resources'),
243
+ '@': path.resolve(__dirname, 'src'),
248
244
  },
245
+ extensionAlias: {
246
+ '.js': ['.ts', '.js'],
247
+ '.ts': ['.ts', '.js'],
248
+ },//命令行工具一定要配置这个后缀映射关系
249
249
  copyRules: [
250
- // 1. 复制共享的 chat.html
251
250
  {
252
251
  type: 'single',
253
- from: path.resolve(__dirname, '../../coda-ui/resources/chat.html'),
254
- to: 'main.html',
252
+ from: path.resolve(__dirname, 'package.json'),
253
+ to: 'package.json',
255
254
  },
256
- // 2. 复制共享的 main.css
257
255
  {
258
256
  type: 'single',
259
- from: path.resolve(__dirname, '../../coda-ui/resources/main.css'),
260
- to: 'main.css',
257
+ from: path.resolve(__dirname, 'README.md'),
258
+ to: 'README.md',
261
259
  },
262
- // 3. 复制 main.js
263
260
  {
264
- type: 'single',
265
- from: path.resolve(__dirname, 'resources', 'main.js'),
266
- to: 'main.js',
261
+ type: 'directory',
262
+ from: path.resolve(__dirname, 'src', 'config'),
263
+ to: 'config',
267
264
  },
268
- // 4. 复制 icon.svg
269
265
  {
270
- type: 'single',
271
- from: path.resolve(__dirname, 'resources', 'icon.svg'),
272
- to: 'icon.svg',
266
+ type: 'directory',
267
+ from: path.resolve(__dirname, 'src', 'service'),
268
+ to: 'service',
269
+ },
270
+ {
271
+ type: 'directory',
272
+ from: path.resolve(__dirname, 'templates'),
273
+ to: 'templates',
273
274
  },
274
275
  ],
275
276
  };
@@ -0,0 +1,174 @@
1
+ import { Configuration } from 'webpack';
2
+ import { Configuration as Configuration$1 } from 'webpack-dev-server';
3
+ import { Options } from 'html-webpack-plugin';
4
+ import TerserPlugin from 'terser-webpack-plugin';
5
+ import CompressionPlugin from 'compression-webpack-plugin';
6
+
7
+ /**
8
+ * 技术路线类型定义(必选)
9
+ * - typescript: 纯 TS 项目编译
10
+ * - web: HTML/React/Vue 项目(预留扩展)
11
+ */
12
+ type TechRoute = 'typescript' | 'web';
13
+ /**
14
+ * 平台目标类型定义(必选)
15
+ * - nodejs-cli: Node.js 命令行工具(仅支持 TS)
16
+ * - node-server: Node.js 服务端应用(仅支持 TS)
17
+ * - chrome-ext: Chrome 浏览器扩展程序(仅支持 TS)
18
+ * - vscode-ext: VS Code 插件扩展(仅支持 TS)
19
+ * - web: Web 平台应用(预留扩展)
20
+ */
21
+ type PlatformTarget = 'nodejs-cli' | 'node-server' | 'chrome-ext' | 'vscode-ext' | 'web';
22
+ /**
23
+ * Webpack 运行模式(必选)
24
+ * - production: 生产模式
25
+ * - development: 开发模式
26
+ * - analyzer: 性能分析模式
27
+ */
28
+ type BuildMode = 'production' | 'development' | 'analyzer';
29
+ /** 单文件复制规则 */
30
+ type CopySingleRule = {
31
+ type: 'single';
32
+ /** 源文件路径 */
33
+ from: string;
34
+ /** 目标输出路径 */
35
+ to: string;
36
+ };
37
+ /** 目录递归复制规则 */
38
+ type CopyDirectoryRule = {
39
+ type: 'directory';
40
+ /** 源目录路径 */
41
+ from: string;
42
+ /** 目标输出目录路径 */
43
+ to: string;
44
+ /** 需要忽略的文件或文件夹模式数组 */
45
+ ignore?: string[];
46
+ };
47
+ /** 模板文件处理规则(支持占位符替换) */
48
+ type CopyTemplateRule = {
49
+ type: 'template';
50
+ /** 模板文件源路径 */
51
+ from: string;
52
+ /** 目标输出路径 */
53
+ to: string;
54
+ /** 占位符对应的数据字典值键值对 */
55
+ data: Record<string, string | number>;
56
+ };
57
+ /** 静态资源复制规则联合类型 */
58
+ type CopyRuleItem = CopySingleRule | CopyDirectoryRule | CopyTemplateRule;
59
+ /**
60
+ * WorkerOptions 多线程配置选项
61
+ */
62
+ interface WorkerOptions {
63
+ name?: string;
64
+ workers?: number;
65
+ workerParallelJobs?: number;
66
+ workerNodeArgs?: string | string[];
67
+ poolRespawn?: boolean;
68
+ poolTimeout?: number;
69
+ poolParallelJobs?: number;
70
+ }
71
+ /**
72
+ * 用户自定义通用配置接口
73
+ */
74
+ interface CodaUserConfig {
75
+ /**************************自定义属性************************************ */
76
+ /** 1. 适配技术路线 (必选) */
77
+ techRoute: TechRoute;
78
+ /** 2. 多平台构建和开发 (必选) */
79
+ platformTarget: PlatformTarget;
80
+ /** 3. Webpack 运行模式 (必选) */
81
+ mode: BuildMode;
82
+ /**************************webpack自身常用属性**************************** */
83
+ /** 1. 脚本入口 entry (必选,继承 Webpack) */
84
+ entry: Configuration['entry'];
85
+ /** 2. 命令执行上下文 (可选,继承 Webpack)*/
86
+ context?: Configuration['context'];
87
+ /** 3. 构建输出 output (可选,继承 Webpack) */
88
+ output?: Configuration['output'];
89
+ /** 4. 模块匹配与解析规则 module (可选,继承 Webpack module) */
90
+ module?: Configuration['module'];
91
+ /** 5. 模块解析 resolve (可选,继承 Webpack) */
92
+ resolve?: Configuration['resolve'];
93
+ /** 6. 代码优化与分包配置 optimization (可选,继承 Webpack) */
94
+ optimization?: Configuration['optimization'];
95
+ /** 7. 自定义 Webpack 插件列表 plugins (可选,继承 Webpack plugins) */
96
+ plugins?: Configuration['plugins'];
97
+ /** 8. 开发服务器配置 devServer (可选,继承 Webpack devServer) */
98
+ devServer?: Configuration$1;
99
+ /** 9. 缓存配置 (可选,继承 Webpack) */
100
+ cache?: Configuration['cache'];
101
+ /** 10. source map 生成 devtool (可选,继承 Webpack) */
102
+ devtool?: Configuration['devtool'];
103
+ /** 11. 编译目标环境 target (可选,继承 Webpack) */
104
+ target?: Configuration['target'];
105
+ /** 12. 是否开启文件监听 watch (可选,继承 Webpack watch) */
106
+ watch?: Configuration['watch'];
107
+ /** 13. 文件监听选项 watchOptions (可选,继承 Webpack watchOptions) */
108
+ watchOptions?: Configuration['watchOptions'];
109
+ /** 14. 外部依赖处理 externals (可选,继承 Webpack) */
110
+ externals?: Configuration['externals'];
111
+ /** 15. 构建日志输出控制 stats (可选,继承 Webpack) */
112
+ stats?: Configuration['stats'];
113
+ /*****************************webpack属性快捷设置************************************** */
114
+ /** 1. 不需要解析的目录 noParse (可选,自动映射至 Webpack module.noParse) */
115
+ noParse?: Configuration['module'] extends {
116
+ noParse?: infer NP;
117
+ } ? NP : never;
118
+ /** 2. 资源加载器规则(可选,自动映射至 Webpack module.rules) */
119
+ rules?: Configuration['module'] extends {
120
+ rules?: infer NP;
121
+ } ? NP : never;
122
+ /** 1. 模块路径别名 (可选,自动映射至 Webpack resolve.alias) */
123
+ alias?: Record<string, string>;
124
+ /** 2. 模块解析扩展名 extensions (可选,自动映射至 Webpack resolve.extensions) */
125
+ extensions?: string[];
126
+ /** 3. 文件后缀别名映射(可选,自动映射至Webpack resolve.extensionAlias) */
127
+ extensionAlias?: Record<string, string | string[]>;
128
+ /** 4. 模块解析目录 modules (可选,自动映射至 Webpack resolve.modules) */
129
+ modules?: Configuration['resolve'] extends {
130
+ modules?: infer M;
131
+ } ? M : never;
132
+ /** 5. 依赖包主文件字段 mainFields (可选,自动映射至 Webpack resolve.mainFields) */
133
+ mainFields?: Configuration['resolve'] extends {
134
+ mainFields?: infer MF;
135
+ } ? MF : never;
136
+ /** 1. 限制每个入口生成的最大 Chunk 数 (可选) */
137
+ maxChunks?: number;
138
+ /** 2. 代码切片配置 (可选,继承 Webpack optimization.splitChunks) */
139
+ splitChunks?: Configuration['optimization'] extends {
140
+ splitChunks?: infer S;
141
+ } ? S : never;
142
+ /** 3. 是否启用代码压缩 minimization (可选,继承webpack.optimization) */
143
+ minimize?: boolean;
144
+ /** 4. Terser 脚本压缩优化选项 (可选,继承webpack.optimization,基于 terser-webpack-plugin) */
145
+ terserOptions?: TerserPlugin['options'];
146
+ /** 5. 压缩插件启用的 CPU 核心数 (可选,继承webpack.optimization,基于 terser-webpack-plugin) */
147
+ parallel?: number;
148
+ /** 1. 是否开启构建打包测速 (可选,基于 speed-measure-webpack-v5-plugin) */
149
+ speedMeasure?: boolean;
150
+ /** 2. 是否开启多线程编译 thread-loader (可选,基于 thread-loader) */
151
+ thread?: boolean;
152
+ /** 3. thread-loader 的自定义 Worker 选项 (可选,基于 thread-loader) */
153
+ workerOptions?: WorkerOptions;
154
+ /** 1. HTML 模板注入配置 (可选,基于 html-webpack-plugin) */
155
+ html?: Options | boolean;
156
+ /** 2. 静态资源复制规则 (可选) */
157
+ copyRules?: CopyRuleItem[];
158
+ /** 3. Gzip 压缩配置 (可选,基于 compression-webpack-plugin) */
159
+ gzip?: CompressionPlugin['options'] | boolean;
160
+ /*****************************webpack外部通过钩子函数进行高级设置***************************** */
161
+ /** 允许外部修改配置的钩子函数 (可选) */
162
+ configureWebpack?: (config: Configuration, mode: BuildMode) => Configuration | void;
163
+ }
164
+
165
+ /**
166
+ * 解析并转换外部传入的通用配置,生成最终的标准 Webpack 配置对象
167
+ * @param {CodaUserConfig} userConfig 用户传入的通用配置
168
+ * @param {boolean} isLogger 是否显示日志
169
+ * @returns {WebpackConfiguration} 标准的 Webpack 配置对象
170
+ */
171
+ declare function resolveWebpackConfig(userConfig: CodaUserConfig, isLogger?: boolean): Configuration;
172
+
173
+ export { resolveWebpackConfig };
174
+ export type { BuildMode, CodaUserConfig, CopyDirectoryRule, CopyRuleItem, CopySingleRule, CopyTemplateRule, PlatformTarget, TechRoute, WorkerOptions };
@@ -0,0 +1,174 @@
1
+ import { Configuration } from 'webpack';
2
+ import { Configuration as Configuration$1 } from 'webpack-dev-server';
3
+ import { Options } from 'html-webpack-plugin';
4
+ import TerserPlugin from 'terser-webpack-plugin';
5
+ import CompressionPlugin from 'compression-webpack-plugin';
6
+
7
+ /**
8
+ * 技术路线类型定义(必选)
9
+ * - typescript: 纯 TS 项目编译
10
+ * - web: HTML/React/Vue 项目(预留扩展)
11
+ */
12
+ type TechRoute = 'typescript' | 'web';
13
+ /**
14
+ * 平台目标类型定义(必选)
15
+ * - nodejs-cli: Node.js 命令行工具(仅支持 TS)
16
+ * - node-server: Node.js 服务端应用(仅支持 TS)
17
+ * - chrome-ext: Chrome 浏览器扩展程序(仅支持 TS)
18
+ * - vscode-ext: VS Code 插件扩展(仅支持 TS)
19
+ * - web: Web 平台应用(预留扩展)
20
+ */
21
+ type PlatformTarget = 'nodejs-cli' | 'node-server' | 'chrome-ext' | 'vscode-ext' | 'web';
22
+ /**
23
+ * Webpack 运行模式(必选)
24
+ * - production: 生产模式
25
+ * - development: 开发模式
26
+ * - analyzer: 性能分析模式
27
+ */
28
+ type BuildMode = 'production' | 'development' | 'analyzer';
29
+ /** 单文件复制规则 */
30
+ type CopySingleRule = {
31
+ type: 'single';
32
+ /** 源文件路径 */
33
+ from: string;
34
+ /** 目标输出路径 */
35
+ to: string;
36
+ };
37
+ /** 目录递归复制规则 */
38
+ type CopyDirectoryRule = {
39
+ type: 'directory';
40
+ /** 源目录路径 */
41
+ from: string;
42
+ /** 目标输出目录路径 */
43
+ to: string;
44
+ /** 需要忽略的文件或文件夹模式数组 */
45
+ ignore?: string[];
46
+ };
47
+ /** 模板文件处理规则(支持占位符替换) */
48
+ type CopyTemplateRule = {
49
+ type: 'template';
50
+ /** 模板文件源路径 */
51
+ from: string;
52
+ /** 目标输出路径 */
53
+ to: string;
54
+ /** 占位符对应的数据字典值键值对 */
55
+ data: Record<string, string | number>;
56
+ };
57
+ /** 静态资源复制规则联合类型 */
58
+ type CopyRuleItem = CopySingleRule | CopyDirectoryRule | CopyTemplateRule;
59
+ /**
60
+ * WorkerOptions 多线程配置选项
61
+ */
62
+ interface WorkerOptions {
63
+ name?: string;
64
+ workers?: number;
65
+ workerParallelJobs?: number;
66
+ workerNodeArgs?: string | string[];
67
+ poolRespawn?: boolean;
68
+ poolTimeout?: number;
69
+ poolParallelJobs?: number;
70
+ }
71
+ /**
72
+ * 用户自定义通用配置接口
73
+ */
74
+ interface CodaUserConfig {
75
+ /**************************自定义属性************************************ */
76
+ /** 1. 适配技术路线 (必选) */
77
+ techRoute: TechRoute;
78
+ /** 2. 多平台构建和开发 (必选) */
79
+ platformTarget: PlatformTarget;
80
+ /** 3. Webpack 运行模式 (必选) */
81
+ mode: BuildMode;
82
+ /**************************webpack自身常用属性**************************** */
83
+ /** 1. 脚本入口 entry (必选,继承 Webpack) */
84
+ entry: Configuration['entry'];
85
+ /** 2. 命令执行上下文 (可选,继承 Webpack)*/
86
+ context?: Configuration['context'];
87
+ /** 3. 构建输出 output (可选,继承 Webpack) */
88
+ output?: Configuration['output'];
89
+ /** 4. 模块匹配与解析规则 module (可选,继承 Webpack module) */
90
+ module?: Configuration['module'];
91
+ /** 5. 模块解析 resolve (可选,继承 Webpack) */
92
+ resolve?: Configuration['resolve'];
93
+ /** 6. 代码优化与分包配置 optimization (可选,继承 Webpack) */
94
+ optimization?: Configuration['optimization'];
95
+ /** 7. 自定义 Webpack 插件列表 plugins (可选,继承 Webpack plugins) */
96
+ plugins?: Configuration['plugins'];
97
+ /** 8. 开发服务器配置 devServer (可选,继承 Webpack devServer) */
98
+ devServer?: Configuration$1;
99
+ /** 9. 缓存配置 (可选,继承 Webpack) */
100
+ cache?: Configuration['cache'];
101
+ /** 10. source map 生成 devtool (可选,继承 Webpack) */
102
+ devtool?: Configuration['devtool'];
103
+ /** 11. 编译目标环境 target (可选,继承 Webpack) */
104
+ target?: Configuration['target'];
105
+ /** 12. 是否开启文件监听 watch (可选,继承 Webpack watch) */
106
+ watch?: Configuration['watch'];
107
+ /** 13. 文件监听选项 watchOptions (可选,继承 Webpack watchOptions) */
108
+ watchOptions?: Configuration['watchOptions'];
109
+ /** 14. 外部依赖处理 externals (可选,继承 Webpack) */
110
+ externals?: Configuration['externals'];
111
+ /** 15. 构建日志输出控制 stats (可选,继承 Webpack) */
112
+ stats?: Configuration['stats'];
113
+ /*****************************webpack属性快捷设置************************************** */
114
+ /** 1. 不需要解析的目录 noParse (可选,自动映射至 Webpack module.noParse) */
115
+ noParse?: Configuration['module'] extends {
116
+ noParse?: infer NP;
117
+ } ? NP : never;
118
+ /** 2. 资源加载器规则(可选,自动映射至 Webpack module.rules) */
119
+ rules?: Configuration['module'] extends {
120
+ rules?: infer NP;
121
+ } ? NP : never;
122
+ /** 1. 模块路径别名 (可选,自动映射至 Webpack resolve.alias) */
123
+ alias?: Record<string, string>;
124
+ /** 2. 模块解析扩展名 extensions (可选,自动映射至 Webpack resolve.extensions) */
125
+ extensions?: string[];
126
+ /** 3. 文件后缀别名映射(可选,自动映射至Webpack resolve.extensionAlias) */
127
+ extensionAlias?: Record<string, string | string[]>;
128
+ /** 4. 模块解析目录 modules (可选,自动映射至 Webpack resolve.modules) */
129
+ modules?: Configuration['resolve'] extends {
130
+ modules?: infer M;
131
+ } ? M : never;
132
+ /** 5. 依赖包主文件字段 mainFields (可选,自动映射至 Webpack resolve.mainFields) */
133
+ mainFields?: Configuration['resolve'] extends {
134
+ mainFields?: infer MF;
135
+ } ? MF : never;
136
+ /** 1. 限制每个入口生成的最大 Chunk 数 (可选) */
137
+ maxChunks?: number;
138
+ /** 2. 代码切片配置 (可选,继承 Webpack optimization.splitChunks) */
139
+ splitChunks?: Configuration['optimization'] extends {
140
+ splitChunks?: infer S;
141
+ } ? S : never;
142
+ /** 3. 是否启用代码压缩 minimization (可选,继承webpack.optimization) */
143
+ minimize?: boolean;
144
+ /** 4. Terser 脚本压缩优化选项 (可选,继承webpack.optimization,基于 terser-webpack-plugin) */
145
+ terserOptions?: TerserPlugin['options'];
146
+ /** 5. 压缩插件启用的 CPU 核心数 (可选,继承webpack.optimization,基于 terser-webpack-plugin) */
147
+ parallel?: number;
148
+ /** 1. 是否开启构建打包测速 (可选,基于 speed-measure-webpack-v5-plugin) */
149
+ speedMeasure?: boolean;
150
+ /** 2. 是否开启多线程编译 thread-loader (可选,基于 thread-loader) */
151
+ thread?: boolean;
152
+ /** 3. thread-loader 的自定义 Worker 选项 (可选,基于 thread-loader) */
153
+ workerOptions?: WorkerOptions;
154
+ /** 1. HTML 模板注入配置 (可选,基于 html-webpack-plugin) */
155
+ html?: Options | boolean;
156
+ /** 2. 静态资源复制规则 (可选) */
157
+ copyRules?: CopyRuleItem[];
158
+ /** 3. Gzip 压缩配置 (可选,基于 compression-webpack-plugin) */
159
+ gzip?: CompressionPlugin['options'] | boolean;
160
+ /*****************************webpack外部通过钩子函数进行高级设置***************************** */
161
+ /** 允许外部修改配置的钩子函数 (可选) */
162
+ configureWebpack?: (config: Configuration, mode: BuildMode) => Configuration | void;
163
+ }
164
+
165
+ /**
166
+ * 解析并转换外部传入的通用配置,生成最终的标准 Webpack 配置对象
167
+ * @param {CodaUserConfig} userConfig 用户传入的通用配置
168
+ * @param {boolean} isLogger 是否显示日志
169
+ * @returns {WebpackConfiguration} 标准的 Webpack 配置对象
170
+ */
171
+ declare function resolveWebpackConfig(userConfig: CodaUserConfig, isLogger?: boolean): Configuration;
172
+
173
+ export { resolveWebpackConfig };
174
+ export type { BuildMode, CodaUserConfig, CopyDirectoryRule, CopyRuleItem, CopySingleRule, CopyTemplateRule, PlatformTarget, TechRoute, WorkerOptions };
package/build/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var j=Object.create;var b=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var D=(t,e)=>{for(var i in e)b(t,i,{get:e[i],enumerable:!0})},z=(t,e,i,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of N(e))!F.call(t,s)&&s!==i&&b(t,s,{get:()=>e[s],enumerable:!(o=q(e,s))||o.enumerable});return t};var u=(t,e,i)=>(i=t!=null?j(T(t)):{},z(e||!t||!t.__esModule?b(i,"default",{value:t,enumerable:!0}):i,t)),U=t=>z(b({},"__esModule",{value:!0}),t);var G={};D(G,{resolveWebpackConfig:()=>M});module.exports=U(G);var W=u(require("webpack-node-externals")),E=require("webpack-bundle-analyzer");var x=u(require("path")),S=u(require("os")),O=u(require("webpackbar")),f={js:/\.(ts|js)$/,css:/\.css$/,image:/\.(png|jpg|jpeg|gif|svg)$/,font:/\.(woff|woff2|eot|ttf|otf)$/,media:/\.(mp4|webm|ogg|mp3|wav)$/},P=(t={},e="development")=>{let i=S.default.cpus().length||4;return{name:t.name||"ts-thread",workers:t.workers||(e==="development"?2:Math.max(1,Math.floor((i-2)/2))),workerParallelJobs:t.workerParallelJobs||(e==="development"?40:20),workerNodeArgs:Array.isArray(t.workerNodeArgs)?t.workerNodeArgs:[t.workerNodeArgs||(e==="development"?"--max-old-space-size=512":"--max-old-space-size=256")],poolRespawn:t.poolRespawn??e!=="development",poolTimeout:t.poolTimeout||500,poolParallelJobs:t.poolParallelJobs||(e==="development"?200:100)}},A=(t=!1,e)=>{let i=[];if(e?.thread){let o=P(e.workerOptions,e.mode);i.push({loader:"thread-loader",options:o})}return i.push({loader:"ts-loader",options:{compilerOptions:{declaration:!1,declarationMap:!1}}}),{mode:"none",output:{path:x.default.resolve(__dirname,"dist"),clean:!0},resolve:{extensions:[".ts",".js"],modules:["node_modules"]},module:{rules:[{test:f.js,use:i,exclude:/node_modules/},{test:f.css,use:[t?{loader:require("mini-css-extract-plugin").loader}:"style-loader",{loader:"css-loader",options:{sourceMap:!0,importLoaders:1}},"postcss-loader"]},{test:f.image,type:"asset/resource",generator:{filename:"assets/img/[hash][ext]"}},{test:f.font,type:"asset/resource",generator:{filename:"assets/font/[name][ext]"}},{test:f.media,type:"asset/resource",generator:{filename:"assets/media/[name][ext]"}}]},plugins:[new O.default({name:"coda-builder",color:"#0052cc"})],devServer:{historyApiFallback:!0,port:8080,compress:!1,open:!1,hot:!0,static:{directory:x.default.join(process.cwd(),"dist")}},stats:"minimal",devtool:e?.mode==="development"?"source-map":"cheap-module-source-map"}};var k=class{config;constructor(e){this.config={...e}}setMode(e){return this.config.mode=e,this}setEntry(e){return this.config.entry=e,this}setContext(e){return e!==void 0&&(this.config.context=e),this}setOutput(e){return e?(this.config.output={...this.config.output,...e},this):this}setDevtool(e){return e!==void 0&&(this.config.devtool=e),this}setTarget(e){return e!==void 0&&(this.config.target=e),this}setCache(e){return e!==void 0&&(this.config.cache=e),this}setResolve(e,i){let o=i?.modules,s=i?.mainFields,n=i?.alias,a=i?.extensions,r=i?.extensionAlias;return this.config.resolve={...this.config.resolve,...o?{modules:o}:{},...s?{mainFields:s}:{},...n?{alias:n}:{},...a?{extensions:a}:{},...r?{extensionAlias:r}:{},...e},this}setModule(e,i){let o=this.config.module?.rules||[],s=i?.rules||[],n=i?.noParse;return this.config.module={...this.config.module||{},...n?{noParse:n}:{},rules:[...o,...s],...e},this}setOptimization(e,i,o,s,n,a,r){let l=i;l===void 0&&(s==="web"||s==="chrome-ext")&&(l={chunks:"all",minSize:2e4,maxSize:2e5,minChunks:1,maxAsyncRequests:6,maxInitialRequests:6,cacheGroups:{libs:{name:"chunk-libs",test:/[\\/]node_modules[\\/]/,chunks:"initial",priority:20,reuseExistingChunk:!0},common:{name:"chunk-common",minChunks:2,priority:2,reuseExistingChunk:!0}}});let m=a!==void 0?a:n==="production"||n==="analyzer",c=e?.minimizer||this.config.optimization?.minimizer;if(m&&!c)try{let g=require("terser-webpack-plugin"),v=require("css-minimizer-webpack-plugin"),R=o!==void 0?o:{parse:{ecma:8},compress:{ecma:5,comparisons:!1,inline:2,warnings:!1},mangle:!0,module:!1,output:{ecma:5,comments:!1},toplevel:!1,ie8:!1,safari10:!1},C=r||2;c=[new g({parallel:C,terserOptions:R}),new v({parallel:C})]}catch{}let d=e?.runtimeChunk||this.config.optimization?.runtimeChunk;return l!==void 0&&!d&&(d={name:"manifest"}),this.config.optimization={...this.config.optimization||{},minimize:m,...l!==void 0?{splitChunks:l}:{},...c!==void 0?{minimizer:c}:{},...d!==void 0?{runtimeChunk:d}:{},...e},this}setStats(e){return e!==void 0&&(this.config.stats=e),this}setDevServer(e){if(!e)return this;let i=this.config.devServer||{};return this.config.devServer={...i,...e,...e.static?{static:typeof e.static=="object"&&typeof i.static=="object"?{...i.static,...e.static}:e.static}:{}},this}setWatch(e){return e!==void 0&&(this.config.watch=e),this}setWatchOptions(e){return e?(this.config.watchOptions={...this.config.watchOptions,...e},this):this}setExternals(e){return e!==void 0&&(this.config.externals=e),this}addPlugin(e){return this.config.plugins=this.config.plugins||[],this.config.plugins.push(e),this}addPlugins(e){return!e||!Array.isArray(e)?this:(e.forEach(i=>{i&&this.addPlugin(i)}),this)}setMaxChunks(e){if(e===void 0)return this;let i=require("webpack");return this.addPlugin(new i.optimize.LimitChunkCountPlugin({maxChunks:e})),this}getConfig(){return this.config}setConfig(e){return this.config={...this.config,...e},this}};var p=u(require("fs")),w=u(require("path")),y=class{rules;constructor(e=[]){this.rules=e}apply(e){e.hooks.thisCompilation.tap("CodaCopyWebpackPlugin",i=>{i.hooks.processAssets.tap({name:"CodaCopyWebpackPlugin",stage:e.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS},()=>{this.rules.forEach(o=>{p.default.existsSync(o.from)&&(o.type==="single"?this.processSingleFile(i,o.from,o.to):o.type==="directory"?this.processDirectory(i,o.from,o.to,o.ignore||[]):o.type==="template"&&this.processTemplate(i,o.from,o.to,o.data))})})})}processSingleFile(e,i,o){let s=p.default.readFileSync(i);e.emitAsset(o,new e.compiler.webpack.sources.RawSource(s))}processDirectory(e,i,o,s){p.default.readdirSync(i,{recursive:!0}).forEach(a=>{let r=w.default.join(i,a);if(p.default.statSync(r).isDirectory())return;let l=w.default.relative(i,r);if(s.some(c=>l.includes(c)))return;let h=w.default.join(o,l).replace(/\\/g,"/"),m=p.default.readFileSync(r);e.emitAsset(h,new e.compiler.webpack.sources.RawSource(m))})}processTemplate(e,i,o,s){let n=p.default.readFileSync(i,"utf-8");Object.keys(s).forEach(a=>{let r=a.replace(/{{\s*|\s*}}/g,""),l=new RegExp(`{{\\s*${r}\\s*}}`,"g");n=n.replace(l,String(s[a]))}),e.emitAsset(o,new e.compiler.webpack.sources.RawSource(Buffer.from(n)))}};function $(t){if(!t.techRoute)throw new Error("[coda-builder] Missing required config: techRoute");if(!t.platformTarget)throw new Error("[coda-builder] Missing required config: platformTarget");if(!t.mode)throw new Error("[coda-builder] Missing required config: mode");if(!t.entry)throw new Error("[coda-builder] Missing required config: entry")}function _(t){let e=t.mode==="production"||t.mode==="analyzer";return A(e,t)}function B(t,e){let{platformTarget:i}=t;["nodejs-cli","node-server","vscode-ext"].includes(i)?(e.setTarget("node"),i==="vscode-ext"?e.setExternals([(0,W.default)(),{vscode:"commonjs vscode"}]):e.setExternals([(0,W.default)()])):i==="chrome-ext"&&e.setTarget("web")}function I(t,e){let i=t.mode==="analyzer"?"production":t.mode;e.setMode(i).setEntry(t.entry).setContext(t.context).setOutput(t.output).setDevtool(t.devtool).setCache(t.cache).setMaxChunks(t.maxChunks).setStats(t.stats).setDevServer(t.devServer).setWatch(t.watch).setWatchOptions(t.watchOptions),e.setOptimization(t.optimization,t.splitChunks,t.terserOptions,t.platformTarget,i,t.minimize,t.parallel),e.setResolve(t.resolve,{alias:t.alias,extensions:t.extensions,extensionAlias:t.extensionAlias,modules:t.modules,mainFields:t.mainFields}),e.setModule(t.module,{noParse:t.noParse,rules:t.rules}),t.target&&e.setTarget(t.target),t.externals&&e.setExternals(t.externals)}function J(t,e){let i=t.mode==="production"||t.mode==="analyzer";if(t.copyRules&&t.copyRules.length>0&&e.addPlugin(new y(t.copyRules)),t.html)try{let o=require("html-webpack-plugin"),s=typeof t.html=="object"?t.html:{};e.addPlugin(new o(s))}catch{throw new Error('[coda-builder] html-webpack-plugin is required when using "html" config. Please install it.')}if(i)try{let o=require("mini-css-extract-plugin");e.addPlugin(new o({filename:"css/[name].[contenthash:8].css",chunkFilename:"css/[name].[contenthash:8].chunk.css"}))}catch{throw new Error("[coda-builder] mini-css-extract-plugin is required in production mode. Please install it.")}if(t.gzip!==!1&&(t.gzip||i))try{let o=require("compression-webpack-plugin"),s={filename:"[path][base].gz",algorithm:"gzip",test:/\.(js|css|png|jpg|jpeg|svg)(\?.*)?$/i,threshold:8192,minRatio:.8,deleteOriginalAssets:!1,exclude:[/node_modules/]},n=typeof t.gzip=="object"?{...s,...t.gzip}:s;e.addPlugin(new o(n))}catch{throw new Error('[coda-builder] compression-webpack-plugin is required when using "gzip" config. Please install it.')}if(t.plugins&&t.plugins.length>0&&e.addPlugins(t.plugins),t.mode==="analyzer"&&e.addPlugin(new E.BundleAnalyzerPlugin({analyzerMode:"server"})),t.platformTarget==="nodejs-cli")try{let o=require("fs"),s=require("path"),n=require("webpack"),a=s.resolve(process.cwd(),"package.json");if(o.existsSync(a)){let r=JSON.parse(o.readFileSync(a,"utf-8"));if(r.bin){let l=[];typeof r.bin=="string"?l=[r.bin]:typeof r.bin=="object"&&r.bin!==null&&(l=Object.values(r.bin)),l.forEach(h=>{let c=h.replace(/^\.\//,"").split("/"),d=c.pop()||"index.js",g=c.pop()||"bin",v=new RegExp(`${g}[\\\\/]${d}$`);e.addPlugin(new n.BannerPlugin({banner:"#!/usr/bin/env node",raw:!0,test:v}))})}}}catch{}}function L(t,e){if(t.configureWebpack&&typeof t.configureWebpack=="function"){let i=t.configureWebpack(e,t.mode);if(i)return i}return e}function M(t,e){if($(t),t.thread&&t.mode==="development")try{let n=require("thread-loader"),a=P(t.workerOptions||{name:"ts-thread",workers:2,workerParallelJobs:40,workerNodeArgs:"--max-old-space-size=512",poolRespawn:!1,poolParallelJobs:200},t.mode);n.warmup({workerBabelArgs:a},["ts-loader"])}catch{}let i=_(t),o=new k(i);o.setConfig({context:process.cwd()}),B(t,o),I(t,o),J(t,o);let s=o.getConfig();if(s=L(t,s),t.speedMeasure&&(t.mode==="development"||t.mode==="analyzer"))try{let n=require("speed-measure-webpack-v5-plugin");s=new n().wrap(s)}catch{throw new Error('[coda-builder] speed-measure-webpack-v5-plugin is required when using "speedMeasure" config. Please install it.')}return e&&(console.log("webpack\u914D\u7F6E:"),console.dir(i,{depth:null})),s}0&&(module.exports={resolveWebpackConfig});
@@ -0,0 +1 @@
1
+ var c=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,i)=>(typeof require<"u"?require:e)[i]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});import C from"webpack-node-externals";import{BundleAnalyzerPlugin as A}from"webpack-bundle-analyzer";import P from"path";import S from"os";import O from"webpackbar";var f={js:/\.(ts|js)$/,css:/\.css$/,image:/\.(png|jpg|jpeg|gif|svg)$/,font:/\.(woff|woff2|eot|ttf|otf)$/,media:/\.(mp4|webm|ogg|mp3|wav)$/},y=(t={},e="development")=>{let i=S.cpus().length||4;return{name:t.name||"ts-thread",workers:t.workers||(e==="development"?2:Math.max(1,Math.floor((i-2)/2))),workerParallelJobs:t.workerParallelJobs||(e==="development"?40:20),workerNodeArgs:Array.isArray(t.workerNodeArgs)?t.workerNodeArgs:[t.workerNodeArgs||(e==="development"?"--max-old-space-size=512":"--max-old-space-size=256")],poolRespawn:t.poolRespawn??e!=="development",poolTimeout:t.poolTimeout||500,poolParallelJobs:t.poolParallelJobs||(e==="development"?200:100)}},W=(t=!1,e)=>{let i=[];if(e?.thread){let o=y(e.workerOptions,e.mode);i.push({loader:"thread-loader",options:o})}return i.push({loader:"ts-loader",options:{compilerOptions:{declaration:!1,declarationMap:!1}}}),{mode:"none",output:{path:P.resolve(__dirname,"dist"),clean:!0},resolve:{extensions:[".ts",".js"],modules:["node_modules"]},module:{rules:[{test:f.js,use:i,exclude:/node_modules/},{test:f.css,use:[t?{loader:c("mini-css-extract-plugin").loader}:"style-loader",{loader:"css-loader",options:{sourceMap:!0,importLoaders:1}},"postcss-loader"]},{test:f.image,type:"asset/resource",generator:{filename:"assets/img/[hash][ext]"}},{test:f.font,type:"asset/resource",generator:{filename:"assets/font/[name][ext]"}},{test:f.media,type:"asset/resource",generator:{filename:"assets/media/[name][ext]"}}]},plugins:[new O({name:"coda-builder",color:"#0052cc"})],devServer:{historyApiFallback:!0,port:8080,compress:!1,open:!1,hot:!0,static:{directory:P.join(process.cwd(),"dist")}},stats:"minimal",devtool:e?.mode==="development"?"source-map":"cheap-module-source-map"}};var b=class{config;constructor(e){this.config={...e}}setMode(e){return this.config.mode=e,this}setEntry(e){return this.config.entry=e,this}setContext(e){return e!==void 0&&(this.config.context=e),this}setOutput(e){return e?(this.config.output={...this.config.output,...e},this):this}setDevtool(e){return e!==void 0&&(this.config.devtool=e),this}setTarget(e){return e!==void 0&&(this.config.target=e),this}setCache(e){return e!==void 0&&(this.config.cache=e),this}setResolve(e,i){let o=i?.modules,s=i?.mainFields,n=i?.alias,a=i?.extensions,r=i?.extensionAlias;return this.config.resolve={...this.config.resolve,...o?{modules:o}:{},...s?{mainFields:s}:{},...n?{alias:n}:{},...a?{extensions:a}:{},...r?{extensionAlias:r}:{},...e},this}setModule(e,i){let o=this.config.module?.rules||[],s=i?.rules||[],n=i?.noParse;return this.config.module={...this.config.module||{},...n?{noParse:n}:{},rules:[...o,...s],...e},this}setOptimization(e,i,o,s,n,a,r){let l=i;l===void 0&&(s==="web"||s==="chrome-ext")&&(l={chunks:"all",minSize:2e4,maxSize:2e5,minChunks:1,maxAsyncRequests:6,maxInitialRequests:6,cacheGroups:{libs:{name:"chunk-libs",test:/[\\/]node_modules[\\/]/,chunks:"initial",priority:20,reuseExistingChunk:!0},common:{name:"chunk-common",minChunks:2,priority:2,reuseExistingChunk:!0}}});let m=a!==void 0?a:n==="production"||n==="analyzer",p=e?.minimizer||this.config.optimization?.minimizer;if(m&&!p)try{let g=c("terser-webpack-plugin"),w=c("css-minimizer-webpack-plugin"),z=o!==void 0?o:{parse:{ecma:8},compress:{ecma:5,comparisons:!1,inline:2,warnings:!1},mangle:!0,module:!1,output:{ecma:5,comments:!1},toplevel:!1,ie8:!1,safari10:!1},x=r||2;p=[new g({parallel:x,terserOptions:z}),new w({parallel:x})]}catch{}let d=e?.runtimeChunk||this.config.optimization?.runtimeChunk;return l!==void 0&&!d&&(d={name:"manifest"}),this.config.optimization={...this.config.optimization||{},minimize:m,...l!==void 0?{splitChunks:l}:{},...p!==void 0?{minimizer:p}:{},...d!==void 0?{runtimeChunk:d}:{},...e},this}setStats(e){return e!==void 0&&(this.config.stats=e),this}setDevServer(e){if(!e)return this;let i=this.config.devServer||{};return this.config.devServer={...i,...e,...e.static?{static:typeof e.static=="object"&&typeof i.static=="object"?{...i.static,...e.static}:e.static}:{}},this}setWatch(e){return e!==void 0&&(this.config.watch=e),this}setWatchOptions(e){return e?(this.config.watchOptions={...this.config.watchOptions,...e},this):this}setExternals(e){return e!==void 0&&(this.config.externals=e),this}addPlugin(e){return this.config.plugins=this.config.plugins||[],this.config.plugins.push(e),this}addPlugins(e){return!e||!Array.isArray(e)?this:(e.forEach(i=>{i&&this.addPlugin(i)}),this)}setMaxChunks(e){if(e===void 0)return this;let i=c("webpack");return this.addPlugin(new i.optimize.LimitChunkCountPlugin({maxChunks:e})),this}getConfig(){return this.config}setConfig(e){return this.config={...this.config,...e},this}};import u from"fs";import v from"path";var k=class{rules;constructor(e=[]){this.rules=e}apply(e){e.hooks.thisCompilation.tap("CodaCopyWebpackPlugin",i=>{i.hooks.processAssets.tap({name:"CodaCopyWebpackPlugin",stage:e.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS},()=>{this.rules.forEach(o=>{u.existsSync(o.from)&&(o.type==="single"?this.processSingleFile(i,o.from,o.to):o.type==="directory"?this.processDirectory(i,o.from,o.to,o.ignore||[]):o.type==="template"&&this.processTemplate(i,o.from,o.to,o.data))})})})}processSingleFile(e,i,o){let s=u.readFileSync(i);e.emitAsset(o,new e.compiler.webpack.sources.RawSource(s))}processDirectory(e,i,o,s){u.readdirSync(i,{recursive:!0}).forEach(a=>{let r=v.join(i,a);if(u.statSync(r).isDirectory())return;let l=v.relative(i,r);if(s.some(p=>l.includes(p)))return;let h=v.join(o,l).replace(/\\/g,"/"),m=u.readFileSync(r);e.emitAsset(h,new e.compiler.webpack.sources.RawSource(m))})}processTemplate(e,i,o,s){let n=u.readFileSync(i,"utf-8");Object.keys(s).forEach(a=>{let r=a.replace(/{{\s*|\s*}}/g,""),l=new RegExp(`{{\\s*${r}\\s*}}`,"g");n=n.replace(l,String(s[a]))}),e.emitAsset(o,new e.compiler.webpack.sources.RawSource(Buffer.from(n)))}};function E(t){if(!t.techRoute)throw new Error("[coda-builder] Missing required config: techRoute");if(!t.platformTarget)throw new Error("[coda-builder] Missing required config: platformTarget");if(!t.mode)throw new Error("[coda-builder] Missing required config: mode");if(!t.entry)throw new Error("[coda-builder] Missing required config: entry")}function M(t){let e=t.mode==="production"||t.mode==="analyzer";return W(e,t)}function R(t,e){let{platformTarget:i}=t;["nodejs-cli","node-server","vscode-ext"].includes(i)?(e.setTarget("node"),i==="vscode-ext"?e.setExternals([C(),{vscode:"commonjs vscode"}]):e.setExternals([C()])):i==="chrome-ext"&&e.setTarget("web")}function j(t,e){let i=t.mode==="analyzer"?"production":t.mode;e.setMode(i).setEntry(t.entry).setContext(t.context).setOutput(t.output).setDevtool(t.devtool).setCache(t.cache).setMaxChunks(t.maxChunks).setStats(t.stats).setDevServer(t.devServer).setWatch(t.watch).setWatchOptions(t.watchOptions),e.setOptimization(t.optimization,t.splitChunks,t.terserOptions,t.platformTarget,i,t.minimize,t.parallel),e.setResolve(t.resolve,{alias:t.alias,extensions:t.extensions,extensionAlias:t.extensionAlias,modules:t.modules,mainFields:t.mainFields}),e.setModule(t.module,{noParse:t.noParse,rules:t.rules}),t.target&&e.setTarget(t.target),t.externals&&e.setExternals(t.externals)}function q(t,e){let i=t.mode==="production"||t.mode==="analyzer";if(t.copyRules&&t.copyRules.length>0&&e.addPlugin(new k(t.copyRules)),t.html)try{let o=c("html-webpack-plugin"),s=typeof t.html=="object"?t.html:{};e.addPlugin(new o(s))}catch{throw new Error('[coda-builder] html-webpack-plugin is required when using "html" config. Please install it.')}if(i)try{let o=c("mini-css-extract-plugin");e.addPlugin(new o({filename:"css/[name].[contenthash:8].css",chunkFilename:"css/[name].[contenthash:8].chunk.css"}))}catch{throw new Error("[coda-builder] mini-css-extract-plugin is required in production mode. Please install it.")}if(t.gzip!==!1&&(t.gzip||i))try{let o=c("compression-webpack-plugin"),s={filename:"[path][base].gz",algorithm:"gzip",test:/\.(js|css|png|jpg|jpeg|svg)(\?.*)?$/i,threshold:8192,minRatio:.8,deleteOriginalAssets:!1,exclude:[/node_modules/]},n=typeof t.gzip=="object"?{...s,...t.gzip}:s;e.addPlugin(new o(n))}catch{throw new Error('[coda-builder] compression-webpack-plugin is required when using "gzip" config. Please install it.')}if(t.plugins&&t.plugins.length>0&&e.addPlugins(t.plugins),t.mode==="analyzer"&&e.addPlugin(new A({analyzerMode:"server"})),t.platformTarget==="nodejs-cli")try{let o=c("fs"),s=c("path"),n=c("webpack"),a=s.resolve(process.cwd(),"package.json");if(o.existsSync(a)){let r=JSON.parse(o.readFileSync(a,"utf-8"));if(r.bin){let l=[];typeof r.bin=="string"?l=[r.bin]:typeof r.bin=="object"&&r.bin!==null&&(l=Object.values(r.bin)),l.forEach(h=>{let p=h.replace(/^\.\//,"").split("/"),d=p.pop()||"index.js",g=p.pop()||"bin",w=new RegExp(`${g}[\\\\/]${d}$`);e.addPlugin(new n.BannerPlugin({banner:"#!/usr/bin/env node",raw:!0,test:w}))})}}}catch{}}function N(t,e){if(t.configureWebpack&&typeof t.configureWebpack=="function"){let i=t.configureWebpack(e,t.mode);if(i)return i}return e}function T(t,e){if(E(t),t.thread&&t.mode==="development")try{let n=c("thread-loader"),a=y(t.workerOptions||{name:"ts-thread",workers:2,workerParallelJobs:40,workerNodeArgs:"--max-old-space-size=512",poolRespawn:!1,poolParallelJobs:200},t.mode);n.warmup({workerBabelArgs:a},["ts-loader"])}catch{}let i=M(t),o=new b(i);o.setConfig({context:process.cwd()}),R(t,o),j(t,o),q(t,o);let s=o.getConfig();if(s=N(t,s),t.speedMeasure&&(t.mode==="development"||t.mode==="analyzer"))try{let n=c("speed-measure-webpack-v5-plugin");s=new n().wrap(s)}catch{throw new Error('[coda-builder] speed-measure-webpack-v5-plugin is required when using "speedMeasure" config. Please install it.')}return e&&(console.log("webpack\u914D\u7F6E:"),console.dir(i,{depth:null})),s}export{T as resolveWebpackConfig};
package/package.json CHANGED
@@ -1,17 +1,13 @@
1
1
  {
2
2
  "name": "coda-builder",
3
- "version": "1.0.0",
4
- "scripts": {
5
- "build": "tsc",
6
- "typecheck": "tsc --noEmit"
7
- },
8
- "main": "dist/src/index.js",
9
- "types": "dist/src/index.d.ts",
3
+ "version": "1.0.8",
4
+ "main": "./build/index.js",
5
+ "types": "./build/index.d.ts",
10
6
  "exports": {
11
7
  ".": {
12
- "types": "./dist/src/index.d.ts",
13
- "require": "./dist/src/index.js",
14
- "import": "./dist/src/index.js"
8
+ "types": "./build/index.d.ts",
9
+ "require": "./build/index.js",
10
+ "import": "./build/index.js"
15
11
  }
16
12
  },
17
13
  "dependencies": {
@@ -36,18 +32,5 @@
36
32
  "terser-webpack-plugin": "^5.6.1",
37
33
  "speed-measure-webpack-v5-plugin": "^1.5.2",
38
34
  "thread-loader": "4.0.2"
39
- },
40
- "devDependencies": {
41
- "@types/node": "^22.0.0",
42
- "@types/webpack": "^5.28.5",
43
- "@types/webpack-dev-server": "^4.7.2",
44
- "@types/webpackbar": "^5.0.0",
45
- "@types/webpack-node-externals": "^3.0.4",
46
- "@types/webpack-bundle-analyzer": "^4.7.0",
47
- "ts-node": "^10.9.2",
48
- "typescript": "^5.5.0"
49
- },
50
- "files": [
51
- "dist"
52
- ]
53
- }
35
+ }
36
+ }