preface

Hi everybody, the most popular thing in the front end circle recently is Vueconf on 5.22. It is very interesting to read the following topics. Considering that many students are not so familiar with VUE3, I will write a preview material for several topics to help you gain more on the day of 22nd

I will reimburse you for three vueconf online tickets by searching wechat and following the front end of The Flower and Fruit Mountain. If you reply to Vueconf, you can directly give you a red envelope

I have ordered a big screen, and we will watch it together on 22nd. Welcome to discuss and study online

issue

  • 09:30 Vue Ecological Progress @ Yu Yuxi
  • 10:30 Vite introduction @Underfin
  • Vue3 Compiler optimization @hcysunyang
  • 12:05 Dry rice and hot pot
  • 13:30 Build tool optimization code @ Jiang Haoqun
  • 14:15 Vue3的jsx                         @Amour1688 jsx-next
  • 15:00 Vue Composition              @Anthony Fu vueuse
  • 15:45 Vue flutter @ Kraken
  • Vue3 Multi-terminal application @ Cui Hongbao UNI-app
  • 17:20 Encapsulate libraries in Vue Composiiton @Jonathan Chakra-UI-vue
  • 18:10 Finish the meal

Introduce the preparation of the above topics in turn, first vuE3 website lu again

Vue3 ecological progress and plans

This is no preview, combined with the content of vue3 and Vueconf us, blind guess synchronization vue ecosystem development progress, I feel now very mature, can try online play

We will experience more recently. There is no preparation for this, and you can listen to it. I am looking forward to hearing the next plan after Vue3

Vue3 updates * Vuex 4 * VuE-Router 4 * Nuxt * Component library * IDE plugin Volar what * Vite2 * Vue2 migration guide * Vue2.7 * Looking forward to a better futureCopy the code

Vite, the next generation Web tool

Sharing content is a pain point for existing Web development and Vite solutions.

The recent popularity of Vite has really addressed the developer’s sore point that WebPack is too slow, as you can see in this chart

Every time webPack starts a project, it needs to be pre-packed, and a bundle must be packed to start dev Server. This is why every NPM run dev takes three minutes. Vite uses the browser’s import function to avoid this step

The import syntax of a script module in a browser will send an HTTP request for a resource, so that debugging does not need to be packaged and the development environment becomes silky smooth

This is just a simple principle, and vite takes a lot of extra work to actually get it to work

* Node_modules path parsing * Plugin mechanism support vue & React & Svelte frameworks * Hot update HMR * introduction of ESbuild translation JS Fast * Prepackaged optimized node_modules/. Vite * support SSR *...Copy the code

Vite has been decouped from Vue and has gradually become the preferred engineering tool for new frameworks. As for the principle, you can read my previous article. Vite2 has been restructured, and the hot update and pre-optimization content will be updated later

We can follow the official website recently to get familiar with vite, with questions to listen to, the harvest will be greater

New Front-end Tool — Vite from entry to Actual Combat (I)

Vue3’s compilation and optimization efforts

I believe that many students are more or less aware of vue3 compilation and runtime to do a lot of performance optimization efforts, this topic will be shared in detail to explore the implementation of optimization ideas, problems and solutions, as well as the exploration of template ability.

Two of my favorite points of Vue3 are composition and Compiler optimization. Composition solves the problem of chaotic code organization, and Compiler can truly update as needed when we are unaware of it

The concept of compiler suggests that we should first look at the-super-tiny-compiler, understand the basic concept of compiler principle, paser, AST, transformer, generate is what means

So compiler optimization, is the code before the package online optimization, vue in the template into the render function, during the source code we go to vue-next search baseCompile

export function baseCompile(template: string | RootNode, options: CompilerOptions = {}) :CodegenResult {
  constprefixIdentifiers = ! __BROWSER__ && (options.prefixIdentifiers ===true )

  constast = isString(template) ? baseParse(template, options) : template transform( ast, extend({}, options, { ... }))return generate(
    ast,
    extend({}, options, {
      prefixIdentifiers
    })
  )
}
Copy the code

