akfun 5.1.15 → 6.0.0

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
@@ -1,341 +1,468 @@
1
- ## AKFun 前端脚手架
2
- AKFun 是一个基于 Webpack 与 Rollup 的多场景前端打包工具,支持 Vue、React、React+TS 技术栈,致力于提供“零配置、开箱即用”的工程能力,让开发者专注业务。
3
-
4
- ### 主要特性
5
- - **零配置**: 内置默认配置,开箱即用;
6
- - **多技术栈**: 支持 Vue、React、React+TS 的调试与构建;
7
- - **多构建场景**: 本地开发(含热更新/代理)、生产构建、库构建(UMD/ESM);
8
- - **灵活可配**: 支持入口、别名、代理、SASS 注入、ESLint/StyleLint、Babel/Loader/Plugin 扩展等配置;
9
- - **样式与规范**: 集成 Autoprefixer、Sass、PostCSS、ESLint、StyleLint;
10
- - **参数替换**: 支持基于 [params-replace-loader](https://www.npmjs.com/package/params-replace-loader) 的环境变量批量替换;
11
- - **模板支持**: 提供完整的 Vue/React 项目模板。
1
+ # AKFun 前端脚手架
12
2
 
13
- ## 快速开始
3
+ AKFun 是一个基于 Webpack 与 Rollup 的多场景前端打包工具,支持 Vue、React、React+TS 技术栈,致力于提供"零配置、开箱即用"的工程能力,让开发者专注业务。
4
+
5
+ ## 目录
6
+
7
+ - [主要特性](#主要特性)
8
+ - [安装](#安装)
9
+ - [快速开始](#快速开始)
10
+ - [命令说明](#命令说明)
11
+ - [配置指南](#配置指南)
12
+ - [配置文件说明](#配置文件说明)
13
+ - [基础配置](#基础配置)
14
+ - [开发配置](#开发配置)
15
+ - [构建配置](#构建配置)
16
+ - [高级配置](#高级配置)
17
+ - [其他说明](#其他说明)
18
+
19
+ ---
20
+
21
+ ## 主要特性
22
+
23
+ - **零配置**: 内置默认配置,开箱即用
24
+ - **多技术栈**: 支持 Vue、React、React+TS 的调试与构建
25
+ - **多构建场景**: 本地开发(含热更新/代理)、生产构建、库构建(UMD/ESM)
26
+ - **灵活可配**: 支持入口、别名、代理、SASS 注入、ESLint/StyleLint、Babel/Loader/Plugin 扩展等配置
27
+ - **样式与规范**: 集成 Autoprefixer、Sass、PostCSS、ESLint、StyleLint
28
+ - **参数替换**: 支持基于 [params-replace-loader](https://www.npmjs.com/package/params-replace-loader) 的环境变量批量替换
29
+ - **模板支持**: 提供完整的 Vue/React 项目模板
30
+ - **内置缓存机制**: 内置缓存机制,提升二次构建速度
31
+
32
+ ---
33
+
34
+ ## 安装
35
+
36
+ ### 全局安装
14
37
 
15
- ### 方法一:全局安装
16
- 1) 安装
17
38
  ```bash
18
39
  yarn global add akfun
19
40
  # 或
20
41
  npm i -g akfun
21
42
  ```
22
- 2) 创建项目(可指定模板与目录)
23
- ```bash
24
- akfun init -t=vue
25
- # 指定目录
26
- akfun init -t=vue --dir=myTest1
27
- ```
28
- 3) 运行构建(需先安装依赖)
29
- ```bash
30
- # 本地开发调试
31
- akfun dev
32
-
33
- # 生产环境构建
34
- akfun build
35
43
 
36
- # 构建库(UMD)
37
- akfun build2lib
38
-
39
- # 构建库(ESM)
40
- akfun build2esm
41
- ```
44
+ ### 项目内安装
42
45
 
43
- ### 方法二:在现有项目中使用
44
- 1) 安装到当前项目
45
46
  ```bash
46
47
  yarn add akfun --dev
47
48
  # 或
48
49
  npm i akfun --save-dev
49
50
  ```
50
- 2) 在 package.json 添加脚本
51
- ```bash
52
- "dev": "akfun dev",
53
- "build": "akfun build",
54
- "build2lib": "akfun build2lib",
55
- "build2esm": "akfun build2esm"
56
- ```
57
- 3) 初始化配置文件(按需调整入口、别名、代理等)
58
- ```bash
59
- akfun config init
60
- ```
61
- 4) 开发与构建
62
- ```bash
63
- npm run dev
64
- npm run build
65
- npm run build2lib
66
- npm run build2esm
51
+
52
+ ---
53
+
54
+ ## 快速开始
55
+
56
+ ### 方式一:创建新项目
57
+
58
+ 1. **创建项目**(可指定模板与目录)
59
+ ```bash
60
+ akfun init -t=vue
61
+ # 指定目录
62
+ akfun init -t=vue --dir=myTest1
63
+ ```
64
+
65
+ 2. **安装依赖**
66
+ ```bash
67
+ cd myTest1
68
+ npm install
69
+ # 或
70
+ yarn install
71
+ ```
72
+
73
+ 3. **开始开发**
74
+ ```bash
75
+ akfun dev
76
+ ```
77
+
78
+ ### 方式二:在现有项目中使用
79
+
80
+ 1. **安装依赖**(见上方安装说明)
81
+
82
+ 2. **初始化配置文件**
83
+ ```bash
84
+ akfun config init
85
+ ```
86
+
87
+ 3. **在 package.json 添加脚本**
88
+ ```json
89
+ {
90
+ "scripts": {
91
+ "dev": "akfun dev",
92
+ "build": "akfun build",
93
+ "build2lib": "akfun build2lib",
94
+ "build2esm": "akfun build2esm"
95
+ }
96
+ }
97
+ ```
98
+
99
+ 4. **运行命令**
100
+ ```bash
101
+ npm run dev
102
+ npm run build
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 命令说明
108
+
109
+ | 命令 | 说明 |
110
+ |------|------|
111
+ | `akfun init` | 交互式创建项目,支持 `-t`(模板类型)、`--dir`(目录名)参数 |
112
+ | `akfun config init` | 在当前项目生成 `akfun.config.js` 配置文件 |
113
+ | `akfun dev` | 启动本地开发服务器(含热更新、接口代理、可选 HTTPS、可选 ESLint/StyleLint) |
114
+ | `akfun build` | 生产环境构建(压缩优化、可选分析) |
115
+ | `akfun build2lib` | 构建 UMD 格式的库产物 |
116
+ | `akfun build2esm` | 构建 ESM 格式的库产物 |
117
+
118
+ ---
119
+
120
+ ## 配置指南
121
+
122
+ ### 配置文件说明
123
+
124
+ AKFun 默认提供完整配置,开箱即用。如需自定义配置,执行 `akfun config init` 生成 `akfun.config.js` 文件,然后按需修改。
125
+
126
+ 配置文件采用 CommonJS 格式,导出一个配置对象:
127
+
128
+ ```javascript
129
+ module.exports = {
130
+ // 配置项...
131
+ }
67
132
  ```
68
133
 
69
- ## 常用命令
70
- - **akfun init**: 交互式创建项目(支持 -t、--dir)。
71
- - **akfun config init**: 在当前项目生成 `akfun.config.js`。
72
- - **akfun dev**: 本地开发调试(含热更新、接口代理、可选 HTTPS、可选 ESLint/StyleLint)。
73
- - **akfun build**: 生产环境构建(压缩优化、可选分析)。
74
- - **akfun build2lib**: 构建 UMD 库产物。
75
- - **akfun build2esm**: 构建 ESM 库产物。
134
+ ---
76
135
 
77
- ## 多页面与模板
78
- - 当 `entry` 仅配置一个且对应文件不存在时,会自动从 `src/pages` 扫描以 `.ts/.tsx/.js/.jsx` 结尾的文件作为入口,匹配同名 HTML 作为模板(对应正则 `/\.[tj]sx?$/`)。
79
- - 仅 `dev` 和 `build` 使用页面模板;`build2lib` 不向页面注入打包产物。
80
- - 优先使用 `./src/index.html`;不存在时使用内置默认模板。多页面时若 `pages` 下存在同名 HTML,将其作为页面模板。
136
+ ### 基础配置
81
137
 
82
- ## 配置说明(akfun.config.js)
83
- AKFun 默认提供完整配置;如需自定义,执行 `akfun config init` 生成 `akfun.config.js` 并按需修改。以下为常用配置。
138
+ #### 1. 代码规范检查
84
139
 
85
- ### 1) 基础规范与检查
86
- ```bash
140
+ 控制 ESLint 和 StyleLint 的启用与自动修复:
141
+
142
+ ```javascript
87
143
  module.exports = {
88
144
  settings: {
89
- enableESLint: true, // 是否开启ESLint,默认开启ESLint检测代码格式
90
- enableESLintFix: false, // 是否ESLint自动修正代码格式
91
- enableStyleLint: true, // 是否开启StyleLint,默认开启ESLint检测代码格式
92
- enableStyleLintFix: false // 是否需要StyleLint自动修正代码格式
93
- },
94
- ...
145
+ enableESLint: true, // 是否开启 ESLint,默认开启
146
+ enableESLintFix: false, // 是否 ESLint 自动修正代码格式
147
+ enableStyleLint: true, // 是否开启 StyleLint,默认开启
148
+ enableStyleLintFix: false // 是否 StyleLint 自动修正代码格式
149
+ }
95
150
  }
96
151
  ```
97
152
 
98
- ### 2) 构建入口(优先级:dev/build/build2lib.entry > webpack.entry)
99
- > 备注:建议以 key/value(object { <key>: string | [string] })配置 entry。详情参考 Webpack 文档:[关于 entry 的配置方法](https://www.webpackjs.com/configuration/entry-context/#entry)
100
- ```bash
153
+ #### 2. 构建入口
154
+
155
+ 配置构建入口文件,支持多入口。优先级:`dev/build/build2lib.entry` > `webpack.entry`
156
+
157
+ > **提示**: 建议以 key/value(object `{ <key>: string | [string] }`)配置 entry。详情参考 [Webpack 文档](https://www.webpackjs.com/configuration/entry-context/#entry)
158
+
159
+ ```javascript
101
160
  module.exports = {
102
- ...
103
161
  webpack: {
104
- entry: { index: './src/index.js' },
162
+ entry: {
163
+ index: './src/index.js'
164
+ }
105
165
  },
106
- ...
166
+ // 各场景可单独配置入口
107
167
  dev: { entry: {} },
108
168
  build: { entry: {} },
109
169
  build2lib: { entry: {} },
110
170
  build2esm: {
111
171
  input: resolve('src/main.js'),
112
- fileName: 'index',
113
- },
114
- ...
172
+ fileName: 'index'
173
+ }
115
174
  }
116
175
  ```
117
176
 
118
- ### 3) 解析配置(extensions)
119
- > 详情参考 Webpack 文档:[关于 resolve.extensions 的配置方法](https://www.webpackjs.com/configuration/resolve/#resolve-extensions)
120
- ```bash
177
+ #### 3. 文件解析配置
178
+
179
+ 配置模块解析的文件扩展名:
180
+
181
+ > 详情参考 [Webpack resolve.extensions 文档](https://www.webpackjs.com/configuration/resolve/#resolve-extensions)
182
+
183
+ ```javascript
121
184
  module.exports = {
122
- ...
123
185
  webpack: {
124
186
  resolve: {
125
- extensions: ['.js', '.jsx', '.vue', 'json'],
187
+ extensions: ['.js', '.jsx', '.vue', '.json']
126
188
  }
127
- },
128
- ...
189
+ }
129
190
  }
130
191
  ```
131
192
 
132
- ### 4) 别名配置(alias)
133
- > 详情参考 Webpack 文档:[关于 resolve.alias 的配置方法](https://www.webpackjs.com/configuration/resolve/#resolve-alias)
134
- ```bash
193
+ #### 4. 路径别名配置
194
+
195
+ 配置模块路径别名,简化导入路径:
196
+
197
+ > 详情参考 [Webpack resolve.alias 文档](https://www.webpackjs.com/configuration/resolve/#resolve-alias)
198
+
199
+ ```javascript
135
200
  module.exports = {
136
- ...
137
201
  webpack: {
138
202
  resolve: {
139
- alias: {},
203
+ alias: {
204
+ '@': resolve('src'),
205
+ 'components': resolve('src/components')
206
+ }
140
207
  }
141
- },
142
- ...
208
+ }
143
209
  }
144
210
  ```
145
211
 
146
- ### 5) 页面模板与样式资源
147
- ```bash
212
+ #### 5. 页面模板与样式资源
213
+
214
+ ```javascript
148
215
  module.exports = {
149
- ...
150
216
  webpack: {
151
- template: '', // 自定义页面模板
152
- sassResources: [], // 为每个 .scss 注入公共 SASS(变量、mixin、function 等)
217
+ template: '', // 自定义页面模板路径
218
+ sassResources: [ // 为每个 .scss 文件注入公共 SASS(变量、mixin、function 等)
219
+ resolve('src/assets/css/mixin.scss'),
220
+ resolve('src/assets/css/variables.scss')
221
+ ]
153
222
  }
154
- ...
155
223
  }
156
224
  ```
157
225
 
158
- ### 6) 依赖打包策略(忽略 node_modules)
159
- > 打包过程中忽略 node_modules 依赖,减少最终体积;可通过 allowList 指定需注入 bundle 的依赖。
160
- ```bash
226
+ #### 6. 依赖打包策略
227
+
228
+ 控制是否忽略 `node_modules` 中的依赖,减少打包体积:
229
+
230
+ ```javascript
161
231
  module.exports = {
162
- ...
163
232
  webpack: {
164
- ignoreNodeModules: true, // 是否忽略node_modules中的依赖文件
165
- allowList: [], // 用于配置会注入bundle中的依赖包(ignoreNodeModules为true时生效)
233
+ ignoreNodeModules: true, // 是否忽略 node_modules 中的依赖文件
234
+ allowList: [ // 配置需要注入 bundle 的依赖包(ignoreNodeModules true 时生效)
235
+ 'lodash',
236
+ 'axios'
237
+ ]
166
238
  }
167
- ...
168
239
  }
169
240
  ```
170
241
 
171
- ### 7) TypeScript 声明文件与工程目录
172
- ```bash
242
+ #### 7. TypeScript 配置
243
+
244
+ ```javascript
173
245
  module.exports = {
174
- ...
175
246
  webpack: {
176
- createDeclaration: true, // 是否生成ts声明文件
177
- projectDir: ['./src'], // 可配置多个目录,用于提升工程执行效率
247
+ createDeclaration: true, // 是否生成 TypeScript 声明文件
248
+ projectDir: ['./src'] // 可配置多个目录,用于提升工程执行效率
178
249
  }
179
- ...
180
250
  }
181
251
  ```
182
252
 
183
- ### 8) 环境变量替换(params-replace-loader)
184
- > [关于 params-replace-loader 的使用方法](https://www.npmjs.com/package/params-replace-loader)
185
- ```bash
253
+ #### 8. 环境变量替换
254
+
255
+ 基于 [params-replace-loader](https://www.npmjs.com/package/params-replace-loader) 实现环境变量批量替换:
256
+
257
+ > 详情参考 [params-replace-loader 使用文档](https://www.npmjs.com/package/params-replace-loader)
258
+
259
+ ```javascript
186
260
  module.exports = {
187
- ...
188
261
  envParams: {
189
- common: { // 通用参数
190
- '#version#': '20200810.1',
262
+ common: { // 通用参数
263
+ '#version#': '20200810.1'
191
264
  },
192
- local: { // 本地开发环境
193
- '#dataApiBase#': 'http://localhost:1024', // 数据接口根地址
265
+ local: { // 本地开发环境
266
+ '#dataApiBase#': 'http://localhost:1024', // 数据接口根地址
194
267
  '#assetsPublicPath#': 'http://localhost:1024', // 静态资源根地址
195
- '#routeBasePath#': '/', // 路由根地址
196
- },
268
+ '#routeBasePath#': '/' // 路由根地址
269
+ }
197
270
  }
198
- ...
199
271
  }
200
272
  ```
201
273
 
202
- ### 9) 开发服务(代理与基础配置)
203
- > [关于 proxyTable 的配置方法](https://www.webpackjs.com/configuration/dev-server/#devserver-proxy)
204
- ```bash
274
+ ---
275
+
276
+ ### 开发配置
277
+
278
+ #### 开发服务器配置
279
+
280
+ 配置开发服务器的端口、代理、资源路径等:
281
+
282
+ > 关于 proxyTable 的配置方法,参考 [Webpack DevServer Proxy 文档](https://www.webpackjs.com/configuration/dev-server/#devserver-proxy)
283
+
284
+ ```javascript
205
285
  module.exports = {
206
- ...
207
286
  dev: {
208
- NODE_ENV: 'development', // development 模式,不会启动UglifyJsPlugin服务
209
- port: 80, // 启动server服务的端口
210
- autoOpenBrowser: true, // 是否自动打开页面
211
- assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
212
- assetsSubDirectory: '', // 资源引用二级路径
213
- hostname: 'localhost', // 自动打开的页面主机
214
- proxyTable: { // 接口代理
287
+ NODE_ENV: 'development', // development 模式,不会启动 UglifyJsPlugin
288
+ port: 80, // 启动 server 服务的端口
289
+ autoOpenBrowser: true, // 是否自动打开页面
290
+ assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
291
+ assetsSubDirectory: '', // 资源引用二级路径
292
+ hostname: 'localhost', // 自动打开的页面主机
293
+ proxyTable: { // 接口代理配置
215
294
  '/apiTest': {
216
- target: 'http://api-test.com.cn', // 不支持跨域的接口根地址
217
- ws: true,
218
- changeOrigin: true
295
+ target: 'http://api-test.com.cn', // 不支持跨域的接口根地址
296
+ ws: true, // 启用 WebSocket
297
+ changeOrigin: true // 改变请求头中的 origin
219
298
  }
220
299
  },
221
- cssSourceMap: false,
222
- },
223
- ...
300
+ cssSourceMap: false, // CSS Source Map
301
+ https: false // 是否启用 HTTPS(见下方 HTTPS 配置说明)
302
+ }
224
303
  }
225
304
  ```
226
305
 
227
- ### 10) 生产构建
228
- ```bash
306
+ #### 本地 HTTPS
307
+
308
+ 启用本地 HTTPS 开发服务:
309
+
310
+ > 使用 `https://localhost/index.html` 访问当前项目
311
+
312
+ ```javascript
313
+ module.exports = {
314
+ dev: {
315
+ https: true // 默认不开启
316
+ }
317
+ }
318
+ ```
319
+
320
+ **注意事项**: akfun 使用自签名证书开启 HTTPS 服务,浏览器会提示安全性问题。需要进行如下设置:
321
+
322
+ - **Chrome**: 浏览器打开 `chrome://flags/#allow-insecure-localhost` 后将其设置为 `Enabled`
323
+ - **其他浏览器**: 类似设置允许本地不安全的 localhost 连接
324
+
325
+ ---
326
+
327
+ ### 构建配置
328
+
329
+ #### 生产环境构建
330
+
331
+ 配置生产构建的输出路径、资源路径、压缩优化等:
332
+
333
+ ```javascript
229
334
  module.exports = {
230
- ...
231
335
  build: {
232
- NODE_ENV: 'production', // production 模式,会启动UglifyJsPlugin服务
233
- assetsRoot: resolve('./dist'), // 打包后的文件绝对路径(物理路径)
234
- assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
235
- assetsSubDirectory: '', // 资源引用二级路径
236
- productionSourceMap: false, // 是否显示原始源代码
237
- productionGzip: false, // 是否开启Gzip服务
238
- productionGzipExtensions: ['js', 'css', 'json'], // Gzip识别的文件后缀
239
- bundleAnalyzerReport: false, // 开启打包分析功能
336
+ NODE_ENV: 'production', // production 模式,会启动 UglifyJsPlugin
337
+ assetsRoot: resolve('./dist'), // 打包后的文件绝对路径(物理路径)
338
+ assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
339
+ assetsSubDirectory: '', // 资源引用二级路径
340
+ productionSourceMap: false, // 是否生成 Source Map
341
+ productionGzip: false, // 是否开启 Gzip 压缩
342
+ productionGzipExtensions: ['js', 'css', 'json'], // Gzip 识别的文件后缀
343
+ bundleAnalyzerReport: false // 是否开启打包分析功能
240
344
  }
241
- ...
242
345
  }
243
346
  ```
244
347
 
245
- ### 11) 库构建(UMD)
246
- ```bash
348
+ #### 库构建(UMD)
349
+
350
+ 构建 UMD 格式的库,适用于通过 `<script>` 标签或 CommonJS/AMD 方式引入:
351
+
352
+ ```javascript
247
353
  module.exports = {
248
- ...
249
354
  build2lib: {
250
- NODE_ENV: 'production', // production 模式,会启动UglifyJsPlugin服务
251
- libraryName: '', // 构建第三方功能包时最后导出的引用变量名
252
- assetsRoot: resolve('dist'), // 编译完成的文件存放路径
253
- assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
254
- assetsSubDirectory: '', // 资源引用二级路径
255
- productionSourceMap: false, // 是否显示原始源代码
256
- productionGzip: false, // 是否开启Gzip服务
257
- productionGzipExtensions: ['js', 'css', 'json'], // Gzip识别的文件后缀
258
- bundleAnalyzerReport: false, // 开启打包分析功能
259
- },
260
- ...
355
+ NODE_ENV: 'production', // production 模式
356
+ libraryName: 'MyLibrary', // 构建第三方功能包时最后导出的引用变量名
357
+ assetsRoot: resolve('dist'), // 编译完成的文件存放路径
358
+ assetsPublicPath: '/', // 设置静态资源的引用路径
359
+ assetsSubDirectory: '', // 资源引用二级路径
360
+ productionSourceMap: false, // 是否生成 Source Map
361
+ productionGzip: false, // 是否开启 Gzip 压缩
362
+ productionGzipExtensions: ['js', 'css', 'json'], // Gzip 识别的文件后缀
363
+ bundleAnalyzerReport: false // 是否开启打包分析功能
364
+ }
261
365
  }
262
366
  ```
263
367
 
264
- ### 12) 库构建(ESM)
265
- ```bash
368
+ #### 库构建(ESM)
369
+
370
+ 构建 ESM 格式的库,适用于现代模块系统:
371
+
372
+ ```javascript
266
373
  module.exports = {
267
- ...
268
374
  build2esm: {
269
- input: resolve('src/main.js'), // 入口文件
270
- fileName: 'index', // 输出的文件名称
271
- svgDir: 'src/icons/**', // 用于设置当前项目的icon所在目录,避免被 @rollup/plugin-image 编译成base64格式
272
- },
273
- ...
375
+ input: resolve('src/main.js'), // 入口文件
376
+ fileName: 'index', // 输出的文件名称
377
+ svgDir: 'src/icons/**' // 用于设置当前项目的 icon 所在目录,避免被 @rollup/plugin-image 编译成 base64 格式
378
+ }
274
379
  }
275
380
  ```
276
381
 
277
- ### 13) 自定义 Loader / Plugin / Babel Plugins
278
- ```bash
382
+ ---
383
+
384
+ ### 高级配置
385
+
386
+ #### 自定义 Loader / Plugin / Babel Plugins
387
+
388
+ 扩展 Webpack 的 Loader、Plugin 和 Babel 插件:
389
+
390
+ ```javascript
279
391
  module.exports = {
280
392
  webpack: {
281
- moduleRules: [], // 用于添加自定义 loaders
282
- plugins: [], // 用于添加自定义 plugins
283
- babelPlugins: [ // 用于添加自定义 Babel plugins
393
+ moduleRules: [], // 用于添加自定义 loaders
394
+ plugins: [], // 用于添加自定义 plugins
395
+ babelPlugins: [ // 用于添加自定义 Babel plugins
284
396
  [
285
397
  'component',
286
- { libraryName: 'element-ui', styleLibraryName: 'theme-chalk' },
287
- ],
288
- ],
289
- },
398
+ {
399
+ libraryName: 'element-ui',
400
+ styleLibraryName: 'theme-chalk'
401
+ }
402
+ ]
403
+ ]
404
+ }
290
405
  }
291
406
  ```
292
- 备注: 以上自定义 babelPlugins 用于实现 [element-ui 组件按需引入](https://element.eleme.cn/#/zh-CN/component/quickstart#an-xu-yin-ru)。
293
407
 
294
- 也支持以函数形式动态调整内置 Babel Plugins:
295
- ```bash
408
+ **示例**: 以上自定义 `babelPlugins` 用于实现 [element-ui 组件按需引入](https://element.eleme.cn/#/zh-CN/component/quickstart#an-xu-yin-ru)
409
+
410
+ **函数形式**: 也支持以函数形式动态调整内置 Babel Plugins:
411
+
412
+ ```javascript
296
413
  module.exports = {
297
414
  webpack: {
298
415
  babelPlugins: (curBabelPlugins) => {
299
416
  curBabelPlugins.push(/* your plugin */)
300
417
  return curBabelPlugins
301
- },
302
- },
418
+ }
419
+ }
303
420
  }
304
421
  ```
305
422
 
306
- ### 14) 自定义 css-loader / 自定义 postcss-loader
307
- ```bash
423
+ #### 自定义 CSS Loader / PostCSS Loader
424
+
425
+ 自定义 CSS 和 PostCSS 的处理配置:
426
+
427
+ ```javascript
308
428
  module.exports = {
309
- ...
310
429
  webpack: {
311
430
  cssLoaderOption: {
312
- import: false, // 启用/禁用 @import 解析
431
+ import: false // 启用/禁用 @import 解析
313
432
  },
314
- postCssLoaderOption: { // 自定义postcss-loader的配置
433
+ postCssLoaderOption: { // 自定义 postcss-loader 的配置
315
434
  postcssOptions: {
316
435
  plugins: [
317
- require('postcss-pxtorem')({ // 用于将px自动转化为rem
318
- rootValue: 16, // 1rem 等于 16px
319
- propList: ['*'], // 所有属性都转换
320
- }),
321
- ],
436
+ require('postcss-pxtorem')({ // 用于将 px 自动转化为 rem
437
+ rootValue: 16, // 1rem 等于 16px
438
+ propList: ['*'] // 所有属性都转换
439
+ })
440
+ ]
322
441
  }
323
442
  }
324
443
  }
325
- ...
326
444
  }
327
445
  ```
328
446
 
329
- ### 15) 本地 HTTPS
330
- > 使用 `https://localhost/index.html` 访问当前项目。
331
- ```bash
332
- module.exports = {
333
- ...
334
- dev: {
335
- ...
336
- https: true, // 默认不开启
337
- }
338
- ...
339
- }
340
- ```
341
- 备注:akfun使用自签名证书开启https服务,浏览器会提示安全性问题不能正常访问,需要进行如下设置,以 Chrome设置 为例:浏览器打开 Chrome://flags/#allow-insecure-localhost 后将其设置为Enabled。
447
+ ---
448
+
449
+ ## 其他说明
450
+
451
+ ### 多页面与模板
452
+
453
+ - **自动扫描入口**: 当 `entry` 仅配置一个且对应文件不存在时,会自动从 `src/pages` 扫描以 `.ts/.tsx/.js/.jsx` 结尾的文件作为入口,匹配同名 HTML 作为模板(对应正则 `/\.[tj]sx?$/`)
454
+
455
+ - **模板使用范围**: 仅 `dev` 和 `build` 使用页面模板;`build2lib` 不向页面注入打包产物
456
+
457
+ - **模板优先级**:
458
+ 1. 优先使用 `./src/index.html`
459
+ 2. 不存在时使用内置默认模板
460
+ 3. 多页面时,若 `pages` 下存在同名 HTML,将其作为页面模板
461
+
462
+ ---
463
+
464
+ ## 相关链接
465
+
466
+ - [Webpack 官方文档](https://webpack.js.org/)
467
+ - [Rollup 官方文档](https://rollupjs.org/)
468
+ - [params-replace-loader](https://www.npmjs.com/package/params-replace-loader)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akfun",
3
- "version": "5.1.15",
3
+ "version": "6.0.0",
4
4
  "description": "前端脚手架:支持Vue技术栈和react技术栈",
5
5
  "keywords": [
6
6
  "前端工程",
@@ -62,21 +62,21 @@
62
62
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
63
63
  "@babel/plugin-syntax-import-meta": "^7.10.4",
64
64
  "@babel/plugin-transform-runtime": "^7.27.1",
65
- "@babel/polyfill": "^7.10.1",
66
65
  "@babel/runtime": "^7.27.1",
67
66
  "@babel/preset-env": "^7.16.11",
68
67
  "@babel/preset-react": "^7.16.7",
69
68
  "@babel/preset-typescript": "^7.16.7",
70
69
  "@babel/register": "^7.17.0",
71
70
  "@mapbox/stylelint-processor-arbitrary-tags": "^0.4.0",
72
- "@rollup/plugin-alias": "^3.1.9",
73
- "@rollup/plugin-babel": "^5.3.0",
74
- "@rollup/plugin-commonjs": "^21.0.1",
75
- "@rollup/plugin-image": "^2.1.1",
71
+ "@rollup/plugin-alias": "^6.0.0",
72
+ "@rollup/plugin-babel": "^6.1.0",
73
+ "@rollup/plugin-commonjs": "^29.0.0",
74
+ "@rollup/plugin-image": "^3.0.3",
76
75
  "@svgr/rollup": "^8.1.0",
77
- "@rollup/plugin-json": "^4.1.0",
78
- "@rollup/plugin-node-resolve": "^13.1.3",
79
- "@rollup/plugin-typescript": "^8.3.1",
76
+ "@rollup/plugin-json": "^6.1.0",
77
+ "@rollup/plugin-node-resolve": "^16.0.3",
78
+ "@rollup/plugin-typescript": "^12.3.0",
79
+ "@rollup/plugin-terser": "^0.4.4",
80
80
  "@svgr/webpack": "^6.2.1",
81
81
  "@typescript-eslint/eslint-plugin": "^5.10.2",
82
82
  "@typescript-eslint/parser": "^5.10.2",
@@ -88,6 +88,7 @@
88
88
  "chalk": "^4.0.0",
89
89
  "compression-webpack-plugin": "^9.2.0",
90
90
  "connect-history-api-fallback": "^2.0.0",
91
+ "core-js": "^3.47.0",
91
92
  "copy-webpack-plugin": "^10.2.4",
92
93
  "css-loader": "^6.6.0",
93
94
  "css-minimizer-webpack-plugin": "^3.4.1",
@@ -129,12 +130,11 @@
129
130
  "progress-bar-webpack-plugin": "^2.1.0",
130
131
  "qs": "^6.10.3",
131
132
  "rimraf": "^3.0.2",
132
- "rollup": "^2.67.0",
133
- "rollup-plugin-node-externals": "^4.0.0",
133
+ "rollup": "^4.53.3",
134
+ "rollup-plugin-node-externals": "^8.1.2",
134
135
  "rollup-plugin-postcss": "^4.0.2",
135
- "rollup-plugin-terser": "^7.0.2",
136
136
  "rollup-plugin-vue": "^6.0.0",
137
- "sass": "^1.49.7",
137
+ "sass": "^1.94.2",
138
138
  "sass-loader": "^12.4.0",
139
139
  "less": "^4.1.3",
140
140
  "less-loader": "^11.0.0",
@@ -175,8 +175,8 @@
175
175
  "prettier": "^2.5.1"
176
176
  },
177
177
  "engines": {
178
- "node": ">= 10.13.0",
179
- "npm": ">= 6.4.1"
178
+ "node": ">= 16.0.0",
179
+ "npm": ">= 8.0.0"
180
180
  },
181
181
  "browserslist": [
182
182
  "> 1%",
package/src/build2esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const ora = require('ora');
2
2
  const rollup = require('rollup');
3
- const { terser } = require('rollup-plugin-terser'); // 压缩
3
+ const { terser } = require('@rollup/plugin-terser'); // 压缩
4
4
  const projectConfig = require('./config/index'); // 引入当前项目配置文件
5
5
  const defaultConfig = require('./config/default.config');
6
6
  const rollupConfig = require('./config/rollup.config'); // rollup的配置文件
@@ -12,18 +12,20 @@ async function build2esmFunc(options, curConfig) {
12
12
  // create a bundle
13
13
  const bundle = await rollup.rollup({
14
14
  input: options.input,
15
- external: options.externals,
15
+ external: options.external || options.externals, // 兼容新旧两种写法
16
16
  plugins: options.plugins
17
17
  });
18
18
 
19
19
  if (isArray(options.output)) {
20
- options.output.map((outputItem) => {
21
- bundle.write(outputItem);
22
- });
20
+ // 等待所有输出完成
21
+ await Promise.all(options.output.map((outputItem) => bundle.write(outputItem)));
23
22
  } else if (isObject(options.output)) {
24
23
  // or write the bundle to disk
25
24
  await bundle.write(options.output);
26
25
  }
26
+
27
+ // 关闭 bundle 以释放资源
28
+ await bundle.close();
27
29
  }
28
30
 
29
31
  // 构建脚本:一般用于构建生产环境的代码
@@ -60,8 +62,8 @@ module.exports = function (fileName, akfunConfig, _consoleTag) {
60
62
  externals = externals.concat(Object.keys(build2esmExternal));
61
63
  }
62
64
 
63
- // 添加到 rollup 配置中
64
- curRollupConfig.externals = externals;
65
+ // 添加到 rollup 配置中(rollup 使用 external 而不是 externals)
66
+ curRollupConfig.external = externals;
65
67
 
66
68
  if (build2esm && build2esm.output) {
67
69
  curRollupConfig.output = build2esm.output;
@@ -5,6 +5,8 @@ module.exports = {
5
5
  {
6
6
  loose: true,
7
7
  modules: false, // 是否启用将ES6模块语法转换为其他模块类型的功能,当前设置为false,以便webpack进行tree shaking。
8
+ useBuiltIns: 'usage', // 按需引入 polyfill,替代 @babel/polyfill
9
+ corejs: 3, // 使用 core-js 3.x 版本
8
10
  targets: {
9
11
  browsers: ['> 1%', 'last 2 versions', 'not ie <= 8']
10
12
  }
@@ -12,6 +12,9 @@ configManager.autoLoadConfig();
12
12
  // 合并配置
13
13
  const mergedConfig = configManager.mergeConfig();
14
14
 
15
+ // 校验当前项目配置
16
+ configManager.validateConfig(mergedConfig);
17
+
15
18
  // 导出合并后的配置(向后兼容)
16
19
  module.exports = mergedConfig;
17
20
 
@@ -7,7 +7,7 @@ const commonjs = require('@rollup/plugin-commonjs'); // 识别cmd模块
7
7
  const vue = require('rollup-plugin-vue');
8
8
  const json = require('@rollup/plugin-json'); // 识别json类型文件
9
9
  const image = require('@rollup/plugin-image'); // 图片处理器
10
- const { terser } = require('rollup-plugin-terser'); // 压缩
10
+ const { terser } = require('@rollup/plugin-terser'); // 压缩
11
11
  const alias = require('@rollup/plugin-alias'); // 简写配置
12
12
  // css相关处理器
13
13
  const postcss = require('rollup-plugin-postcss');
@@ -57,9 +57,12 @@ module.exports = function (fileName, akfunConfig) {
57
57
  input: rollupInput,
58
58
  plugins: [
59
59
  alias({
60
- resolve: curConfig.webpack.resolve.extensions,
61
- extensions: curConfig.webpack.resolve.extensions,
62
- entries: curConfig.webpack.resolve.alias
60
+ entries: Object.entries(curConfig.webpack.resolve.alias || {}).map(
61
+ ([find, replacement]) => ({
62
+ find,
63
+ replacement
64
+ })
65
+ )
63
66
  }),
64
67
  /**
65
68
  * excludeList(在akfun.config.js中配置)
@@ -72,6 +75,12 @@ module.exports = function (fileName, akfunConfig) {
72
75
  // devDeps: false, // 不标记 devDependencies
73
76
  // peerDeps: true, // 标记 peerDependencies
74
77
  }),
78
+ /**
79
+ * nodeResolve 插件用于解析模块路径
80
+ * extensions: 默认识别的文件后缀列表
81
+ * 默认值(来自 webpack.resolve.extensions): ['.js', '.jsx', '.ts', '.tsx', '.vue', '.json']
82
+ * 如果不配置此插件,Rollup 默认只识别 .js 和 .mjs 文件
83
+ */
75
84
  nodeResolve({
76
85
  extensions: curConfig.webpack.resolve.extensions
77
86
  }),
@@ -55,18 +55,20 @@
55
55
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
56
56
  "@babel/plugin-syntax-import-meta": "^7.10.4",
57
57
  "@babel/plugin-transform-runtime": "^7.17.0",
58
- "@babel/polyfill": "^7.10.1",
59
58
  "@babel/preset-env": "^7.16.11",
60
59
  "@babel/preset-react": "^7.16.7",
61
60
  "@babel/preset-typescript": "^7.16.7",
62
61
  "@babel/register": "^7.17.0",
63
62
  "@mapbox/stylelint-processor-arbitrary-tags": "^0.4.0",
64
- "@rollup/plugin-alias": "^3.1.9",
65
- "@rollup/plugin-babel": "^5.3.0",
66
- "@rollup/plugin-commonjs": "^21.0.1",
67
- "@rollup/plugin-image": "^2.1.1",
68
- "@rollup/plugin-json": "^4.1.0",
69
- "@rollup/plugin-node-resolve": "^13.1.3",
63
+ "@rollup/plugin-alias": "^6.0.0",
64
+ "@rollup/plugin-babel": "^6.1.0",
65
+ "@rollup/plugin-commonjs": "^29.0.0",
66
+ "@rollup/plugin-image": "^3.0.3",
67
+ "@rollup/plugin-json": "^6.1.0",
68
+ "@rollup/plugin-node-resolve": "^16.0.3",
69
+ "@rollup/plugin-terser": "^0.4.4",
70
+ "@rollup/plugin-typescript": "^12.3.0",
71
+ "@svgr/rollup": "^8.1.0",
70
72
  "@typescript-eslint/eslint-plugin": "^5.10.2",
71
73
  "@typescript-eslint/parser": "^5.10.2",
72
74
  "@vue/compiler-sfc": "^3.2.29",
@@ -77,6 +79,7 @@
77
79
  "chalk": "^4.0.0",
78
80
  "compression-webpack-plugin": "^9.2.0",
79
81
  "connect-history-api-fallback": "^1.6.0",
82
+ "core-js": "^3.47.0",
80
83
  "copy-webpack-plugin": "^10.2.4",
81
84
  "css-loader": "^6.6.0",
82
85
  "cssnano": "^5.0.16",
@@ -104,7 +107,7 @@
104
107
  "http-proxy-middleware": "^2.0.2",
105
108
  "inquirer": "^8.2.0",
106
109
  "mini-css-extract-plugin": "^2.5.3",
107
- "sass": "^1.49.7",
110
+ "sass": "^1.94.2",
108
111
  "open": "^8.4.0",
109
112
  "ora": "^4.0.4",
110
113
  "params-replace-loader": "^1.1.6",
@@ -116,9 +119,10 @@
116
119
  "progress-bar-webpack-plugin": "^2.1.0",
117
120
  "qs": "^6.10.3",
118
121
  "rimraf": "^3.0.2",
119
- "rollup": "^2.67.0",
122
+ "rollup": "^4.53.3",
123
+ "rollup-plugin-jsx": "^1.0.3",
124
+ "rollup-plugin-node-externals": "^8.1.2",
120
125
  "rollup-plugin-postcss": "^4.0.2",
121
- "rollup-plugin-terser": "^7.0.2",
122
126
  "rollup-plugin-vue": "^6.0.0",
123
127
  "sass-loader": "^12.4.0",
124
128
  "sass-resources-loader": "^2.2.4",
@@ -1,10 +1,12 @@
1
- module.export = {
1
+ module.exports = {
2
2
  presets: [
3
3
  [
4
4
  '@babel/preset-env',
5
5
  {
6
6
  loose: false,
7
7
  modules: false,
8
+ useBuiltIns: 'usage', // 按需引入 polyfill,替代 @babel/polyfill
9
+ corejs: 3, // 使用 core-js 3.x 版本
8
10
  targets: {
9
11
  browsers: ['> 1%', 'last 2 versions', 'not ie <= 8']
10
12
  }
@@ -189,20 +189,20 @@ class ConfigManager {
189
189
  const config = this.mergedConfig;
190
190
 
191
191
  // 验证必需的配置项
192
- if (!config.dev || typeof config.dev !== 'object') {
193
- throw new Error('dev 配置缺失或格式错误');
192
+ if (config.dev && typeof config.dev !== 'object') {
193
+ throw new Error('dev 配置格式错误');
194
194
  }
195
195
 
196
- if (!config.build || typeof config.build !== 'object') {
197
- throw new Error('build 配置缺失或格式错误');
196
+ if (config.build && typeof config.build !== 'object') {
197
+ throw new Error('build 配置格式错误');
198
198
  }
199
199
 
200
- if (!config.webpack || typeof config.webpack !== 'object') {
201
- throw new Error('webpack 配置缺失或格式错误');
200
+ if (config.webpack && typeof config.webpack !== 'object') {
201
+ throw new Error('webpack 配置格式错误');
202
202
  }
203
203
 
204
204
  // 验证端口号
205
- if (config.dev.port) {
205
+ if (config.dev && config.dev.port) {
206
206
  const port = parseInt(config.dev.port, 10);
207
207
  if (isNaN(port) || port < 1 || port > 65535) {
208
208
  throw new Error('dev.port 必须是 1-65535 之间的数字');
@@ -210,7 +210,7 @@ class ConfigManager {
210
210
  }
211
211
 
212
212
  // 验证路径
213
- if (config.build.assetsRoot) {
213
+ if (config.build && config.build.assetsRoot) {
214
214
  const assetsRoot = config.build.assetsRoot;
215
215
  if (typeof assetsRoot !== 'string') {
216
216
  throw new Error('build.assetsRoot 必须是字符串类型的路径');
@@ -35,7 +35,7 @@ class ConfigValidator {
35
35
 
36
36
  // 输出警告
37
37
  if (this.warnings.length > 0) {
38
- console.log(chalk.yellow('\n⚠️ 配置警告:'));
38
+ console.log(chalk.yellow('\n⚠️ 配置异常提示:'));
39
39
  this.warnings.forEach((warning) => {
40
40
  console.log(chalk.yellow(` - ${warning}`));
41
41
  });
@@ -81,23 +81,18 @@ class ConfigValidator {
81
81
  * @private
82
82
  */
83
83
  _validateWebpack(webpack) {
84
- if (!webpack) {
85
- this.errors.push('webpack 配置缺失');
86
- return;
87
- }
88
-
89
84
  // 验证 entry
90
- if (webpack.entry !== undefined) {
85
+ if (webpack && webpack.entry !== undefined) {
91
86
  this._validateEntry(webpack.entry);
92
87
  }
93
88
 
94
89
  // 验证 resolve
95
- if (webpack.resolve) {
90
+ if (webpack && webpack.resolve) {
96
91
  this._validateResolve(webpack.resolve);
97
92
  }
98
93
 
99
94
  // 验证 externals
100
- if (webpack.externals !== undefined) {
95
+ if (webpack && webpack.externals !== undefined) {
101
96
  const validTypes = ['object', 'string', 'function'];
102
97
  if (!validTypes.includes(typeof webpack.externals)) {
103
98
  this.errors.push('webpack.externals 类型不正确');
@@ -105,14 +100,14 @@ class ConfigValidator {
105
100
  }
106
101
 
107
102
  // 验证 sassResources
108
- if (webpack.sassResources !== undefined) {
103
+ if (webpack && webpack.sassResources !== undefined) {
109
104
  if (!Array.isArray(webpack.sassResources)) {
110
105
  this.errors.push('webpack.sassResources 必须是数组');
111
106
  }
112
107
  }
113
108
 
114
109
  // 验证 babelPlugins
115
- if (webpack.babelPlugins !== undefined) {
110
+ if (webpack && webpack.babelPlugins !== undefined) {
116
111
  const validTypes = ['function', 'object'];
117
112
  const type = Array.isArray(webpack.babelPlugins) ? 'object' : typeof webpack.babelPlugins;
118
113
  if (!validTypes.includes(type)) {
@@ -121,12 +116,12 @@ class ConfigValidator {
121
116
  }
122
117
 
123
118
  // 验证 moduleRules
124
- if (webpack.moduleRules !== undefined && !Array.isArray(webpack.moduleRules)) {
119
+ if (webpack && webpack.moduleRules !== undefined && !Array.isArray(webpack.moduleRules)) {
125
120
  this.errors.push('webpack.moduleRules 必须是数组');
126
121
  }
127
122
 
128
123
  // 验证 plugins
129
- if (webpack.plugins !== undefined && !Array.isArray(webpack.plugins)) {
124
+ if (webpack && webpack.plugins !== undefined && !Array.isArray(webpack.plugins)) {
130
125
  this.errors.push('webpack.plugins 必须是数组');
131
126
  }
132
127
  }
@@ -32,7 +32,7 @@ const BannerPack = new webpack.BannerPlugin({
32
32
  * _curEnvConfig: 执行环境中的配置,用于记录 dev、build、build2lib 等对应的配置内容;
33
33
  * _akfunConfig:完整的配置对象
34
34
  */
35
- module.exports = (_curEnvConfig, _akfunConfig) => {
35
+ module.exports = (_curEnvConfig, _akfunConfig, buildMode = 'build') => {
36
36
  const curEnvConfig = _curEnvConfig || {}; // 用于接收当前运行环境配置变量
37
37
  let config = _akfunConfig || projectConfig; // 默认使用执行命令目录下的配置数据
38
38
  // 获取当前项目配置文件中的webpack配置
@@ -49,7 +49,20 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
49
49
  curWebpackConfig.babelPlugins(babelConfig.plugins);
50
50
  }
51
51
 
52
+ // 获取缓存目录路径
53
+ const cacheDirectory = resolveToCurrentRoot('./node_modules/.cache/webpack');
54
+
52
55
  const webpackConfig = {
56
+ // Webpack 5 持久化缓存配置
57
+ cache: {
58
+ type: 'filesystem',
59
+ cacheDirectory: cacheDirectory,
60
+ buildDependencies: {
61
+ config: [__filename] // 当配置文件改变时,使缓存失效
62
+ },
63
+ name: `${curEnvConfig.NODE_ENV || 'development'}--${buildMode}-cache`,
64
+ compression: 'gzip' // 使用 gzip 压缩缓存文件以节省磁盘空间
65
+ },
53
66
  stats: {
54
67
  // cachedModules: false,
55
68
  // providedExports: true,
@@ -96,7 +109,13 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
96
109
  use: [
97
110
  {
98
111
  loader: 'babel-loader',
99
- options: babelConfig
112
+ options: {
113
+ ...babelConfig,
114
+ // Babel 缓存配置
115
+ cacheDirectory: true, // 启用缓存
116
+ cacheCompression: false, // 不压缩缓存文件以提升性能
117
+ cacheIdentifier: `${curEnvConfig.NODE_ENV || 'development'}--${buildMode}-babel`
118
+ }
100
119
  },
101
120
  {
102
121
  loader: 'ts-loader',
@@ -105,7 +124,11 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
105
124
  compilerOptions: {
106
125
  declaration: curWebpackConfig.createDeclaration || false,
107
126
  outDir: curEnvConfig.assetsRoot || './dist'
108
- }
127
+ },
128
+ // TypeScript 缓存配置
129
+ transpileOnly: true, // 只进行转译,不进行类型检查(提升性能)
130
+ experimentalWatchApi: true // 使用实验性的 watch API(提升性能)
131
+ // 注意:ts-loader 的缓存由 Webpack 5 的持久化缓存自动处理
109
132
  }
110
133
  }
111
134
  ],
@@ -117,7 +140,13 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
117
140
  use: [
118
141
  {
119
142
  loader: 'babel-loader',
120
- options: babelConfig
143
+ options: {
144
+ ...babelConfig,
145
+ // Babel 缓存配置
146
+ cacheDirectory: true, // 启用缓存
147
+ cacheCompression: false, // 不压缩缓存文件以提升性能
148
+ cacheIdentifier: `${curEnvConfig.NODE_ENV || 'development'}--${buildMode}-babel`
149
+ }
121
150
  }
122
151
  ],
123
152
  // exclude: /node_modules/,
@@ -273,6 +302,9 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
273
302
  }
274
303
  // 是否开启ESLint
275
304
  if (config.settings.enableESLint) {
305
+ // ESLint 缓存目录
306
+ const eslintCacheLocation = resolveToCurrentRoot('./node_modules/.cache/eslint');
307
+
276
308
  // ts类型
277
309
  webpackConfig.plugins.push(
278
310
  new ESLintPlugin({
@@ -280,7 +312,9 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
280
312
  extensions: ['ts', 'tsx'],
281
313
  // include: curProjectDir, // [resolve('src')],
282
314
  // exclude: 'node_modules',
283
- cache: true,
315
+ cache: true, // 启用缓存
316
+ cacheLocation: path.join(eslintCacheLocation, '.eslintcache-ts'), // 指定缓存位置
317
+ cacheStrategy: 'metadata', // 使用元数据缓存策略(更快)
284
318
  fix: config.settings.enableESLintFix || false,
285
319
  formatter: require('eslint-friendly-formatter'),
286
320
  overrideConfigFile: path.resolve(__dirname, '../config/.eslintrc.ts.js')
@@ -292,7 +326,9 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
292
326
  extensions: ['js', 'jsx'],
293
327
  // include: curProjectDir, // [resolve('src')],
294
328
  // exclude: 'node_modules',
295
- cache: true,
329
+ cache: true, // 启用缓存
330
+ cacheLocation: path.join(eslintCacheLocation, '.eslintcache-js'), // 指定缓存位置
331
+ cacheStrategy: 'metadata', // 使用元数据缓存策略(更快)
296
332
  fix: config.settings.enableESLintFix || false,
297
333
  formatter: require('eslint-friendly-formatter'),
298
334
  overrideConfigFile: path.resolve(__dirname, '../config/.eslintrc.js')
@@ -304,7 +340,9 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
304
340
  extensions: ['vue'],
305
341
  // include: curProjectDir, // [resolve('src')],
306
342
  // exclude: 'node_modules',
307
- cache: true,
343
+ cache: true, // 启用缓存
344
+ cacheLocation: path.join(eslintCacheLocation, '.eslintcache-vue'), // 指定缓存位置
345
+ cacheStrategy: 'metadata', // 使用元数据缓存策略(更快)
308
346
  fix: config.settings.enableESLintFix || false,
309
347
  formatter: require('eslint-friendly-formatter'),
310
348
  overrideConfigFile: path.resolve(__dirname, '../config/.eslintrc.vue.js')
@@ -313,6 +351,9 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
313
351
  }
314
352
  // 是否开启StyleLint: 用于验证scss文件里面的style规范
315
353
  if (config.settings.enableStyleLint) {
354
+ // StyleLint 缓存目录
355
+ const stylelintCacheLocation = resolveToCurrentRoot('./node_modules/.cache/stylelint');
356
+
316
357
  const vuePagesObj = catchVuePages();
317
358
  // 判断项目中是否有vue文件
318
359
  if (vuePagesObj && Object.keys(vuePagesObj).length > 0) {
@@ -321,8 +362,8 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
321
362
  new StyleLintPlugin({
322
363
  files: ['src/**/*.vue'],
323
364
  // quiet: true,
324
- cache: true,
325
- cacheLocation: resolveToCurrentRoot('./node_modules/stylelint/.vue-cache'),
365
+ cache: true, // 启用缓存
366
+ cacheLocation: path.join(stylelintCacheLocation, '.stylelintcache-vue'), // 统一缓存位置
326
367
  fix: config.settings.enableStyleLintFix,
327
368
  configFile: path.resolve(__dirname, '../config/.stylelintrc-vue')
328
369
  })
@@ -333,8 +374,8 @@ module.exports = (_curEnvConfig, _akfunConfig) => {
333
374
  new StyleLintPlugin({
334
375
  files: 'src/**/*.s?(a|c)ss',
335
376
  // quiet: true,
336
- cache: true,
337
- cacheLocation: resolveToCurrentRoot('./node_modules/stylelint/.cache'),
377
+ cache: true, // 启用缓存
378
+ cacheLocation: path.join(stylelintCacheLocation, '.stylelintcache-scss'), // 统一缓存位置
338
379
  fix: config.settings.enableStyleLintFix,
339
380
  configFile: path.resolve(__dirname, '../config/.stylelintrc')
340
381
  })
@@ -13,7 +13,7 @@ module.exports = (akfunConfig) => {
13
13
  let config = akfunConfig || projectConfig; // 默认使用执行命令目录下的配置数据
14
14
  const curEnvConfig = config.dev || {}; // 当前执行环境配置
15
15
  // 获取webpack基本配置
16
- const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config);
16
+ const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config, 'dev');
17
17
 
18
18
  // 获取页面模板地址
19
19
  let curHtmlTemplate = path.resolve(__dirname, '../initData/template/index.html');
@@ -19,7 +19,7 @@ module.exports = (akfunConfig) => {
19
19
  let config = akfunConfig || projectConfig; // 默认使用执行命令目录下的配置数据
20
20
  const curEnvConfig = config.build2lib || {}; // 当前执行环境配置
21
21
  // 获取webpack基本配置
22
- const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config);
22
+ const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config, 'build2lib');
23
23
 
24
24
  let curTarget = ['web', 'es5'];
25
25
  if (config.webpack.target) {
@@ -24,7 +24,7 @@ module.exports = (akfunConfig) => {
24
24
  let config = akfunConfig || projectConfig; // 默认使用执行命令目录下的配置数据
25
25
  const curEnvConfig = config.build || {}; // 当前执行环境配置
26
26
  // 获取webpack基本配置
27
- const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config);
27
+ const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config, 'build');
28
28
  // 获取页面模板地址
29
29
  let curHtmlTemplate = path.resolve(__dirname, '../initData/template/index.html');
30
30
  if (config.webpack.template) {