Principles and thinking underlying implementation -------------------------- reference applet

 

   1. Single-threaded

     Vue 1.1 transformation

      

The transformation of the Vue usually there are two options:

  • Polyfill using similar tactics to cover some of Vue native API provided

  • Fork it ourselves out of a Vue

The first program capacity is limited, there is some internal logic Vue is no way to change the form of polyfill. The second flaw is that if I want the program to modify certain piece of logic Vue, I do not modify other parts if there Bug, Vue official updated version I have no way synchronization.

Both programs have flaws and shortcomings, so I did not use either of these which I used another program, I think it is by far the best kind of program.

I briefly explain this approach:

  • The Vue.js installed in the node_modules

  • Project in use webpack, and set the alias

  • I want to transform that part of the code to copy your project directory to be modified

Because I need to render the layer transformation, so I need to reset the web alias, as follows:

 

  1. const path = require('path')

  2.  

  3. module.exports = {

  4. 'vue$': path.resolve(__dirname, '../src/web/entry-runtime-with-compiler'),

  5. compiler: 'vue/src/compiler',

  6. core: 'vue/src/core',

  7. shared: 'vue/src/shared',

  8. web: path.resolve(__dirname, '../src/web'),

  9. weex: 'vue/src/platforms/weex',

  10. server: 'vue/src/server',

  11. sfc: 'vue/src/sfc'

  12. }

    General principle is: If you do not need to import a transformation, that is actually import the file node_modules in the original Vue, if the import is in need of rehabilitation, that is actually import a file of my directory, I modified file is .

1.2 is set for the label blacklist

     After Vue through a series of calculations of the final output is the result of some instructions, such as creating a DOM element, remove a DOM element is inserted into a location.

So when the practice is simple when you create the DOM element with the tagName check whether the blacklist, if it triggers a warning in the blacklist and how and how.

But in fact this practice can only be: anti-anti-villain is not a gentleman.

Problems encountered 1.3

Project done here encountered a problem is no matter what, there is no way to prevent the developer to do some of the features we want to disable. Because it is a web page, developers can perform JS, can operate DOM, you can operate BOM, you can do everything.

So we started thinking about the user's code into a totally secure sandbox execution.

2. Double thread

In Web technology, the user can put the code to execute Web Worker can be placed in a hidden iframe to carry out, provides an environment or host environment. Either way, the goal is the same, that is, the user's code into a totally secure sandbox execution.

Because developers are based Vue.js development, user code is no way to separate into the sandbox to perform, so I put into the sandbox Vue also to perform.

This time technical architecture and technology direction are adjusted became a Master-Slave two- thread mode.

Sandbox code I called Master, which through a series of calculations, the final output of some instructions: create elements, modifying elements, insert elements, routing jump event binding and some basic instructions. These instructions from the sandbox by a thread passing messages between mechanism to a Web page, this page has a module called the Slave, which is responsible for monitoring Master sent me the instructions and do the specified action according to the instructions.

 

 

 

 

Vue put into the implementation of Web Worker need to solve a lot of problems, such as: the original Vue operation of the DOM need to be converted to another thread to send commands directly, as well as event binding problem, Event Object of events, event modifier (event.preventDefault) problem, routing control (two-way) question, problem-way binding form elements, ref problems. Because message passing between threads can only pass a string, so many things will become very troublesome.

However, these specific technical problems are easier to solve, the more difficult the problem is two-fold: "Performance" and "native capacity constrained"

 

 

 

 

2.1 Performance
       In this architecture, when the page there is a wide range of UI changes (for example, for the first time rendering), Logic thread needs to send a large number of instructions to the UI thread, including: Creating a DOM, insert DOM, binding events, each instruction is a separate messaging across threads, and when a large number of messages, performance issues will be revealed, and very obvious.

If you go to Chrome DevTools the Performance panel look, you will find the UI thread is very busy, but rendering is very slow. Because the cost of messaging, and each encode and decode also a price to pay, I did not find the problem when writing DEMO, but when put into production continue render a real component, you will find a performance problem is obvious.

Under this framework, although there are performance issues, but I think the ability to solve this problem is not too difficult. Another problem (native capacity is limited) is a problem under this framework will never be able to solve.

2.2 Native capacity is limited

For security, the need to user code into a sandbox to execute, but because developers want users to use Vue, Vue have to put it in a sandbox, which leads to a problem is not solved: our official offer native components, will be limited.

The reason is simple, assuming that the user uses native components provide an official in the template, then this component must be required to register in advance to the Vue, it is representative of the components of our official offer, it has placed in the sandbox , the so we have to put yourself locked out.

The official cause we want to provide video components, audio components is very difficult because the components can not touch our official DOM and BOM, not to mention the ability to provide the components of other Native.

Of course, this problem without changing architecture or a way of imposing solutions, the solution is this:

Official component of Vue to register a component in a sandbox, then this component not to achieve specific functions, but the user receives data transmission, and then pass the data to the UI thread, the UI thread and then have a real component corresponding to this component do a specific function and ultimately rendered to the UI.

 

 

 

Each component required to do so, which is very unfriendly to the students component development, they need to understand how the underlying architecture of this small program is running, but also add a lot of workload.

This is not what I want, and I hope that whatever I underlying single-threaded or dual-threaded, the upper layer is not aware of the development. And because Vue.js do various operations in the sandbox, not sure what the future will be unable to meet demand, technical risk is too high.

At this step, I have slowly begun to feel, Vue has become a bottleneck, it limits me.

3. Return the single-threaded

Not only because of technical reasons, but also because of other reasons, such as too risky, time is tight, the final decision to switch the program back to the first single-threaded, so to say the least ensure that this project can not be postponed. Then go to the other side slowly research and developed a technical solution can solve all problems encountered before.

It seems to be back to square one, because there are single-threaded single-threaded problem , and that is too open Web technology, and we can not do "safe" and a "control" for developers.

But we still found a can improve certain safety program in single-threaded mode, program mode by Close ShadowDOM of the Body locked. Own code so that developers can not manipulate the DOM, because I was locked up, but the JavaScript developer is free.

 

 

 

In this framework, developers can manipulate DOM, you can operate BOM, can operate Vue.js, can do anything, but it can not be directly manipulated me locked ShadowDOM, want to operate this ShadowDOM, must operate through legal means, the main window is the ShadowDOM applet for display.

Then for some dangerous API on the BOM, is disabled out in advance.

The program seems to solve all the problems, but still left a little hidden dangers for the future, as long as the JavaScript developer is free, you'll never know what he will do with his JavaScript. For some unknown vulnerabilities, can be very dangerous, this leaves a risk for the future, things will become lasting between an official and developers battle.

In any case, this solution addresses all the current problems, which also left me a lot of time to study the real little program what to do.

4. Return the double thread

Eventually, I found two threads is the right direction, only the user code into the sandbox execution can really do: "security" and "control."

But this time I decided not to use Vue.js, I need to develop a new framework to support two threads of this model. The reason why the last two threads will fail, mainly because the last time the UI thread lighter, heavier thread and Logic, user code, Vue.js, an official of the components are run under Logic thread, and this thread is just a JS run time, so our native ability is limited.

而这一次我决定让UI重一点,Logic轻一点。只把用户的代码和框架的一部分下放到Logic线程,大部分操作和原生组件都放在UI线程下执行。

 

 

 

 

Worker线程只是做一些计算然后把数据传递到UI线程,然后大部分工作都在UI下面执行,并且官方的组件在UI这边执行。

这样可以解决之前遇到的两个问题:性能和原生能力受限。

因为线程之间的消息通道只传递数据,而数据不会像绘制UI指令数量那么多,可以说根本不在一个数量级,性能问题解决了,而且不光解决了性能问题,还顺带着提升了性能,因为无论用户代码写的执行效率再怎么低,都不会卡死UI线程。

原生能力受限的问题也解决了,因为官方提供的组件根本不在这个线程下运行,安全和管控的问题也解决了。

5. 一些思考

之前我一直以为其他小程序是Native渲染的,而我是基于Web技术实现的,但偶然有一次看到一些资料,才发现,原来大家都是基于Web技术实现的小程序,而实现方式也大致相同,遇到的问题也都一样。

可能唯一的区别是,我不需要多个webview,我只需要一个网页就够了,所以我可以把Logic线程的代码放到Web Worker里,而其他小程序是多个webview,所以他们不能用Web Worker,不过没有本质区别。

 

5.1 关于小程序跨平台的一些看法

前一段时间各种小程序多端框架满天飞,准确的说,这些框架都是“翻译”器,就我个人觉得,以翻译为基础在不同小程序之间进行跨端,只能算是一种临时性技术方案。

我觉得真正的终极技术方案,有两种:

  • 从渲染引擎层面抹平平台间的差异,例如:Flutter

  • 各个小程序开发商共同制定一些标准和规范,例如:浏览器

第一种,使用小程序提供的canvas的一些API实现一个渲染引擎,然后在渲染引擎上实现一些布局引擎,在此基础上提供的框架和其他能力都是统一的,不同平台之间只需要实现不同的渲染引擎即可。不过我不确定小程序提供的canvas能不能做到这一点,不过Web浏览器提供的canvas可以做到,像SpriteJS就做到了。

第二种,各大小程序厂商共同制定一套标准,按照标准实现各自的API,这种情况是比较好的,而且也不是完全没有可能。最近各大小程序厂商已经在W3C起草了小程序白皮书。

我捡重要的列一下白皮书中的内容:

  • 标准化小程序包(就是说一份小程序代码,可以在各大小程序平台解析,使用统一的.ma后缀的文件)

  • 标准化小程序页面的URI Scheme(就是说定义一份协议,然后同一个URI地址可以在不同的小程序平台打开相同的页面)

  • 标准化小程序Widgets

6. 总结

仔细看到这里的读者应该会对我开发小程序的整个过程和一些决策有一个大致的了解。

大家对小程序的底层实现都是使用双线程模型,大家对外宣称都会说是为了:

  • 方便多个页面之间数据共享和交互

  • 为native开发者提供更好的编码体验

  • 为了性能(防止用户的JS执行卡住UI线程)

  • 其他好处

但其实真正的原因其实是:“安全”和“管控”,其他原因都是附加上去的。

因为Web技术是非常开放的,JavaScript可以做任何事。但在小程序这个场景下,它不会给开发者那么高的权限:

  • 不允许开发者把页面跳转到其他在线网页

  • 不允许开发者直接访问DOM

  • 不允许开发者随意使用window上的某些未知的可能有危险的API

当然,想解决这些问题不一定非要使用双线程模型,但双线程模型无疑是最合适的技术方案。

Guess you like

Origin www.cnblogs.com/zhouyideboke/p/12212830.html