@lark-apaas/fullstack-rspack-preset 0.1.2-alpha.7 → 1.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
@@ -2,32 +2,57 @@
2
2
 
3
3
  > 开箱即用的 Fullstack Rspack 配置预设
4
4
 
5
- 提供开箱即用的 Rspack 配置,包含路由解析、性能监控、模块别名、HMR 等完整功能。
5
+ 提供开箱即用的 Rspack 配置,包含 TypeScript、React、路由解析、HMR 等完整功能。
6
6
 
7
7
  ## 特性
8
8
 
9
9
  - ✅ **零配置** - 环境变量驱动,开箱即用
10
- - ✅ **路由解析** - 自动解析 React Router 路由生成 routes.json
11
- - ✅ **性能监控** - 集成 Slardar 性能监控
12
- - ✅ **模块优化** - clsx + tailwind-merge、echarts 别名
13
- - ✅ **HMR 监控** - 热更新时间统计
10
+ - ✅ **两种使用方式** - 支持 extends 继承和 defineConfig 函数
11
+ - ✅ **TypeScript** - 完整的类型定义和 TSX 支持
14
12
  - ✅ **React Refresh** - 支持 React 快速刷新
15
- - ✅ **TypeScript** - 完整的类型定义
16
- - ✅ **向后兼容** - 同时支持新旧两种 API
13
+ - ✅ **路由解析** - 自动解析 React Router 路由
14
+ - ✅ **模块优化** - clsx + tailwind-merge、echarts 别名
15
+ - ✅ **开发体验** - HMR 监控、代理配置
17
16
 
18
17
  ## 安装
19
18
 
20
19
  ```bash
21
20
  npm install @lark-apaas/fullstack-rspack-preset
22
- # or
23
- yarn add @lark-apaas/fullstack-rspack-preset
24
21
  ```
25
22
 
26
- ## 快速开始
23
+ ## 使用方式
24
+
25
+ ### 方式 1: extends(推荐给简单场景)
26
+
27
+ 类似 ESLint、TypeScript 的配置继承方式:
28
+
29
+ ```javascript
30
+ // rspack.config.js
31
+ const path = require('path');
32
+
33
+ module.exports = {
34
+ extends: '@lark-apaas/fullstack-rspack-preset/preset.config.js',
35
+ entry: {
36
+ main: './client/src/index.tsx',
37
+ },
38
+ resolve: {
39
+ alias: {
40
+ '@': path.resolve(__dirname, 'client/src'),
41
+ },
42
+ },
43
+ };
44
+ ```
45
+
46
+ **特点:**
47
+ - ✅ 简洁明了(4 行配置)
48
+ - ✅ 符合 webpack/rspack 惯例
49
+ - ✅ 配置自动深度合并
50
+
51
+ ---
27
52
 
28
- ### 1. 简化版 API(推荐)
53
+ ### 方式 2: defineConfig(推荐给复杂场景)
29
54
 
30
- 只需提供必要的覆盖配置,其他都通过环境变量控制。
55
+ 函数式调用,更灵活:
31
56
 
32
57
  ```javascript
33
58
  // rspack.config.js
@@ -46,7 +71,14 @@ module.exports = defineConfig({
46
71
  });
47
72
  ```
48
73
 
49
- ### 2. 环境变量配置
74
+ **特点:**
75
+ - ✅ TypeScript 类型推断更好
76
+ - ✅ 可以动态计算配置
77
+ - ✅ 更灵活的配置方式
78
+
79
+ ---
80
+
81
+ ## 环境变量配置
50
82
 
51
83
  在项目根目录创建 `.env` 文件:
52
84
 
@@ -56,7 +88,6 @@ NODE_ENV=development
56
88
 
57
89
  # 功能开关
58
90
  ENABLE_REACT_REFRESH=true
59
- ENABLE_INSPECTOR=false
60
91
  NEED_ROUTES=true
61
92
 
