In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "how to implement Mini Program web service". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn "how to implement Mini Program web service".
Implementation of Mini Program web service
I used koa to provide web services and et-improve to provide template rendering in the development of wept.
* step: prepare the page template
We need three pages, one as the control layer index.html, one as the service layer service.html, and one as the view layer view.html
Index.html:
Var _ wxConfig__ = {{= _ .config}} var _ _ root__ ='{{= _ .root}}'
Service.html:
Var _ _ wxAppData = {} var _ _ wxRoute var _ _ wxRouteBegin global = {} var _ _ wxConfig = {{= _ .config}} {{each _ .utils as util}} {{/}} {{each _ .routes as route}} var _ _ wxRoute ='{{= route | noext}}', _ _ wxRouteBegin = true {{/}} window._sendMsgToNW ({sdkName: 'APP_SERVICE_COMPLETE'})
View.html:
Var _ _ path__ ='{{= _ .path}}'{{= _ .inject _ js}} document.dispatchEvent (new CustomEvent ("generateFuncReady", {detail: {generateFunc: $gwx ('. / {{= _ .path} .wxml')
Step 2: implement the http service
The code logic implemented in koa is very simple:
Server.js
/ / app.use (logger ()) / / gzip app.use (compress ({threshold: 2048)) Flush: require ('zlib'). Z_SYNC_FLUSH}) / / error alert middleware app.use (notifyError) / / request app.use (staticFallback) / / various route implementation app.use (router.routes ()) app.use (router.allowedMethods ()) / / enable static file service app.use (require (' koa-static') (path.resolve (_ _ dirname)) for public directory '.. / public')) / / create startup service let server = http.createServer (app.callback ()) server.listen (3000)
Router.js
Router.get ('/', function * () {/ / load index.html templates and data, output index pages}) router.get ('/ appservice', function * () {/ / load service.html templates and data Output service page}) / / have `/ app/**` load the directory file router.get ('/ app/ (. *) 'where Mini Program is located Function* () {if (/\. (wxss | js) $/ .test (file)) {/ / dynamically compiled to css and corresponding js} else if (/\ .wxml / .test (file)) {/ / dynamically compiled to html} else {/ / find other types of files, and returned let exists = util.exists (file) if (exists) {yield send (this) File)} else {this.status = 404 throw new Error (`File: ${file} not room`)}})
Step 3: realize the function of the control layer
After implementing the above two steps, you can access the view page, but you will find that it can only render and will not have any function, because the function of the view layer depends on the communication of the control layer, and if the control layer does not receive the message, it will not respond to any events.
The control layer is the most complex part of the whole implementation process, because the code of the official tool is too highly coupled with third-party components such as nwjs and react, so it can not be used directly. You can find all the code of the control layer logic in the src directory of the wept project. In general, the control layer is responsible for the following functions:
Realize the communication logic among service layer, view layer and control layer.
Dynamically create view according to routing instructions (wept is implemented using iframe)
Dynamically render header and tabbar based on the current page
Implement the native API call and return the result to the service layer
The communication between iframe in wept is realized through message.js module. The control page (index.html) code is as follows:
Window.addEventListener ('message', function (e) {let data = e.data let cmd = data.command let msg = data.msg / / does not shake hands with contentscript and does not need to deal with if (data.to = =' contentscript') return / / this is a legacy method, which basically abandons if (data.command = = 'EXEC_JSSDK') {sdk (data) / / directly forwards view layer messages to service Mainly various event notifications} else if (cmd = = 'TO_APP_SERVICE') {toAppService (data) / / except that publish sends messages to the view layer and logic that can be handled by the control layer (such as setting headers), / / all forward service processing The processing results of all control layers first return service} else if (cmd = = 'COMMAND_FROM_ASJS') {let sdkName = data.sdkName if (command.hasOwnProperty (sdkName)) {command [sdkName] (data)} else {console.warn (`Method ${sdkName} not implemented for command! `)} else {console.warn (`Command ${cmd} not recognized!`)})
For more information on the implementation logic, please see src/command.js src/service.jssrc/sdk/*.js. For view/service pages, just change the window.postMessage of the original bridge.js to window.top.postMessage.
The control logic of the view layer is implemented by src/view.js and src/viewManage.js. ViewManage implements navigateTo, redirectTo and navigateBack to respond to the corresponding page routing events sent by the service layer through a command named publish.
Header.js and tabbar.js include header and tabbar modules implemented based on react (originally planned to use vue, but could not find an API to communicate with native js modules)
The sdk directory contains storage, recording, compass modules, and other relatively simple native underlying calls I wrote directly in command.js.
The above is all the logic to achieve the webserver needed to run Mini Program, its implementation is not complex, the main difficulty lies in understanding the whole set of communication methods of Wechat.
Realize the real-time update of Mini Program
Step 1: monitor file changes and notify the front end
Wept uses the chokidar module to monitor file changes, and uses WebSocket to tell all clients to update after the changes. The specific implementation is located in lib/watcher.js and lib/socket.js, and the content sent is a string in json format.
After receiving the WebSocket message, the front-end control layer forwards the message to the view/service layer through the postMessage interface:
View.postMessage ({msg: {data: {data: {path}}, eventName: 'reload'}, command:' CUSTOM'})
The view/service layer listens for reload events:
WeixinJSBridge.subscribe ('reload', function (data) {/ / data is the above msg.data})
Step 2: the front end responds to different file changes
The front end requires four different hot update treatments for four (wxml wxss json javascript) different types of files, of which wxss and json are relatively simple.
After the wxss file changes, the front-end control layer notifies (postMessage API) that the corresponding page (or all view pages if app.wxss) is refreshed. After receiving the message, the view layer only needs to change the timestamp of the corresponding css file. The code is as follows:
O.subscribe ('reload', function (data) {if (/\ .wxss $/ .test (data.path)) {var p =' / app/' + data.path var els = document.getElementsByTagName ('link') [] .slice.call (els) .forEach (function (el) {var href = el.getAttribute ('href'). Replace (/\? (. *) $/,') if (p = = href) {console.info ('Reload:' + data.path) el.setAttribute ('href', href +'? id=' + Date.now ()}})}}))
The change of json file first needs to be judged. If it is app.json, we cannot update it hot, so the current practice is to refresh the page. For the json of the page, we only need to set the corresponding status to header on the control layer (react will handle the rendering work for us):
Socket.onmessage = function (e) {let data = JSON.parse (e.data) let p = data.path if (data.type = = 'reload') {if (p = =' app.json') {redirectToHome ()} else if (/ / .json $/ .test (p)) {let win = window.__wxConfig__ ['window'] win.pages [p.replace (/\ .json $/ '')] = data.content / / header uses global _ _ wxConfig__ to obtain state for rendering header.reset () console.info (`Reset header for ${p.replace (/\ .json $/,')} `)}
Wxml uses diff apply provided by VirtualDom API for processing. First, you need an API to get the new generateFunc function (used to generate VirtualDom) and add the router of koa:
Router.get ('/ generateFunc', function* () {this.body = yield loadFile (this.query.path + '.wxml') this.type = 'text'}) function loadFile (p, throwErr = true) {return new Promise ((resolve, reject) = > {fs.stat (`. / ${p}`), (err Stats) = > {if (err) {if (throwErr) return reject (new Error (`file ${p} not room`)) / / the file does not exist and may have been deleted Therefore, you cannot use reject return resolve ('')} if (stats & & stats.isFile ()) {/ / parer function to call the exec command to execute the wcsc file to generate the javascript code return parser (`${p}`). Then (resolve, reject)} else {return resolve ('')}
With the interface, you can request the interface, and then execute the return function to diff apply:
/ / curr is the current VirtualDom tree if (! curr) return var xhr = new XMLHttpRequest () xhr.onreadystatechange = function () {if (xhr.readyState = 4) {if (xhr.status = 200) {var text = xhr.responseText var func = new Function (text +'\ n return $gwx (". /'+ _ path__+ '.wxml") window.__generateFunc__ = func () var oldTree = curr / / get the current data to generate a new tree var o = m (p.default.getData ()) False), / / diff apply a = oldTree.diff (o) A.apply (x); document.dispatchEvent (new CustomEvent ("pageReRender", {})); console.info ('Hot apply:' + _ path__ + '.wxml')} xhr.open ('GET',' / generateFunc?path=' + encodeURIComponent (_ path__)) xhr.send ()
The javascript update logic is relatively complex, starting with an interface to get the new javascript code:
Router.get ('/ generateJavascript', function* () {this.body = yield loadFile (this.query.path) this.type = 'text'})
Then we add the Reload function to the window object to execute the specific replacement logic:
Window.Reload = function (e) {var pages = _ wxConfig.pages; if (pages.indexOf (window.__wxRoute) =-1) return / / replace the original constructor f [window. _ _ wxRoute] = e var keys = Object.keys (p) / / determine whether the page var isCurr = s.route = = window.__wxRoute keys.forEach (function (key) {var o = p [key] is currently in use Key = Number (key) var query = o.roomqueryquery _ var page = o.page var route = o.route / / Page has been created if (route = = window.__wxRoute) {/ / execute encapsulated onHide and onUnload isCurr & & page.onHide () page.onUnload () / / create a new page object var newPage = new a.default (e, key) Route) newPage.__query__ = query / / rebind the current page if (isCurr) s.page = newPage o.page = newPage / / execute onLoad and onShow newPage.onLoad () if (isCurr) newPage.onShow () / / update data data window.__ wxAppData[ route] = newPage.data window.__ wxAppData[ route]. _ _ webviewId__ = key / / send update event Notify view layer u.publish (c.UPDATE_APP_DATA) u.info ("Update view with init data") u.info (newPage.data) / / send appDataChange event u.publish ("appDataChange", {data: {data: newPage.data}) Option: {timestamp: Date.now ()}) newPage.__webviewReady__ = true}}) u.info ("Reload page:" + window.__wxRoute)}
The above code needs to be added to the t.pageHolder function before it can be run
* switch the Page function to the Reload function after initialization of the view layer (of course, you can also rename Page to Reload before you request to return javascript).
Window._sendMsgToNW ({sdkName: 'APP_SERVICE_COMPLETE'}) at this point, I believe you have a deeper understanding of "how to implement Mini Program web service". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.