You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JSX 变量在模板语法使用 this.state.x,编译的时候生成未赋值的 data 值,需要定义一个变量赋值 this.state.x ;
不必遵守 render* 渲染 JSX 的约定;
不必遵守 on* 渲染传递函数名的约定;
...
从架构层面上讲,Taro 从一个编译型框架变成了一个运行时框架,基本上曾经的 Taro 无法运行的代码在 Taro Next 中完全没有压力。[email protected] 在运行时维护了一个 DOM 模型,使得编译的时候不去做 data xml 转化,从而规避掉了编译带来的 bug,同时降低学习成本,PC 端开发的同学也能轻松接入。
前言
[email protected]
发版以来,基本上保持在一周的时间发版,主要是修复bug
。通过社区可以了解到,[email protected]
发版带来了重大变革,其中对H5
和小程序场景进行重构,提供了新的特性和新的架构。[email protected]
发版之后,社区一直很活跃,不少用户开始使用一键式(命令)升级。敲完之后是这样:
还有这样的:
看到这些我差点笑出声,这是我在 issue 在讨论
3.x
时看到的,这位同学版本应该是敲错了。不得不说逛社区是件很有意思的事情,有的时候看issue
能发现一些同道中人,你踩的坑别人也在前赴后继[手动尴尬]。Taro
目前还有很多的 坑 ,现在有 600+ 的issue
数,平摊到各个平台其实不会很多,咋看一下 V-3issue
也就几十个。也有可能是用户基数的关系,毕竟刚发版不久,幸存者偏差。这里我不是要劝退想要升级的同学,就像官方说的,”没有枪,没有炮,没有轮子自己造“,不要怂,就是*!首先我们先看看[email protected]
特性。以下是在小程序场景下升级
[email protected]
,其他端升级仅供参考和学习。[email protected] 特性
看到它那么多特性,似乎很诱人,详细参考 官方文档,文档有的东西在这里就不过多的赘述了。
下面是如何用上它呢?如果是新项目那很好办,只需要实现新功能,对于旧项目呢?”买不了吃亏,买不了上当“,以其忍受旧的技术栈,不如升级玩出新花样。
[email protected] 是个啥
首先先简单了解下框架原理和解决的问题。
框架
下面是引用官方的一张架构图:
解决了什么问题
this.state.x
,编译的时候生成未赋值的data
值,需要定义一个变量赋值this.state.x
;render*
渲染JSX
的约定;on*
渲染传递函数名的约定;从架构层面上讲,Taro 从一个编译型框架变成了一个运行时框架,基本上曾经的
Taro
无法运行的代码在Taro Next
中完全没有压力。[email protected]
在运行时维护了一个DOM
模型,使得编译的时候不去做data xml
转化,从而规避掉了编译带来的bug
,同时降低学习成本,PC
端开发的同学也能轻松接入。看起来挺香的。了解了一些知识后,下面我们先从依赖开始升级。
[email protected] 依赖
以下是基于
[email protected]
升级到基于[email protected]
框架Taro@lastest(@3.0.7)
的历程。框架选型
对用户来说,开放式框架给了用户更多地选择,原来的版本只支持的类
React
语法,现在完全可以使用社区的其他框架,比如Vue 2
、Vue 3
、jQuery
。在这里因为我是一个React
的重度用户,比起官方的Nerv
,倾向于React
。而且React
是一个非常优秀的开源项目,有庞大的团队在维护。这里安利一下 React,[email protected] 发布了,只是一个过渡版本,消除了设计上的隐患,帮助用户更安全的升级过渡,新的功能特性放在React@18
发布,有没有一种服务到家的感觉(这里有点要黑[email protected] break change
式升级的嫌疑)。跑题了,下面继续介绍
Taro
升级,下面是选择React
框架需要改造的地方:React
技术栈所使用的npm
包;API
从Taro
移到第三方框架,比如:import React, { Component } from 'react'
;config.framework: 'react'
;babel.config.js
配置React
相关babel
,这里可以使用官方的babel-preset-taro
,下面【配置更改】会讲到;Babel@7
在
[email protected]
使用的babel@6
,了解babel
同学应该知道 6.x 版本和 7.x 版本的差异,比如Presets
,新的Proposals
等命名,babel@7
使用@babel/x
scope
代替babel/x
,防止被占用。相关依赖包升级
npm
挨个安装升级的需要babel
包了;babel-preset-taro
;cli
。将taro-cli
升级到3.x,执行taro update project[version]
命令。建议使用cli
升级命令最好是已经升级到 3.x 版本,对于2到3的升级,建议手动升级各个依赖包,因为只能cli
检测dependencies
某一些包 进行升级。配置更改
babel-config.js
。在[email protected]
之前是babel
配置在config/index
配置文件里面,现在把它放在根目录的babel
配置文件里面.eslintrc
。在[email protected]
eslint-plugin-taro
废弃,因为之前的配置以及编码最佳实践将不适用。如果开启了ts
编译,还需要安装@typescript-eslint/parser
和@typescript-eslint/eslint-plugin
。[email protected] 业务代码改造
页面 config 独立文件
在
Taro
1.x,2.x 时,配置是在页面实例里面去配置config
,编译后输出x.json
配置文件。在[email protected]
里,需要在同级目录里新增一个独立的JS
文件去配置:x.config.js
。在这里需要注意的一点是,跟页面代码一起的
config
会通过webpack
编译,而独立成x.config.js
只会被babel-register
进行编译,在项目里刚好config
配置的pages
常量是根据不同的场景定义的webpack
常量,所以config.js
取不到webpack
常量配置报错。解决方案是,使用 babel-plugin-transform-define,主要不能与webpack
常量冲突,需要额外定义config.js
里面的常量。这种解决方式毕竟不优雅,官方考虑在后续添加这个特性,相关issue。config/index 配置文件
Config.framework
配置当前小程序使用的框架React | Vue | Nerv
;Config.defineContants
。[email protected]
常量的value
可以使用key: '我是字符串'
。在[email protected] 编译会报错,要用String
再包一层,比如key: JSON.stringify('我是字符串')
,这里建议定义的常量值都使用JSON.stringify
处理一下。Config.terser
压缩配置项,terser 配置只在生产模式下生效。如果你正在使用watch
模式,又希望启用terser
,那么则需要设置,process.env.NODE_ENV
为production
,将不会生成source-map
文件。页面实例的改动
Taro.Component
替换为React.Component
;路由信息
this.$router is undefined
;Taro.getApp() is undefined
;页面实例方法的改变,比如
onShareMessage
改成static onShareMessage
;e.currentTarget.dataset
空对象;withWeapp
问题;没有了
this.$scope
和this.$componentType
的概念;...
[email protected] 多场景下框架的兼容
在
[email protected]
,小程序分包我们可以使用宿主小程序的框架,但在升级[email protected]
过程中,我们需要分析 2.x 和 3.x 框架版本能不能做到共用。这个章节我们针对主包、分包和插件场景下对小程序的运行、打包和包大小进行分析,演示多场景框架升级的可行性。独立运行
在58小程序体系里面,经常会有同一份源码编译到不同端的场景,以及借助内部工程化管理工具
MPS
更为便捷的管理分包,组件。在分包和插件的场景下,是一份这样的目录结构:分包
在分包场景中,为了减少包大小,分包尽量减少了依赖第三方
vendors
的注入,比如Taro
,共用主包的vendor
,删掉了无效的app.x
和project.config.json
。在升级[email protected]
的过程中,由于框架机制的改变,而无法做到与低于 3.0 的版本做到框架的共用。因为在3.x,各个Page
依赖入口文件app.js
createReactApp(App: React.ComponentClass, react: typeof React, reactdom, config: AppConfig)
创建的Current
(包含app
,router
,page
)和Reconciler
实例,就是page
依赖执行app.js
文件(参考代码实现)。但是分包的app.js
不是作为入口文件执行的,咋办呢?我想到的是在各个文件
require('./**/app.js')
,在加载完整个分包后执行app.js
,实现App
的实例化。可以看到,在入口文件我们取到实例,且在
Page
页面也能取到实例。但是有个问题发现了没,我们是跟主包共用一个App
实例,这会导致我们改掉App
实例的内容影响到主包。注入
app.js
方案在分包场景是没有问题的,但是怎么解决App
实例影响问题呢?这个问题等下再回答,我们再来以插件场景进行尝试这个方案。插件
还是跟分包一样的入口文件和
page
页面。我们先看下编译后的app.js
代码长啥样:这就是
[email protected]
编译后的入口文件,下面我们引入这个插件:发现在插件模式下,微信小程序没有提供
App
实例。分析分包和插件页面加载方案
从上面可以看出,
require('./**/app.js')方案
从运行机制上来看可行,但是存在一些问题:分包引入
app.js
执行会引入主包App
实例被改问题;插件模式下,微信小程序没有提供
App
实例报错;怎么给每个
Page
注入app.js
;怎么解决上面的问题呢?所以我们想到,我们能不能在分包和插件自己实现一个
App
函数,并且提供一个onLaunch
空方法,让taro-runtime
能够执行createReactApp
呢?下面是我们使用插件@mps/mps-taro-plugin/dist/MpsRuntimeTaroPlugin
实现了一个App
函数:并且通过
webpack.ProvidePlugin
注入到app.js
中,打包后的文件是这样的:我们再来手动引入
app.js
试试,没有报错,程序能正常运行。我们不能每个
Page
都手动注入app.js
吧?接下来如何给每个Page
引入app.js
呢?这时候我们可以通过webpack
插件做这件事情,刚好我们现有@mps/mps-taro-plugin/dist/MpsBusinessTaroPlugin
已经提供了这个能力,安装@mps/[email protected]
版本。下面是提供App
函数和给每个Page
注入app.js
的插件配置:撒花!通过以上的方式解决了多场景下框架版本的兼容性问题。
打包文件
入口文件处理
多场景如何定义入口文件,这是一个问题,我们经常在入口文件主包需要引用一一些
sdk
之外,然而在分包和插件场景并不需要使用到。比如在Taro2.x
的是按WEBPACK_CONST
条件将import
进来模块赋值给已经赋值过的变量,引入target
模块定义的上下文在没有使用的时候会被tree-shaking
掉,其实这应该是一个bug
。或者说是现在的webpack + uglyfy(terser)
目前没有实现的一个特性(类消除也是后面实现的),理论上编译器只有在静态分析100%确定没问题的情况下才会删,不会去分析程序流,意味着你的分包和插件在不使用的一些代码都会被打包进来。听起来可能不好理解,我们直接看代码,感兴趣的同学可以尝试下,分别放在[email protected]
和[email protected]
编译:[email protected]
下,不会被删掉;[email protected]
下如果入口文件沿用
[email protected]
的写法会带来几个问题:import
,require
,requirePlugin
等引入上下文会执行;影响包体的大小;
[email protected]
dev
环境不会tree-shaking
,参考上面的配置说明 【config/index
配置文件】;解决上面问题很简单,我们用
webpak + require + defineConstants
的方式对各个场景按需引入,比如:if (WEBPACK_CONST) { require('..') }
,当WEBPACK_CONST
(编译常量)为false
的时候,Webpack
编译分析不会把条件外的require
内容引入进来。有了这个结论我们就对入口文件进行了处理:咋一看,上面的文件是解决了,但是不太优雅,如果支持配置指定入口文件是不是更好。可惜的是,
[email protected]
在小程序场景中的将入口文件写死了app.x
,所以不得不使用这种方式去做到分入口加载。感兴趣的同学可以看看这个 PR,entryFileName
其实已经支持在H5
和RN
里面配置。包大小
玩游戏最怕的是”一顿操作猛如虎,一看战绩零杠五“。要是包大小不通过,所有的解决方案都是白忙活。下面是我通过开发者工具统计的包大小信息:
根据上面统计的信息,在主包,分包和插件场景下,现有的包大小没有超过原来的包大小。
总结
在这里,我们可以认为升级
Taro@3x
在现有的58体系里面是可行的,改动的范围也是可以接受的。我是从发布不久开始接入,可以说从
[email protected]
一路踩坑过来的,开始的时候因为api
改动大有点打击信心,但随着了解了一些运行机制之后和简单的开发体验后,越发觉得[email protected]
颠覆式的重构反而能让Taro
走的更远。有兴趣的同学可以按照上面的步骤进行升级,基本上没啥问题,有啥问题可以给提issue
提PR
,官方人手不多,一起帮忙加特性(改bug
)。还是那句话,”没有枪,没有炮,没有轮子自己造“。参考资料
[1] Taro 3 正式版发布:开放式跨端跨框架解决方案: https://aotu.io/notes/2020/06/30/taro-3-0-0/index.html
[2] 从旧版本迁移到 Taro Next: https://nervjs.github.io/taro/docs/migration
[3] Taro Next 发布预览版: [https://juejin.im/post/6844904063675400199](
The text was updated successfully, but these errors were encountered: