Skip to content

Commit 2059b11

Browse files
authored
feat(fe): add support for TypeScript, Less, and SCSS; enhance npm component handling
* fix(fe): add null checks for item in serializeProps function to prevent errors * feat(compiler): add support for TypeScript, Less, and SCSS; enhance npm component handling * refactor(compiler): lint fix * feat(compiler): add support for TypeScript, Less, and SCSS; enhance npm component handling * refactor(compiler): lint fix * fix(compiler): remove fallback for moduleId in enhanceCSS function * feat(fe): add system information retrieval to api * fix(fe): simplify condition in serializeProps function * fe(dmcc): restructure wxs processing logic and enhance dependency handling * fix(fe): remove condition in runtime data initialization for update props by method * feat(fe): enhance component relationship management with immediate bidirectional relation establishment * feat(compiler): enhance wxs processing by converting getRegExp to regex literal and updating getDate to new Date * feat(fe): add comprehensive tests for selectComponent and selectAllComponents methods in page and component instances * refactor(fe): simplify router push method and enhance component/page initialization * feat(compiler): add support for ES6 import statements and transform to CommonJS * refactor(compiler): remove console logs from npm package build process * fix(compiler): implement caching mechanism for template compilation results * fix(fe): set default value to null for undefined properties in component data initialization * feat(compiler): add :host selector processing and corresponding tests * feat(fe): implement createIntersectionObserver method in Component class and update Page class id assignment * feat(fe): add RootPortal component * feat(compiler): enhance template and wxs processing in toCompileTemplate function * feat(fe): implement createShadowDOM function in Wrapper component and update template structure * feat(compiler): improve getRegExp function handling by converting string literals to regex literals * feat(compiler): add processWxsContent function and corresponding tests for wxs content handling * fix(fe): update Wrapper component template to use wrapper-component and clean up shadow DOM creation * feat(compiler): enhance getRegExp handling to convert variable parameters to new RegExp calls and update tests accordingly * feat(compiler): enhance getAbsolutePath and toCompileTemplate functions for improved path handling and node management * feat(fe): update Wrapper component to dynamically generate component names based on path and enhance template structure * feat(compiler): implement page view compilation with wxs module handling and caching mechanism * fix(compiler): enhance parseKeyExpression function to support custom index names and update related tests * feat(fe): update external class handling in parseExternalClass function to support dynamic class names from module props * fix(fe): update placeholderStyle handling in Input and Textarea components to ensure proper object type checks * feat(fe): implement groupSetData method for batch updates, allowing multiple setData calls to be merged and sent in a single update * feat(compiler): enhance wxs module handling with registration, path mapping, and dependency collection * fix(component): correct data filtering logic in ComponentModule constructor to ensure data is set properly * fix(fe): optimize observer execution in Component class to ensure all observers are called after data updates * feat(fe): change shadow DOM mode from 'open' to 'closed' for improved encapsulation * fix(fe): update data handling in watch method to merge newProps into data object * fix(fe): improve ancestor checking logic in Runtime class to handle NodeList and ensure target elements are valid * fix(fe): correct data filtering logic in filterData function to handle Date objects and improve key checks * fix(fe): refactor watch method in Runtime class to include immediate execution for newProps updates * fix(fe): correct logic for setting component ID to ensure it is assigned only when not already defined
1 parent 6cac75f commit 2059b11

48 files changed