62
93
  # 路径配置
@@ -68,231 +99,135 @@ SERVER_PORT=3000
68
99
  CLIENT_DEV_PORT=8080
69
100
  ```
70
101
 
71
- ### 3. 运行
72
-
73
- ```bash
74
- # 开发模式
75
- npx rspack serve --config rspack.config.js --env mode=development
76
-
77
- # 生产构建
78
- NODE_ENV=production npx rspack build --config rspack.config.js
79
- ```
80
-
81
- ## API 文档
82
-
83
- ### createFullstackRspackConfig / defineConfig(推荐)
84
-
85
- 自动从环境变量读取配置,用户只需提供覆盖配置。
86
-
87
- ```typescript
88
- function defineConfig(
89
- overrides?: Partial<Configuration>
90
- ): Configuration;
91
-
92
- // 别名:createFullstackRspackConfig(向后兼容)
93
- function createFullstackRspackConfig(
94
- overrides?: Partial<Configuration>
95
- ): Configuration;
96
- ```
97
-
98
- **参数:**
99
- - `overrides` - Rspack 配置对象,会与默认配置深度合并
100
-
101
- **环境变量:**
102
-
103
- | 环境变量 | 类型 | 默认值 | 说明 |
104
- |---------|------|--------|------|
105
- | `NODE_ENV` | `development \| production` | `development` | 环境模式 |
106
- | `ENABLE_REACT_REFRESH` | `boolean` | `false` | 是否启用 React Refresh |
107
- | `ENABLE_INSPECTOR` | `boolean` | `false` | 是否启用 Miaoda Inspector |
108
- | `NEED_ROUTES` | `boolean` | `true` | 是否需要路由解析 |
109
- | `CLIENT_BASE_PATH` | `string` | `/` | 客户端基础路径 |
110
- | `ASSETS_CDN_PATH` | `string` | `/` | 生产环境 CDN 路径 |
111
- | `SERVER_PORT` | `number` | `3000` | 服务器端口 |
112
- | `CLIENT_DEV_PORT` | `number` | `8080` | 客户端开发端口 |
113
-
114
- ### createRecommendRspackConfig (传统版)
102
+ ### 环境变量说明
103
+
104
+ | 变量 | 类型 | 默认值 | 说明 |
105
+ |------|------|--------|------|
106
+ | `NODE_ENV` | string | `development` | 环境模式:development / production |
107
+ | `ENABLE_REACT_REFRESH` | boolean | `false` | 是否启用 React 热更新 |
108
+ | `NEED_ROUTES` | boolean | `true` | 是否需要路由解析 |
109
+ | `CLIENT_BASE_PATH` | string | `/` | 客户端基础路径 |
110
+ | `ASSETS_CDN_PATH` | string | `/` | 生产环境 CDN 路径 |
111
+ | `SERVER_PORT` | number | `3000` | 服务器端口 |
112
+ | `CLIENT_DEV_PORT` | number | `8080` | 客户端开发服务器端口 |
113
+
114
+ ## 内置功能
115
+
116
+ ### 1. TypeScript 和 React 支持
117
+ - 自动处理 `.ts` / `.tsx` 文件
118
+ - 支持 JSX 语法
119
+ - SWC 编译器
120
+
121
+ ### 2. 样式处理
122
+ - CSS 模块支持
123
+ - PostCSS 处理
124
+ - Tailwind CSS 支持
125
+
126
+ ### 3. 资源处理
127
+ - 图片自动优化(SVG, PNG, JPG, GIF, WebP)
128
+ - 小于 10KB 自动 inline
129
+
130
+ ### 4. 路由解析
131
+ - 自动解析 React Router 路由
132
+ - 生成 `routes.json` 文件
133
+ - 通过 `NEED_ROUTES` 控制
134
+
135
+ ### 5. 开发服务器
136
+ - HMR 热更新
137
+ - API 代理到后端服务器
138
+ - 热更新时间统计
139
+
140
+ ### 6. 模块别名优化
141
+ - **clsx**: 自动集成 `tailwind-merge`
142
+ - **echarts**: 优化导入路径
143
+
144
+ ## 对比两种方式
145
+
146
+ | 特性 | extends | defineConfig |
147
+ |------|---------|-------------|
148
+ | 代码简洁度 | ✅ 更简洁 | 一般 |
149
+ | TypeScript 类型 | 一般 | ✅ 更好 |
150
+ | 动态配置 | ❌ 只能用环境变量 | ✅ 可以代码计算 |
151
+ | 符合惯例 | ✅ 符合 webpack | 一般 |
152
+ | 学习成本 | ✅ 低 | 一般 |
115
153
 
116
- 提供更细粒度的控制,需要手动处理环境变量。
117
-
118
- ```typescript
119
- function createRecommendRspackConfig(
120
- options: CreateRecommendRspackConfigOptions
121
- ): Configuration;
122
-
123
- interface CreateRecommendRspackConfigOptions {
124
- isDev?: boolean;
125
- enableReactRefresh?: boolean;
126
- needRoutes?: boolean;
127
- clientBasePath?: string;
128
- publicPath?: string;
129
- }
130
- ```
154
+ ## 迁移指南
131
155
 
132
- **示例:**
156
+ ### 从旧 API 迁移
133
157
 
158
+ **之前(15+ 行):**
134
159
  ```javascript