So if we simplify this

const ast = baseParse(template) // Parse template into an AST, i.e., a tree
transform(ast,option)           // Optimizations, such as marking and converting vUE specific syntax
return genrate(ast)             // Generate the render function
Copy the code

You can experience the real-time results of the Vue Compiler online

Before we go live, we mark all the dynamic content, so that when the browser executes, we can skip a lot of operations. For example, in the picture above, h1 is purely static and does not change, div ID and textContent are dynamic and can be changed, and the function passed in also has a cache thief bar

We will try to implement a mini ourselves for you to experience, the actual implementation cost can go to vue-next, beginners to read a little difficult, and the re also need to understand

My code is quite bad, string traversal one by one, is a very DER implementation, the most twist is called the-der-tiny-compiler, welcome to star

So let’s try to simulate it, write a very der implementation to help you understand using this input


function compiler(template) {
  const ast = parse(template);
  transform(ast)
  const code = generate(ast)
  return new Function(code);
}

let tmpl = ` < div id = "app" > < = p @ click "add" : id = "name" > {{name}} < / p > < h1 class = "item" > technology fishing < / h1 > < / div > `


let render = compiler(tmpl)
Copy the code

tokens

So let’s break the strings into tokens


function tokenizer(input) {
  let tokens = []
  let type = ' '
  let val = ' '
  // Rough loop
  for (let i = 0; i < input.length; i++) {
    let ch = input[i]
    if (ch === '<') {
      push()
      if (input[i + 1= = ='/') {
        type = 'tagend'
      } else {
        type = 'tagstart'}}if (ch === '>') {
      push()
      type = "text"
      continue
    } else if (/[\s]/.test(ch)) { // Run into a space clip
      push()
      type = 'props'
      continue
    }
    val += ch
  }
  return tokens
Copy the code

We got this

[{type: 'tagstart'.val: 'div' },
  { type: 'props'.val: 'id="app"' },
  { type: 'tagstart'.val: 'p' },
  { type: 'props'.val: '@click="add"' },
  { type: 'props'.val: ':id="name"' },
  { type: 'text'.val: '{{name}}' },
  { type: 'tagend'.val: 'p' },
  { type: 'tagstart'.val: 'h1' },
  { type: 'props'.val: 'class="item"' },
  { type: 'text'.val: 'Technology fishing' },
  { type: 'tagend'.val: 'h1' },
  { type: 'tagend'.val: 'div'}]Copy the code

parse

And then to get the AST is to iterate to make a tree

function parse(template) {
  const tokens = tokenizer(template)
  let cur = 0
  let ast = {
    type: 'root'.props: [].children: []}while (cur < tokens.length) {
    ast.children.push(walk())
  }
  return ast

  function walk() {
    let token = tokens[cur]
    if (token.type == 'tagstart') {
      let node = {
        type: 'element'.tag: token.val,
        props: [].children: []
      }
      token = tokens[++cur]
      while(token.type ! = ='tagend') {
        if (token.type == 'props') {
          node.props.push(walk())
        } else {
          node.children.push(walk())
        }
        token = tokens[cur]
      }
      cur++
      return node
    }
    if (token.type === 'tagend') {
      cur++
      // return token
    }
    if (token.type == "text") {
      cur++
      return token
    }
    if (token.type === "props") {
      cur++
      const [key, val] = token.val.split('=')
      return {
        key,
        val
      }
    }
  }
}
Copy the code

And you end up with ast

{ "type": "root", "props": [], "children": [ { "type": "element", "tag": "div", "props": [ { "key": "id", "val": "\"app\"" } ], "children": [ { "type": "element", "tag": "p", "props": [ { "key": "@click", "val": "\"add\"" }, { "key": ":id", "val": "\"name\"" } ], "children": [ { "type": "text", "val": "{{name}}" } ] }, { "type": "element", "tag": "h1", "props": [ { "key": "class", "val": "\"item\"" } ], "children": [ { "type": "text", "val": }]}]}Copy the code

transform

And then I’m going to optimize it, basically just make a tag, a tag for attributes, whether the text is static or not

function transform(ast) {
  // Optimize the AST
  let context = {
    // import { toDisplayString , createVNode , openBlock , createBlock } from "vue"
    helpers:new Set(['openBlock'.'createVnode']), // The utility function used
  }
  traverse(ast, context)
  ast.helpers = context.helpers
}
function traverse(ast, context){
  switch(ast.type){
    case "root":
      context.helpers.add('createBlock')
      // log(ast)
    case "element":
      ast.children.forEach(node= >{
        traverse(node,context)
      })
      ast.flag = {props:false.class:false.event:false}
      ast.props = ast.props.map(prop= >{
        const {key,val} = prop
        if(key[0] = =The '@'){
          ast.flag.event = true
          return {
            key:'on'+key[1].toUpperCase()+key.slice(2),
            val
          }
        }
        if(key[0] = =':'){
          ast.flag.props = true
          return{
            key:key.slice(1),
            val
          }
        }
        if(key.startsWith('v-')) {// pass such as v-model
        }
        return{... prop,static:true}})break
    case "text":
      // trnsformText
      let re = /\{\{(.*)\}\}/g
      if(re.test(ast.val)){
        / / a {{
          ast.static = false
          context.helpers.add('toDisplayString')
          ast.val = ast.val.replace(/\{\{(.*)\}\}/g.function(s0,s1){
            return s1
          })
      }else{
        ast.static = true}}}Copy the code

Mainly is to use the ast. Flag = {props: false, the class: false, the event: false} to tag, false if it is all static, can be directly over the virtual dom diff

generate

And then the generation code, string spelling

function generate(ast) {
  const {helpers} = ast 

  let code = `
import {${[...helpers].map(v=>v+' as _'+v).join(', ')}} from 'vue'\n
export function render(_ctx, _cache, $props){
  return(_openBlock(), ${ast.children.map(node=>walk(node))})} `

  function walk(node){
    switch(node.type){
      case 'element':
        let {flag} = node // The compiled flag
        let props = '{'+node.props.reduce((ret,p) = >{
          if(flag.props){
            // Dynamic attributes
            ret.push(p.key +':_ctx.'+p.val.replace(/['"]/g.' '))}else{
            ret.push(p.key +':'+p.val )
          }

          return ret
        },[]).join(', ') +'} '
        return `_createVnode("${node.tag}",${props}),${node.children.map(n=>walk(n))}].The ${JSON.stringify(flag)}`
        break
      case 'text':
        if(node.static){
          return '"'+node.val+'"'
        }else{
          return `_toDisplayString(_ctx.${node.val}) `
        }
        break}}return code
}
Copy the code

So you get this code

import { openBlock as _openBlock, createVnode as _createVnode, createBlock as _createBlock, toDisplayString as _toDisplayString } from 'vue'

export function render(_ctx, _cache, $props) {
    return (_openBlock(), _createVnode("div", { id: "app" }), [
        _createVnode("p", { onClick: _ctx.add, id: _ctx.name }), [
            _toDisplayString(_ctx.name)
        ], { "props": true."class": false."event": true }, _createVnode("h1", { class: "item"}),"Technology"] and {"props": false."class": false."event": false}, {"props": false."class": false."event": false})}Copy the code

It’s not nearly the same as vue, but it’s not the same as vue, so we can tag props and event with bit operators

Although the implementation is very der(voice), but the compiler is enough to help understand VUe3, I will write an article in the future and implement it well (@todo).

Svelte style compiler will be directly compiled into the DOM in the future. Is vue really going to be a family bucket

Optimize code for a new generation of build tools

To take full advantage of the unique capabilities of these new tools, such as faster module hot updates, cross-module code reuse, and strong build caching, our project code also needs to keep up with The Times. This topic will share some of the coding tips and development process practices THAT I learned while researching building tools to make them work.Copy the code

I don’t know, I can’t predict what I’m going to say, blind guessing is the new ideas that these tools provide, and auxiliary functions, right? I’ll write a summary after VUeconf

Should be a sharing to improve development efficiency

Explore JSX in Vue 3

For JSX and Template, template is recommended in most scenarios, especially business scenarios. While template in Vue 3 offers many performance optimizations, it may not be flexible enough for some library developers to use JSX in a more flexible way. In this post, we will talk about the differences between JSX and Template, and share some design ideas of Vue 3 JSX plug-in, and development tips of Babel plug-in.

JSX compiler is a little easier than vue3, because there is less markup optimization, mainly can learn how to participate in the design of vuE3 ecology, and Babel plug-in skills

The der-compiler can also be used to parse JSX with a loader

There is also a bit of confusion, template has a lot of static tags, but I just ran a demo, JSX performance is almost the same as Template, 5000 components difference of about 10ms, expect to understand more about Template and JSX tomorrow

Composable Vue

Vue Composition API introduction to the underlying principles, for writing good combinatorial functions and sharing patterns.

Composition works fine. Vue-next’s code address is here

  // 2. call setup()
  const { setup } = Component
  if (setup) {
    const setupContext = (instance.setupContext =
      setup.length > 1 ? createSetupContext(instance) : null)

    currentInstance = instance
    const setupResult = callWithErrorHandling(
      setup,
      instance,
      ErrorCodes.SETUP_FUNCTION,
      [__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
    )
 
 
 export function callWithErrorHandling(fn,instance,type,args) {
  let res
  try{ res = args ? fn(... args) : fn() }catch (err) {
    handleError(err, instance, type)
  }
  return res

Copy the code

Others say more about his vue.use library, which encapsulates everyday functions in usEXx-style, such as tweaking the little ICONS on web pages

import { useFavicon } from '@vueuse/core'
const icon = useFavicon()
icon.value = 'dark.png' // change current icon
Copy the code

The inside is just looking for the link tag and changing the href, but the API makes it very slippery

export function useFavicon(
  newIcon: MaybeRef<string | null | undefined> = null,
  options: FaviconOptions = {},
) {
  const {
    baseUrl = ' ',
    rel = 'icon'.document = defaultDocument,
  } = options

  const favicon = isRef(newIcon)
    ? newIcon
    : ref<string | null>(newIcon)

  const applyIcon = (icon: string) = > {
    document? .head .querySelectorAll<HTMLLinkElement>(`link[rel*="${rel}"] `)
      .forEach(el= > el.href = `${baseUrl}${icon}`)
  }

  watch(
    favicon,
    (i, o) = > {
      if(isString(i) && i ! == o) applyIcon(i) }, {immediate: true},)return favicon
}

Copy the code

By the way, favicon can also be set to video and camera, so I’ll mention pr later

The principle can be seen in my previous article

Technical fishing tool development (1) 60 lines of code to implement favcion fishing

Build a high-performance Flutter application with vue.js

At present, cross-end has been a topic that the front end cannot get around. With the popularity of IoT devices, more and more “ends” emerge in our daily development. Since The introduction of Hybrid and React Native (Weex), Flutter has emerged as a new favorite in recent years thanks to its streamlined rendering pipeline and its ability to draw its own rendering. However, its development model with Dart + Widgets and its separate ecosystem from the front end resulted in high development costs. Based on this background, we explore a W3C standard-based application of Flutter, which connects to the front-end ecology up and ensures multi-end consistency down through self-drawing. This article will bring you a plan to develop Flutter application with vue. js and the practice and thinking behind Kraken.

The big brother in the group said it was very useful, but I am not interested in Flutter, and I am also a chicken. I will let the big shuai write some thoughts about flutter later

Develop multi-terminal applications based on Vue 3.0

The uni-App compiler has been upgraded to Vite and the runtime has been upgraded to Vue 3.0. The upgraded uni-App compilers are exponentially faster and the runtime has many performance optimizations.

This time I will share a series of explorations and reflections in the process of uni-App upgrading Vue 3.0. The main contents include: The Uni Runtime is smaller, faster, and trekking based on platform differences. The uni runtime can be used as a component of the uni app. 5, The advantages of developing multi-end applications with Vue 3.0 (performance/flexibility/compilation speed, etc.)Copy the code

The Vue cross-end is also a very popular application. Once run-time Core and Run-time DOM are separated, we can customize the renderer based on run-time Core. Render vuE3 to any platform you want. I wrote a toy rendering canvas in my previous study

import { createRenderer } from '@vue/runtime-core'
let ctx

function draw(ele, isChild) {
  if(! isChild) { ctx.clearRect(0.0.500.500)
  }
  ctx.fillStyle = ele.fill || 'white'ctx.fillRect(... ele.pos)if (ele.text) {
    ctx.fillStyle = ele.color || 'white'
    ele.fontSize = ele.type == "h1" ? 20 : 12
    ctx.font = (ele.fontSize || 18) + 'px serif'
    ctx.fillText(ele.text, ele.pos[0] + 10, ele.pos[1] + ele.fontSize)
  }
  ele.child && ele.child.forEach(c= > {
    draw(c, true)})}const { createApp: originCa } = createRenderer({
  insert: (child, parent, anchor) = > {
    if (typeof child == 'string') {
      parent.text = child
    } else {
      child.parent = parent
      if(! parent.child) { parent.child = [child] }else {
        parent.child.push(child)
      }
    }
    if (parent.nodeName) {
      draw(child)
      if (child.onClick) {
        ctx.canvas.addEventListener('click'.() = > {
          child.onClick()
          setTimeout(() = > {
            draw(child)
          })
        }, false)}}},createElement(type, isSVG, isCustom) {
    return {
      type
    }
  },
  setElementText(node, text) {
    node.text = text
  },
  patchProp(el, key, prev, next) {
    el[key] = next
  },
  parentNode: node= > node,
  nextSibling: node= > node,
  createText: text= > text,
  remove:node= >node

});
function createApp(. args) {
  constapp = originCa(... args)return {
    mount(selector) {
      const canvas = document.createElement('canvas')
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight
      document.querySelector(selector).appendChild(canvas)
      ctx = canvas.getContext('2d')
      app.mount(canvas)
    }
  }
}
export { createApp }



Copy the code

Then you can play with it and make the size and position of the canvas responsive

<template>
<div @click="Elegantly-named setName (' vue3 grest ')" :pos=",10,300,300 [10]" fill="#eee">
    <h1 :pos="[20,20,200,100]" fill="red" color="# 000">Accumulator {{count}}</h1>
    <span :pos="pos" fill="black" >Hello {{name}}</span>
</div>

</template>

<script>

import {ref} from 'vue'
export default {
  setup(){
    const name = ref('kkb')
    const pos = ref([20.120.200.100])
    const count = ref(1)
    const setName = (n) = >{
      name.value = n
      pos.value[1] + =20
      count.value+=2
    }
    return {
      name,
      setName,
      pos,
      count
    }
  }
}
</script>



Copy the code

We have a group with PixiJS wrote a VUE3 dozen aircraft war, we can refer to play

Converting Browser Libraries into Vue hooks/composables.

The only foreigner’s shared feeling may conflict with vueuse’s content, and there is no specific introduction, so you can’t guess what it is about, according to author Jonathan’s work

I still don’t see anything. Look forward to sharing

Lightning share

According to the habit of Vueconf in the past, in addition to these topics, there will also be a lightning share of the big wigs, this time is no exception, let me keep it in the dark for now, and I will write some thoughts after the end

conclusion

I hope this article can help you better audit tomorrow’s Vueconf, Yeah. Please pay attention to my column and the latest articles will be sent out in time

I will reimburse you for three vueconf online tickets by searching wechat and following the front end of The Flower and Fruit Mountain. If you reply to Vueconf, you can directly give you a red envelope

Reply to reading plus group, tomorrow together in the group live discussion Vueconf experience, the king is also welcome