尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WePY 2 组件化小程序框架指南:类 Vue 开发体验、编译原理与上手指南

WePY 2 组件化小程序框架指南:类 Vue 开发体验、编译原理与上手指南 WePY 2 组件化小程序框架指南类 Vue 开发体验、编译原理与上手指南【免费下载链接】wepy小程序组件化开发框架 - 已归档项目地址: https://gitcode.com/gh_mirrors/we/wepyWePY读音 /wepi/是腾讯开源的一款微信小程序组件化开发框架核心思路是通过预编译把.wpy单文件组件转换为微信小程序原生代码让开发者用类 Vue 的语法、ES2015 的能力和自定义组件体系来编写小程序。本文以 README_EN.md 为骨架结合本仓库 packages/ 下的源码实现完整介绍 WePY 2beta的核心特性、单文件组件写法、CLI 使用流程以及框架编译 运行时的底层原理读完即可上手初始化项目并理解其工作方式。归档状态提示项目仓库首页顶部已明确标注This project has been archived已归档。由于微信小程序生态的演进该项目已停止活跃维护WePY 的代码不再作为新项目的推荐参考。本文仅面向历史技术研究、已有项目维护与源码学习场景新项目建议采用更现代的小程序解决方案。一、WePY 是什么预编译与组件化的核心理念WePY 的口号是 componentization of small programs小程序组件化。与当时直接手写原生app.js / page.js / component.js / wxml / wxss / json的常规做法不同WePY 选择了编译期转换路线开发者以 Vue 风格的 SFCSingle File Component形式编写.wpy文件框架在构建阶段将其预编译为微信开发者工具能直接运行的wxml / wxss / js / json产物。从源码可以印证这一预编译定位。CLI 的入口 packages/cli/index.js 直接导出./core/compile.js而 编译核心实现 中的run()方法串起了完整流程run() { return this.init().then(() this.start()); }其中 start() 会先解析 App 入口的wpy文件读取其config中声明的pages、subPackages、usingComponents、自定义tabBar等配置然后逐一编译页面与组件output() 则把每个 SFC 块的产物按映射写出const outputMap { script: js, styles: wxss, config: json, template: wxml };也就是说一个.wpy文件会被拆成.js、.wxss、.json、.wxml四个原生文件输出到weapp/目录这正是 WePY pre-compiling 理念的源码级证据。同时WePY 也在持续吸收前端优化工具与框架的设计思想README 原文表述为 drawing heavily on the design concepts and ideas of some front-end optimization tools and frameworks例如响应式观察者、指令系统、编译器插件化等都属于这一思路的产物。二、核心特性总览README 中明确列出了 WePY 2 的 8 项核心特性逐条展开如下特性说明仓库佐证类 Vue 的开发风格wepy.page/wepy.component/wepy.app注册 APIdata/computed/watch/methods等选项式写法packages/core/weapp/apis/index.js自定义组件开发SFC 组件 config.usingComponents声明引用packages/cli/core/compile.js支持引入 NPM 包编译期通过 enhanced-resolve 解析依赖vendor 独立打包packages/cli/core/compile.js#L59-L126支持 Promise运行时内置响应式与异步调度next-tick、schedulerpackages/core/weapp/util/next-tick.js支持 ES2015如 Async Functions通过 Babel 编译器处理配套compiler-babel包packages/compiler-babel/index.js多编译器支持Less / Sass / Stylus / PostCSS / Babel / TypeScript / Pug按需加载wepy/compiler-*packages/compiler-less、packages/compiler-sass、packages/compiler-stylus、packages/compiler-postcss、packages/compiler-typescript多种插件处理文件/图片压缩、内容替换等插件即函数packages/cli/core/init/plugin.js、packages/plugin-uglifyjs、packages/plugin-define支持 Sourcemap、ESLint 等eslint、cliLogs、noCache等 CLI 配置项packages/cli/core/parseOptions.js#L4-L27小程序细节优化事件优化$emit/$trigger、请求队列、渲染 nextTick 调度packages/core/weapp/class/WepyComponent.js2.1 类 Vue 开发风格注册 API 与响应式系统WePY 的全局对象由 packages/core/weapp/wepy.js 构建通过initGlobalAPI挂载了全套注册与工具方法。查看 packages/core/weapp/apis/index.js 可见wepy.use use; // 安装插件 wepy.mixin mixin; // 全局混入 wepy.set / wepy.delete // 响应式新增/删除属性 wepy.observe // 响应式观察 wepy.nextTick // 渲染调度 wepy.app / wepy.page / wepy.component // 三类组件注册入口其中wepy.page与wepy.component的实现位于 packages/core/weapp/native/index.js。以 page.js 为例注册时会依次执行patchMixins混入合并、patchProps属性声明、patchMethods方法、patchData数据、patchLifecycle生命周期最终调用微信原生的Component(pageConfig)生成小程序组件而 app.js 则通过patchMixins patchAppLifecycle后调用原生App(appConfig)。组件的类实现 WepyComponent 提供了$watch可传数组或带handler的对象支持immediate、$forceUpdate、$emit、$trigger转发到$wx.triggerEvent与父组件通信以及$nextTickWepyConstructor 则完成data初始化、watch初始化与computed初始化——这三者构成了类 Vue 响应式开发的运行时基础。2.2 自定义组件与 NPM 依赖解析在编译期compile.js 使用 webpack 同源的enhanced-resolve创建 normal / context 两套 resolver并将.js、.ts、.json、.node、.wxs、.wpy全部纳入扩展名解析范围。组件间依赖会被递归收集buildComps会遍历每个组件config.parsed.components区分 WePY 组件.wpy与原生组件.js逐个编译后统一打包 vendor 与静态资源compile.js#L289-L349。README 特性中的 Support for introducing NPM packages 正是由这套解析 vendor 打包机制支撑。2.3 多编译器与多插件生态编译器WePY 2 把样式、脚本编译器做成独立 npm 包编译时按需加载。查看 packages/cli/core/init/compiler.js 可知其加载约定let moduleName wepy/compiler-${c}; // 通过 resolver 解析后 require再以 compilers[c] 作为配置调用即compilers配置中的每个键如less、sass、babel、typescript都会映射到wepy/compiler-xxx包。本仓库中即包含 compiler-less、compiler-sass、compiler-stylus、compiler-postcss、compiler-babel、compiler-typescript 六个编译器包每个都自带完整的 fixtures 与测试用例。插件插件初始化见 packages/cli/core/init/plugin.js。框架会先挂载一批内置系统插件scriptDepFix、scriptInjection、template/parse、template/attrs、template/directives、errorHandler等再校验并执行用户在wepy.config.js中配置的自定义插件要求插件必须是一个函数。仓库中配套了 plugin-define编译期内容替换/宏定义、plugin-eslint代码检查、plugin-uglifyjs压缩等示例插件以及 use-promisify、use-intercept 两个运行时增强插件。三、单文件组件 Demo 逐段解析README 给出了一个完整的.wpy示例这里原样继承并逐块拆解。这是理解 WePY 开发风格最直接的入口style langless color: #4D926F; .num { color: color; } /style template div classcontainer div classnum tapnum {{num}} /div custom-component/custom-component vendor-component/vendor-component div{{text}}/div input v-modeltext/ /div /template config { usingComponents: { customComponent: /components/customComponent, vendorComponent: module:vendorComponent } } /config script import wepy from wepy/core; wepy.page({ data: { num: 0, text: Hello World, }, }); /script一个.wpy文件由四个块组成顺序与语义如下块作用说明style样式支持lang属性切换编译器如less对应输出为.wxsstemplate模板类 HTML 的 WXML 语法支持tap事件绑定、{{}}插值、v-model指令对应输出.wxmlconfig组件配置JSON 格式声明usingComponents等对应输出.jsonscript脚本通过import wepy from wepy/core引入运行时用wepy.page()注册页面对应输出.js3.1 style 块Less 编译style langless声明后编译期会走wepy-compiler-less钩子对应 packages/compiler-less/index.js。仓库中该包的 test/fixtures/less 下提供了变量、导入、守卫、懒求值、选择器、列表等一整套 Less 特性测试样例验证其编译能力。同理lang换成sass/stylus/postcss即可切换对应编译器。3.2 template 块事件、插值与指令tapnum事件绑定前缀对应原生bindtap在 packages/cli/core/plugins/template/directives 中由v-on指令转换实现v-on.js对应的转换断言用例可在 packages/cli/test/core/fixtures/template/assert/v-on 中查看{{num}}、{{text}}双花括号插值编译为 WXML 文本节点v-modeltext双向绑定指令由 model.js 实现自定义标签custom-component、vendor-component在config.usingComponents中声明后即可在模板中直接使用。3.3 config 块组件引用与路径别名{ usingComponents: { customComponent: /components/customComponent, vendorComponent: module:vendorComponent } }这里的路径规则值得注意/components/customComponent为项目src目录别名指向本地自定义组件module:vendorComponentmodule:前缀表示该组件来自 node_modulesNPM 包编译时会经 vendor 解析与打包机制处理对应 compile.js 的getModuleTarget将 node_modules 依赖输出到weapp/vendor/目录。3.4 script 块页面注册import wepy from wepy/core; wepy.page({ data: { num: 0, text: Hello World, }, });wepy/core即本仓库的 packages/core 包入口为 packages/core/index.js。wepy.page内部会做 mixins / props / methods / data / lifecycle 的合并与补丁最终调用原生Component()详见上文 2.1 节。在选项对象中还可以继续补充computed、watch、methods、onLoad等生命周期字段运行时分别由 init/computed.js、init/watch.js、init/lifecycle.js 处理。四、快速上手从初始化到真机预览README 的 Usage 章节给出了一套完整的命令行流程这里完整继承并补充说明4.1 安装升级WePY 命令行工具npm install wepy/clinext -gnext标签对应 WePY 2beta版本线。本仓库中的 CLI 源码位于 packages/cli其入口 packages/cli/index.js 最终导出编译核心模块。4.2 使用模板初始化项目wepy init standard myprojectwepy init会基于standard模板在当前目录生成名为myproject的项目骨架模板拉取与交互逻辑可参见 packages/cli/core/init 下的 compiler / parser 实现。4.3 安装依赖cd myproject npm install项目依赖中应包含wepy/core运行时、所需wepy/compiler-*编译器与wepy/cli本地版本。4.4 监听模式构建wepy build --watch--watch开启监听模式构建完成后 CLI 会持续监听src目录见 compile.js 的 watch()底层使用chokidar监听文件变化并以300ms 防抖合并连续改动单文件变化时走partialBuild/weappBuild增量编译多文件同时变化则触发全量start()重建。构建产物默认输出到weapp/目录见下文的output配置项。4.5 导入微信开发者工具在微信开发者工具中新建项目选择本地项目根目录即myproject工具会自动识别并导入weapp/下的编译产物与project.config.json配置随后即可在模拟器/真机中预览调试。需要说明由于仓库已归档wepy/clinext及其配套包在 npm 上的可安装性以实际发布状态为准安装失败时建议参考本仓库 packages 目录下的源码与package.json自行构建使用。4.6 工程配置wepy.config.js虽然 README 未展开wepy.config.js但它承载了上面所有 CLI 行为的具体配置。从 packages/cli/core/parseOptions.js#L4-L27 可以看到全部默认配置项const DEFAULT_OPTIONS { entry: { type: String, default: app }, // 应用入口名不含扩展名 src: { type: String, default: src }, // 源码目录 target: { type: String, default: weapp }, // 编译目标weapp static: { type: [String, Array], default: static }, // 静态资源目录可多个 output: { type: String, default: weapp }, // 输出目录 platform: { type: String }, // 目标平台 wpyExt: { type: String, default: .wpy }, // SFC 文件扩展名 eslint: { type: Boolean, default: true }, // 是否启用 ESLint cliLogs: { type: Boolean, default: false }, // 是否输出 CLI 日志 watch: { type: Boolean, default: false }, // 是否监听 watchOption: { type: Object }, // chokidar 监听选项 noCache: { type: Boolean, default: false }, // 是否禁用编译缓存 resolve: { type: Object, default: {} }, // 模块解析配置 compilers: { type: Object }, // 编译器配置如 less、babel 等 plugins: { type: Array, default: [] }, // 插件函数列表 appConfig: { type: Object }, // 应用级配置 appConfig.noPromiseAPI: { type: Array, default: [] } };一个真实的配置示例可参考仓库内 packages/plugin-define/test/fixtures/wepy.config.jsmodule.exports { plugins: [ DefinePlugin({ BASE_URL: JSON.stringify(http://www.bar.com) }), DefinePlugin({ process.env.NODE_ENV: JSON.stringify(development), typeof window: JSON.stringify(undefined), }) ], }可以看到插件以函数数组形式传入编译期对源码做内容替换这正是 README 特性中内容替换类插件处理的落地示例。五、从源码理解编译流水线结合前面的分析WePY 2 的完整构建流水线可以归纳为如下阶段对应 compile.js 的 hook 设计解析入口wepy-parser-wpy解析app.wpy读取config中的pages/subPackages/usingComponents/tabBar.custom收集任务为每个页面与组件创建解析任务.wpy走 SFC 解析原生.js组件走wepy-parser-componentsubPackages中暂不支持independent独立分包源码中有显式告警与EXIT处理见 compile.js#L213-L227递归构建组件buildComps递归收集并编译全部组件依赖随后按output-app、output-pages、output-components、output-vendor、output-assets、output-static顺序输出产物块级编译applyCompiler依据style的lang找到wepy-compiler-{lang}钩子执行编译compile.js#L493-L520且带依赖的样式文件会跳过缓存避免依赖变更未生效产物写出SFC 四块内容分别映射为.js / .wxss / .json / .wxml写出到output目录compile.js#L563-L590。整个编译过程构建在Hook事件系统之上packages/cli/core/hook.js框架内置插件与用户插件均通过注册钩子参与各阶段这也是 WePY 可扩展性的根基。六、谁在用 WePY历史案例README 中列出了一批基于 WePY 开发的微信小程序案例其中标注开源的项目在原始 README 中附有仓库链接此处仅保留名称腾讯疫苗查询小程序、腾讯翻译君小程序、腾讯地图小程序、玩转故宫小程序、手机充值、手机余额查询、手机流量充值优惠、友福图书馆开源、素洁商城开源、NewsLite开源、西安找拼车开源、深大的树洞开源、求知微阅读开源、给你的 iPhone X 换个发型、天天跟我买、坚橙、群脱单、米淘联盟、帮助圈、众安保险福利、阅邻二手书、趣店招聘、满熊阅读开源含微信/支付宝双端、育儿柚道、平行进口报价内参、GitHub 掘金版、班级群管、鲜花说小店、逛人备忘、英语助手君、花花百科、独角兽公司、爱羽客羽毛球、斑马小店、小小羽球、培恩医学、农资优选、公务员朝夕刷题、七弦琴小助手、七弦琴大数据、爽到家小程序、应用全球排行开源、we 川大开源、聊会儿、诗词墨客开源、南京邮电大学开源……这批案例覆盖工具、内容、电商、社交、校园等多种场景一定程度上反映了 WePY 在 2017—2020 年前后的小程序生态中的普及度。七、贡献与交流历史信息微信交流群README 说明 WePY 交流群当时已达 500 人上限需添加gcaufy_helper好友并回复验证语 wepy 后按指引入群原文档附有群二维码此处不展开。贡献方式欢迎通过提交 Issue 或 Pull Request 的方式参与改进详见 CONTRIBUTING.md同时 README 提到腾讯开源激励计划鼓励开发者参与贡献。文档与更新记录README 原文链接指向在线文档站与 Changelog 页面外部站点此处不展开仓库内的更新记录见根目录 CHANGELOG.md 及 packages/cli/CHANGELOG.md、packages/core/CHANGELOG.md 等各子包更新日志。开源协议项目基于 MIT 协议开源见 LICENSE。结语如何看待已归档的 WePY作为小程序早期组件化方案的代表WePY 2 的价值主要体现在三方面其一它以预编译 SFC路线证明了类 Vue 语法在小程序领域的可行性其二它的编译器/插件/运行时分层设计本仓库 packages/ 下的cli、core、compiler-*、plugin-*、redux、router、use-*包即是这套架构的完整呈现对理解前端编译工具链很有参考意义其三它为后来者提供了如何把工程化开发体验引入封闭平台的实践样本。对于新项目请遵循归档声明选择更现代的方案对于源码研究与历史项目维护本仓库仍是一份结构清晰、测试完备的参考资料CLI 与模板相关的断言用例可见 packages/cli/test、packages/compiler-less/test 等目录。【免费下载链接】wepy小程序组件化开发框架 - 已归档项目地址: https://gitcode.com/gh_mirrors/we/wepy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表