135
160
  const { createRecommendRspackConfig } = require('@lark-apaas/fullstack-rspack-preset');
136
161
  const { normalizeBasePath } = require('@lark-apaas/devtool-kits');
162
+ const { merge } = require('webpack-merge');
137
163
 
138
164
  require('dotenv').config();
139
165
 
140
166
  const isDev = process.env.NODE_ENV !== 'production';
141
-
142
- module.exports = createRecommendRspackConfig({
167
+ const baseConfig = createRecommendRspackConfig({
143
168
  isDev,
144
- enableReactRefresh: true,
145
169
  clientBasePath: normalizeBasePath(process.env.CLIENT_BASE_PATH || '/'),
146
- publicPath: isDev ? '/' : 'https://cdn.example.com',
170
+ publicPath: isDev ? '/' : process.env.ASSETS_CDN_PATH,
147
171
  });
148
- ```
149
-
150
- ## 内置插件和功能
151
-
152
- ### 1. RouteParserPlugin
153
-
154
- 自动解析 React Router 路由,生成 `routes.json` 文件。
155
-
156
- - **输入**:`./client/src/app.tsx`
157
- - **输出**:`dist/client/routes.json`
158
- - **控制**:`NEED_ROUTES` 环境变量
159
-
160
- ### 2. SlardarPerformanceMonitorPlugin
161
-
162
- 注入 Slardar 性能监控脚本到 HTML。
163
-
164
- - **位置**:`<head>` 标签末尾
165
- - **包含**:Slardar SDK + Performance 监控
166
-
167
- ### 3. Module Alias
168
-
169
- #### clsx 别名
170
- 将 `clsx` 替换为增强版本,自动集成 `tailwind-merge`:
171
-
172
- ```javascript
173
- import { clsx } from 'clsx'; // 自动包含 twMerge 功能
174
- ```
175
-
176
- #### echarts 别名
177
- 优化 echarts 导入路径。
178
-
179
- ### 4. HMR Timing Monitor
180
-
181
- 开发模式下自动监控热更新时间,通过 WebSocket 推送给客户端。
182
172
 
183
- ### 5. 代理配置
184
-
185
- 自动配置开发服务器代理:
186
- - API 代理:`${CLIENT_BASE_PATH}/api` → `http://localhost:${SERVER_PORT}`
187
- - HTML 代理:所有 HTML 请求 → `http://localhost:${SERVER_PORT}`
188
-
189
- ## 项目结构要求
190
-
191
- ```
192
- your-project/
193
- ├── .env # 环境变量配置
194
- ├── rspack.config.js # Rspack 配置
195
- ├── client/
196
- │ ├── public/ # 静态资源
197
- │ └── src/
198
- │ ├── app.tsx # 路由定义(需包含 React Router)
199
- │ └── index.tsx # 入口文件
200
- ├── server/ # 服务端代码
201
- └── dist/
202
- └── client/ # 构建产物
203
- ├── routes.json # 路由文件(自动生成)
204
- └── ...
173
+ module.exports = merge(baseConfig, {
174
+ entry: { main: './client/src/index.tsx' },
175
+ });
205
176
  ```
206
177
 
207
- ## 迁移指南
208
-
209
- ### 从旧 API 迁移到新 API
210
-
211
- **之前(15 行):**
212
-
178
+ **现在(extends 方式,4 行):**
213
179
  ```javascript
214
- const { defineConfig } = require('@rspack/cli');
215
- const { createRecommendRspackConfig } = require('@lark-apaas/fullstack-rspack-preset');
216
- const { normalizeBasePath } = require('@lark-apaas/devtool-kits');
217
- const { default: merge } = require('webpack-merge');
218
-
219
- require('dotenv').config();
220
-
221
- module.exports = defineConfig(({mode}) => {
222
- const isDev = mode !== 'production';
223
- const basePathWithoutTrailingSlash = normalizeBasePath(process.env.CLIENT_BASE_PATH || '/');
224
- const publicPath = isDev ? '/' : process.env.ASSETS_CDN_PATH;
225
-
226
- const baseConfig = createRecommendRspackConfig({
227
- isDev,
228
- clientBasePath: basePathWithoutTrailingSlash,
229
- publicPath: publicPath,
230
- });
231
-
232
- return merge(baseConfig, {
233
- entry: { main: './client/src/index.tsx' },
234
- });
235
- });
180
+ module.exports = {
181
+ extends: '@lark-apaas/fullstack-rspack-preset/preset.config.js',
182
+ entry: { main: './client/src/index.tsx' },
183
+ };
236
184
  ```
237
185
 
238
- **现在(8 行):**
239
-
186
+ **或者(defineConfig 方式,6 行):**
240
187
  ```javascript
241
- const path = require('path');
242
188
  const { defineConfig } = require('@lark-apaas/fullstack-rspack-preset');
243
189
 
244
190
  module.exports = defineConfig({
245
- entry: {
246
- main: './client/src/index.tsx',
247
- },
248
- resolve: {
249
- alias: {
250
- '@': path.resolve(__dirname, 'client/src'),
251
- },
252
- },
191
+ entry: { main: './client/src/index.tsx' },
253
192
  });
254
193
  ```
255
194
 
256
195
  **迁移步骤:**
257
-
258
- 1. 修改导入:`createRecommendRspackConfig` → `defineConfig`
196
+ 1. 选择使用方式(extends 或 defineConfig)
259
197
  2. 删除手动环境变量处理代码
260
- 3. 删除 `defineConfig`、`normalizeBasePath`、`merge` 等导入
261
- 4. 只保留覆盖配置(entry、resolve 等)
262
- 5. 确保 `.env` 文件包含必要的环境变量
198
+ 3. 删除 `normalizeBasePath`、`merge` 等依赖
199
+ 4. 确保 `.env` 文件包含必要的环境变量
263
200
 
264
201
  ## 常见问题
265
202
 
266
- ### Q: 如何禁用某个功能?
267
-
268
- 通过环境变量控制:
269
-
270
- ```bash
271
- # 禁用路由解析
272
- NEED_ROUTES=false
273
-
274
- # 禁用 React Refresh
275
- ENABLE_REACT_REFRESH=false
276
- ```
203
+ ### Q: 如何自定义 webpack plugins?
277
204
 
278
- ### Q: 如何自定义 DefinePlugin 变量?
279
-
280
- 直接在 `overrides` 中添加:
205
+ 在配置中直接添加:
281
206
 
282
207
  ```javascript
283
- const { defineConfig } = require('@lark-apaas/fullstack-rspack-preset');
284
208
  const rspack = require('@rspack/core');
285
209
 
286
- module.exports = defineConfig({
210
+ module.exports = {
211
+ extends: '@lark-apaas/fullstack-rspack-preset/preset.config.js',
287
212
  plugins: [
288
213
  new rspack.DefinePlugin({
289
- 'process.env.CUSTOM_VAR': JSON.stringify('custom-value'),
214
+ 'process.env.CUSTOM_VAR': JSON.stringify('value'),
290
215
  }),
291
216
  ],
292
- });
217
+ };
218
+ ```
219
+
220
+ ### Q: 如何禁用某个功能?
221
+
222
+ 通过环境变量:
223
+
224
+ ```bash
225
+ # .env
226
+ NEED_ROUTES=false # 禁用路由解析
227
+ ENABLE_REACT_REFRESH=false # 禁用 React Refresh
293
228
  ```
294
229
 
295
- ### Q: 如何使用生产环境 CDN?
230
+ ### Q: 生产环境如何使用 CDN?
296
231
 
297
232
  设置环境变量:
298
233
 
@@ -301,30 +236,39 @@ NODE_ENV=production
301
236
  ASSETS_CDN_PATH=https://cdn.example.com
302
237
  ```
303
238
 
304
- ### Q: 为什么 DefinePlugin 没有生效?
239
+ ## API 文档
240
+
241
+ ### defineConfig
242
+
243
+ ```typescript
244
+ function defineConfig(
245
+ overrides?: Partial<Configuration>
246
+ ): Configuration;
247
+ ```
248
+
249
+ **参数:**
250
+ - `overrides` - Rspack 配置对象,会与默认配置深度合并
305
251
 
306
- 检查:
307
- 1. `.env` 文件是否存在
308
- 2. 环境变量名是否正确
309
- 3. `process.env.runtimeMode` 缺少 `JSON.stringify`(已知问题,待修复)
252
+ **返回:**
253
+ - 完整的 Rspack 配置对象
310
254
 
311
- ## 版本历史
255
+ ### createRecommendRspackConfig (旧版本 API)
312
256
 
313
- ### 0.1.2-alpha.3
314
- - ✨ 新增 `defineConfig` API(对齐 rspack 官方)
315
- - ✨ 保持 `createFullstackRspackConfig` 向后兼容
316
- - 🐛 修复 .env 异步加载问题
257
+ ```typescript
258
+ function createRecommendRspackConfig(
259
+ options: CreateRecommendRspackConfigOptions
260
+ ): Configuration;
317
261
 
318
- ### 0.1.2-alpha.2
319
- - ✨ 新增 `createFullstackRspackConfig` 简化 API
320
- - ✨ 自动加载 `.env` 环境变量
321
- - ✨ 支持环境变量驱动配置
322
- - 🐛 修复 `@rspack/core` 版本冲突
323
- - 🐛 修复 Slardar 插件在 npm link 环境下的问题
324
- - 📝 完善文档和示例
262
+ interface CreateRecommendRspackConfigOptions {
263
+ isDev?: boolean;
264
+ enableReactRefresh?: boolean;
265
+ needRoutes?: boolean;
266
+ clientBasePath?: string;
267
+ publicPath?: string;
268
+ }
269
+ ```
325
270
 
326
- ### 0.1.0
327
- - 🎉 初始版本
271
+ > ⚠️ 建议迁移到 `defineConfig` 或 extends 方式
328
272
 
329
273
  ## License
330
274
 
@@ -124,21 +124,51 @@ function removeAllChildren(element, skip) {
124
124
  element.removeChild(childList[i]);
125
125
  }
126
126
  }
127
+ /**
128
+ * 降级复制方案(兼容旧浏览器)
129
+ * @param text 要复制的文本
130
+ * @returns boolean 复制是否成功
131
+ */
132
+ function fallbackCopyToClipboard(text) {
133
+ try {
134
+ // 创建临时的 textarea 元素
135
+ const textArea = document.createElement('textarea');
136
+ textArea.value = text;
137
+ // 设置样式,使其不可见
138
+ textArea.style.position = 'fixed';
139
+ textArea.style.left = '-999999px';
140
+ textArea.style.top = '-999999px';
141
+ textArea.setAttribute('readonly', '');
142
+ // 添加到 DOM
143
+ document.body.appendChild(textArea);
144
+ // 选中文本
145
+ textArea.focus();
146
+ textArea.select();
147
+ // 执行复制命令
148
+ const successful = document.execCommand('copy');
149
+ // 清理:移除临时元素
150
+ document.body.removeChild(textArea);
151
+ return successful;
152
+ }
153
+ catch (error) {
154
+ console.error('降级复制方案失败:', error);
155
+ return false;
156
+ }
157
+ }
127
158
  async function copyToClipboard(text) {
128
- // 优先使用现代的 Clipboard API
129
- if (navigator.clipboard && window.isSecureContext) {
130
- try {
159
+ try {
160
+ // 优先使用现代的 Clipboard API
161
+ if (navigator.clipboard && window.isSecureContext) {
131
162
  await navigator.clipboard.writeText(text);
132
163
  return true;
133
164
  }
134
- catch (error) {
135
- // 权限被拒绝或其他错误,降级到 execCommand
136
- console.warn('Clipboard API 失败,降级到 execCommand:', error);
137
- return fallbackCopyToClipboard(text);
138
- }
165
+ // 降级方案:使用传统的 execCommand 方法
166
+ return fallbackCopyToClipboard(text);
167
+ }
168
+ catch (error) {
169
+ // 执行navigator.clipboard.writeText失败时,降级方案
170
+ return fallbackCopyToClipboard(text);
139
171
  }
140
- // 降级方案:使用传统的 execCommand 方法
141
- return fallbackCopyToClipboard(text);
142
172
  }
143
173
  // 获取父窗口 origin
144
174
  function getPreviewParentOrigin() {
@@ -168,6 +198,10 @@ function render() {
168
198
  const origin = targetOrigin || getPreviewParentOrigin();
169
199
  window.parent.postMessage(message, origin);
170
200
  };
201
+ // 通知前端,渲染错误页面已准备就绪
202
+ sendPostMessage({
203
+ type: 'PreviewReady'
204
+ });
171
205
  // 通知主应用存在自定义 overlay
172
206
  sendPostMessage({
173
207
  type: 'app-features',
package/lib/preset.js CHANGED
@@ -128,7 +128,6 @@ function createRecommendRspackConfig(options) {
128
128
  'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
129
129
  'process.env.runtimeMode': JSON.stringify('fullstack'),
130
130
  'process.env.CLIENT_BASE_PATH': JSON.stringify(clientBasePath),
131
- // FIXME:安全漏洞,会读取到服务路径,不应该在客户端代码中使用
132
131
  'process.env.CWD': JSON.stringify(''),
133
132
  // 解决 window 未定义问题
134
133
  'typeof window': JSON.stringify('object'),
@@ -316,7 +315,7 @@ function createRecommendRspackConfig(options) {
316
315
  output: {
317
316
  publicPath,
318
317
  path: path_1.default.resolve(rootDir, 'dist/client'),
319
- clean: true,
318
+ clean: false,
320
319
  globalObject: 'this',
321
320
  },
322
321
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-rspack-preset",
3
- "version": "0.1.2-alpha.7",
3
+ "version": "1.0.0",
4
4
  "files": [
5
5
  "lib",
6
6
  "preset.config.js"