摘要:深入源碼文件編譯過程是騰訊開源的一款小程序框架,主要通過預編譯的手段,讓開發者采用類風格開發。處理好的最終會寫入文件中,文件存儲路徑會判斷類型是否為。根據上面的流程圖,可以看出所有的文件生成之前都會經過處理。
深入wepy源碼:wpy文件編譯過程
wepy 是騰訊開源的一款小程序框架,主要通過預編譯的手段,讓開發者采用類 Vue 風格開發。 讓我們一起看看, wepy 是如何實現預編譯的。先放上一張官網的流程圖,后面的分析可以參考該圖。
wepy-cli 主要負責 .wpy 文件的編譯,目錄結構如下:
編譯的入口是 src/compile.js 中的 compile() 方法,該方法主要是根據文件類型,執行不同的 compiler ,比如 .wpy 文件會走 compile-wpy.js 下的 compile() 方法。
compile(opath) { ... switch(opath.ext) { case ext: cWpy.compile(opath); break; case ".less": cStyle.compile("less", opath); break; case ".sass": cStyle.compile("sass", opath); break; case ".scss": cStyle.compile("scss", opath); break; case ".js": cScript.compile("babel", null, "js", opath); break; case ".ts": cScript.compile("typescript", null, "ts", opath); break; default: util.output("拷貝", path.join(opath.dir, opath.base)); ... } }.wpy文件拆解
compile-wpy.js 下的 compile() 方法,核心調用了 resolveWpy() 方法。
resolveWpy() 方法,主要是將 .wpy 拆解成 rst 對象,并對其中的 template、script 做一些預處理,然后將 template、 script、 style 三部分移交給不同的 compiler 處理。
生成rst對象通過 xmldom 獲取 xml 對象,然后遍歷節點,拆解為 rst對象。
import {DOMParser} from "xmldom"; export default { createParser (opath) { return new DOMParser({ ... }) }, ... resolveWpy () { let xml = this.createParser(opath).parseFromString(content); } }
rst對象結構如下:
let rst = { moduleId: moduleId, style: [], template: { code: "", src: "", type: "" }, script: { code: "", src: "", type: "" } };
此外,還對 template 做了如下一些預處理:
pug 預編譯
獲取文件中的 import ,放入 rst.template.components 中
獲取 props 和 events ,放入 rst.script.code 中
compile-templatecompile-template.js 中的 compile() 方法,根據 template 的 lang 值,執行不同的 compiler ,比如 wepy-compile-typescript 。編譯完成后,執行 compileXML 方法,做了如下的操作:
updateSlot 方法: 替換 slot 內容
updateBind 方法: 在 {{}} 和 attr 上加入組件的前綴,例如:{{width}} -> {{$ComponentName$width}}
把自定義的標簽、指令轉換為 wxml 語法,例如:
compile-style
依舊先是根據 lang 值,先執行不同的 compiler ,比如 wepy-compile-less 。編譯完成后,執行 src/style-compiler/scope.js 中的 scopedHandler() 方法,處理 scoped 。
import postcss from "postcss"; import scopeId from "./scope-id"; export default function scopedHandler (id, content) { console.log("id is: ", id) console.log("css content is: ", content) return postcss([scopeId(id)]) .process(content) .then(function (result) { console.log("css result is: ", result.css) return result.css }).catch((e) => { return Promise.reject(e) }) }
這里主要是利用 add-id 的 postcss 插件,插件源碼可參考 src/style-compiler/scope-id.js。根據上面的代碼,打印出來的log如下:
最后,會把 requires 由絕對路徑替換為相對路徑,并在 wxss 中引入,最終生成的 wxss 文件為:
@import "./../components/demo.wxss"; Page{background:#F4F5F7} ...compile-script
依舊先是根據 lang 值,執行不同的 compiler。compiler 執行完之后,判斷是否是 npm 包,如果不是,依據不同的 type 類型,加入 wepy 初始化的代碼。
if (type !== "npm") { if (type === "page" || type === "app") { code = code.replace(/exports.defaults*=s*(w+);/ig, function (m, defaultExport) { if (defaultExport === "undefined") { return ""; } if (type === "page") { let pagePath = path.join(path.relative(appPath.dir, opath.dir), opath.name).replace(//ig, "/"); return ` Page(require("wepy").default.$createPage(${defaultExport} , "${pagePath}")); `; } else { appPath = opath; let appConfig = JSON.stringify(config.appConfig || {}); let appCode = ` App(require("wepy").default.$createApp(${defaultExport}, ${appConfig})); `; if (config.cliLogs) { appCode += "require("./_wepylogs.js") "; } return appCode; } }); } }
接下來會執行 resolveDeps() 方法,主要是處理 requires。根據 require 文件的類型,拷貝至對應的目錄,再把 code 中的 require 代碼替換為 相對路徑。
處理好的 code 最終會寫入 js 文件中,文件存儲路徑會判斷類型是否為 npm。
let target; if (type !== "npm") { target = util.getDistPath(opath, "js"); } else { code = this.npmHack(opath, code); target = path.join(npmPath, path.relative(opath.npm.modulePath, path.join(opath.dir, opath.base))); }plugin
根據上面的流程圖,可以看出所有的文件生成之前都會經過 Plugin 處理。先來看一下,compiler 中是如何載入 Plugin 的。
let plg = new loader.PluginHelper(config.plugins, { type: "css", code: allContent, file: target, output (p) { util.output(p.action, p.file); }, done (rst) { util.output("寫入", rst.file); util.writeFile(target, rst.code); } });
其中,config.plugins 就是在 wepy.config.js 中定義的 plugins。讓我們來看一下 PluginHelper 類是如何定義的。
class PluginHelper { constructor (plugins, op) { this.applyPlugin(0, op); return true; } applyPlugin (index, op) { let plg = loadedPlugins[index]; if (!plg) { op.done && op.done(op); } else { op.next = () => { this.applyPlugin(index + 1, op); }; op.catch = () => { op.error && op.error(op); }; if (plg) plg.apply(op); } } }
在有多個插件的時候,不斷的調用 next(),最后執行 done()。
編寫pluginwxss 與 css 相比,拓展了尺寸單位,即引入了 rpx 單位。但是設計童鞋給到的設計稿單位一般為 px,那現在我們就一起來編寫一個可以將 px 轉換為 rpx 的 wepy plugin。
從 PluginHelper 類的定義可以看出,是調用了 plugin 中的 apply() 方法。另外,只有 .wxss 中的 rpx 才需要轉換,所以會加一層判斷,如果不是 wxss 文件,接著執行下一個 plugin。rpx 轉換為 px 的核心是,使用了 postcss-px2units plugin。下面就是設計好的 wepy-plugin-px2units,更多源碼可參考 github 地址。
import postcss from "postcss"; import px2units from "postcss-px2units"; export default class { constructor(c = {}) { const def = { filter: new RegExp(".(wxss)$"), config: {} }; this.setting = Object.assign({}, def, c); } apply (op) { let setting = this.setting; if (!setting.filter.test(op.file)) { op.next(); } else { op.output && op.output({ action: "變更", file: op.file }); let prefixer = postcss([ px2units(this.setting.config) ]); prefixer.process(op.code, { from: op.file }).then((result) => { op.code = result.css; op.next(); }).catch(e => { op.err = e; op.catch(); }); } } }最后
本文分析的源碼以 wepy-cli@1.7.1 版本為準,更多信息可參考 wepy github (即 github 1.7.x 分支)。另外,文中有任何表述不清或不當的地方,歡迎大家批評指正。
本文首發于:https://github.com/yingye/Blo...
歡迎各位關注我的Blog,正文以issue形式呈現,喜歡請點star,訂閱請點watch~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94894.html
摘要:主要解決問題開發模式轉換在原有的小程序的開發模式下進行再次封裝,更貼近于現有框架開發模式。官方代碼獲取應用實例事件處理函數基于的實現支持組件化開發。根組件,一般都是頁面父組件小程序對象子組件列表方法參數返回值說明組件初始化。 小程序框架wepy文檔 Github地址 快速入門 項目創建與使用 安裝wepy 以下安裝都通過npm安裝 安裝 wepy 命令行工具。 npm install ...
摘要:而掃描各個模塊并合并路由表的腳本非常簡單,讀寫文件就了。編寫插件之前先要理解抽象語法樹這個概念。的解析器,的配置。編寫腳本識別字段思路首先獲取到源代碼是類單文件的語法。獲取內的字段,并替換成已生成的路由表。 話不多說先上圖,簡要說明一下干了些什么事。圖可能太模糊,可以點svg看看showImg(https://segmentfault.com/img/bV3fs4?w=771&h=63...
摘要:目錄項目構建文件使用優化之處組件通信的使用注意事項報錯記錄踩坑記錄項目構建官方文檔地址鏈接項目源碼地址鏈接項目資料地址鏈接簡單介紹是一個微信小程序框架,支持模塊化開發,開發風格類似。使用的方式請求小程序原生都將化。 目錄 wepy項目構建 wepy文件使用 wepy優化之處 wepy組件通信 wepy的API使用 wepy注意事項 wepy報錯記錄 wepy踩坑記錄 1. wep...
摘要:四最后一點點感悟本文總結的比較淺顯很多地方說的也不是太詳細歡迎大家留言一起交流探討堅持學習不斷探索總結路漫漫其修遠兮吾將上下而求索參考資料官方文檔微信小程序官網開發文檔官方開發文檔 一、微信小程序wepy框架簡介: 微信小程序WePY框架是騰訊官方推出來的框架,類似的框架還有美團的mpvue,京東的Taro等; 目前公司開發小程序主要用到的是微信原生方法和官方的wepy框架; wepy...
閱讀 2771·2021-10-11 11:08
閱讀 1489·2021-09-30 09:48
閱讀 1049·2021-09-22 15:29
閱讀 1037·2019-08-30 15:54
閱讀 976·2019-08-29 15:19
閱讀 527·2019-08-29 13:12
閱讀 3161·2019-08-26 13:53
閱讀 957·2019-08-26 13:28