Lines changed: 6494 additions & 224 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fe/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"devDependencies": {
2828
"@antfu/eslint-config": "^4.14.1",
29+
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
2930
"@eslint/eslintrc": "^3.3.1",
3031
"@vitest/coverage-v8": "^3.2.3",
3132
"archiver": "^7.0.1",

fe/packages/compiler/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,59 @@ dmcc build --no-app-id-dir
9898

9999
```txt
100100
app.js, index.js -> logic.js (逻辑文件)
101+
app.ts, index.ts -> logic.js (TypeScript 逻辑文件)
101102
index.wxml -> view.js (视图文件)
102103
app.wxss, index.wxss -> style.css (样式文件)
104+
app.less, index.less -> style.css (Less 样式文件)
105+
app.scss, index.scss -> style.css (SCSS 样式文件)
106+
app.sass, index.sass -> style.css (Sass 样式文件)
103107
app.json, index.json -> config.json (配置文件)
108+
miniprogram_npm/ -> npm包构建 (npm组件支持)
104109
```
105110

111+
### TypeScript、Less 和 SCSS 支持
112+
113+
编译器现已支持现代前端开发工具:
114+
115+
-**TypeScript 支持**: `.ts` 文件自动编译为 JavaScript
116+
-**ES6 Import 语句**: 支持相对路径、npm 包和绝对路径导入
117+
-**Less 支持**: `.less` 文件编译为 CSS,支持变量、mixin 和嵌套
118+
-**SCSS/Sass 支持**: `.scss``.sass` 文件编译为 CSS
119+
-**错误处理**: 编译失败时自动回退,不中断构建流程
120+
-**向后兼容**: 完全兼容现有的 `.js``.wxss` 文件
121+
122+
#### 支持的文件类型
123+
124+
**逻辑文件查找顺序**: `.js``.ts`
125+
**样式文件查找顺序**: `.wxss``.ddss``.less``.scss``.sass`
126+
127+
详细使用说明请参考:[TypeScript、Less 和 SCSS 支持文档](./docs/typescript-less-scss-support.md)
128+
129+
### npm 组件支持
130+
131+
编译器现已支持微信小程序的 npm 包功能,遵循微信官方的 npm 支持规范:
132+
133+
- ✅ 支持 `miniprogram_npm` 目录中的组件解析
134+
- ✅ 按照微信小程序寻址顺序查找组件
135+
- ✅ 自动构建和复制 npm 包文件
136+
- ✅ 支持组件依赖关系处理
137+
- ✅ 缓存机制提升编译性能
138+
- ✅ 兼容现有的相对路径组件引用
139+
140+
#### npm 组件使用示例
141+
142+
```json
143+
// pages/index/index.json
144+
{
145+
"usingComponents": {
146+
"lib-button": "lib-weapp/button",
147+
"custom-component": "./components/custom"
148+
}
149+
}
150+
```
151+
152+
详细使用说明请参考:[npm 支持文档](./docs/npm-support.md)
153+
106154
### 编译产物目录结构
107155

108156
编译后,默认会在目标目录生成以小程序 id 命名的文件夹,项目结构如下:
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2+
import fs from 'node:fs'
3+
import path from 'node:path'
4+
import os from 'node:os'
5+
6+
describe('全局组件 wxs 问题修复', () => {
7+
let tempDir
8+
let originalWorkPath
9+
let originalTargetPath
10+
11+
beforeEach(() => {
12+
// 保存原始环境变量
13+
originalWorkPath = process.env.WORK_PATH
14+
originalTargetPath = process.env.TARGET_PATH
15+
16+
// 创建临时测试目录
17+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'global-wxs-test-'))
18+
})
19+
20+
afterEach(() => {
21+
// 恢复原始环境变量
22+
if (originalWorkPath) {
23+
process.env.WORK_PATH = originalWorkPath
24+
} else {
25+
delete process.env.WORK_PATH
26+
}
27+
28+
if (originalTargetPath) {
29+
process.env.TARGET_PATH = originalTargetPath
30+
} else {
31+
delete process.env.TARGET_PATH
32+
}
33+
34+
// 清理临时目录
35+
if (fs.existsSync(tempDir)) {
36+
fs.rmSync(tempDir, { recursive: true, force: true })
37+
}
38+
})
39+
40+
it('应该在所有使用全局组件的页面中包含 wxs 代码', async () => {
41+
// 创建基本的项目结构
42+
const appJsonPath = path.join(tempDir, 'app.json')
43+
fs.writeFileSync(appJsonPath, JSON.stringify({
44+
pages: ['pages/index/index', 'pages/about/about'],
45+
usingComponents: {
46+
'global-component': './components/global-component/index'
47+
}
48+
}))
49+
50+
const projectConfigPath = path.join(tempDir, 'project.config.json')
51+
fs.writeFileSync(projectConfigPath, JSON.stringify({
52+
appid: 'test-app-id'
53+
}))
54+
55+
// 创建页面配置
56+
const indexPageDir = path.join(tempDir, 'pages/index')
57+
fs.mkdirSync(indexPageDir, { recursive: true })
58+
59+
const indexPageJsonPath = path.join(indexPageDir, 'index.json')
60+
fs.writeFileSync(indexPageJsonPath, JSON.stringify({
61+
navigationBarTitleText: '首页'
62+
}))
63+
64+
const indexPageWxmlPath = path.join(indexPageDir, 'index.wxml')
65+
fs.writeFileSync(indexPageWxmlPath, `
66+
<view>
67+
<global-component />
68+
</view>
69+
`)
70+
71+
const aboutPageDir = path.join(tempDir, 'pages/about')
72+
fs.mkdirSync(aboutPageDir, { recursive: true })
73+
74+
const aboutPageJsonPath = path.join(aboutPageDir, 'about.json')
75+
fs.writeFileSync(aboutPageJsonPath, JSON.stringify({
76+
navigationBarTitleText: '关于'
77+
}))
78+
79+
const aboutPageWxmlPath = path.join(aboutPageDir, 'about.wxml')
80+
fs.writeFileSync(aboutPageWxmlPath, `
81+
<view>
82+
<global-component />
83+
</view>
84+
`)
85+
86+
// 创建全局组件
87+
const globalComponentDir = path.join(tempDir, 'components/global-component')
88+
fs.mkdirSync(globalComponentDir, { recursive: true })
89+
90+
const globalComponentJsonPath = path.join(globalComponentDir, 'index.json')
91+
fs.writeFileSync(globalComponentJsonPath, JSON.stringify({
92+
component: true
93+
}))
94+
95+
const globalComponentWxmlPath = path.join(globalComponentDir, 'index.wxml')
96+
fs.writeFileSync(globalComponentWxmlPath, `
97+
<wxs module="utils">
98+
function formatText(text) {
99+
return text + ' from wxs'
100+
}
101+
module.exports = {
102+
formatText: formatText
103+
}
104+
</wxs>
105+
<view>
106+
<text>{{utils.formatText('Hello')}}</text>
107+
</view>
108+
`)
109+
110+
// 设置环境变量
111+
process.env.WORK_PATH = tempDir
112+
113+
// 创建输出目录
114+
const outputDir = path.join(tempDir, 'dist')
115+
fs.mkdirSync(outputDir, { recursive: true })
116+
process.env.TARGET_PATH = outputDir
117+
118+
// 清理模块缓存
119+
const envModulePath = path.resolve(__dirname, '../src/env.js')
120+
delete require.cache[envModulePath]
121+
122+
// 重新导入并初始化环境
123+
const { storeInfo, getPages, getTargetPath } = await import('../src/env.js')
124+
125+
// 执行配置收集
126+
storeInfo(tempDir)
127+
128+
// 获取页面信息
129+
const pagesInfo = getPages()
130+
131+
// 验证全局组件被正确合并到页面配置中
132+
expect(pagesInfo.mainPages).toHaveLength(2)
133+
expect(pagesInfo.mainPages[0].usingComponents).toHaveProperty('global-component')
134+
expect(pagesInfo.mainPages[1].usingComponents).toHaveProperty('global-component')
135+
136+
// 模拟编译过程
137+
const { compileML } = await import('../src/core/view-compiler.js')
138+
139+
// 编译页面
140+
const progress = { completedTasks: 0 }
141+
await compileML(pagesInfo.mainPages, null, progress)
142+
143+
// 验证编译结果
144+
const mainDir = path.join(outputDir, 'main')
145+
expect(fs.existsSync(mainDir)).toBe(true)
146+
147+
const indexOutputPath = path.join(mainDir, 'pages_index_index.js')
148+
const aboutOutputPath = path.join(mainDir, 'pages_about_about.js')
149+
150+
expect(fs.existsSync(indexOutputPath)).toBe(true)
151+
expect(fs.existsSync(aboutOutputPath)).toBe(true)
152+
153+
// 读取编译后的文件内容
154+
const indexContent = fs.readFileSync(indexOutputPath, 'utf-8')
155+
const aboutContent = fs.readFileSync(aboutOutputPath, 'utf-8')
156+
157+
// 验证两个页面都包含 wxs 代码的核心功能
158+
expect(indexContent).toContain('formatText')
159+
expect(aboutContent).toContain('formatText')
160+
161+
// 验证两个页面都包含 utils 模块定义
162+
expect(indexContent).toContain('"utils"')
163+
expect(aboutContent).toContain('"utils"')
164+
165+
// 验证两个页面都包含 wxs 模块的完整定义
166+
expect(indexContent).toContain('from wxs')
167+
expect(aboutContent).toContain('from wxs')
168+
169+
// 验证两个页面都包含压缩后的 exports(可能是 t.exports 或 module.exports)
170+
expect(indexContent).toMatch(/[t|module]\.exports/)
171+
expect(aboutContent).toMatch(/[t|module]\.exports/)
172+
173+
// 验证两个页面都包含全局组件的模块定义
174+
expect(indexContent).toContain('/components/global-component/index')
175+
expect(aboutContent).toContain('/components/global-component/index')
176+
177+
console.log('✅ 全局组件 wxs 问题修复验证通过')
178+
console.log('首页文件大小:', indexContent.length, '字节')
179+
console.log('关于页面文件大小:', aboutContent.length, '字节')
180+
181+
// 验证两个页面的内容长度相似(都包含了相同的 wxs 代码)
182+
const sizeDifference = Math.abs(indexContent.length - aboutContent.length)
183+
expect(sizeDifference).toBeLessThan(100) // 允许一些小的差异
184+
})
185+
})

0 commit comments

Comments
 (0)