字节跳动开发者工具_Chameleon 支持字节跳动小程序(附实现原理)

前言

Chameleon(简写 CML ) 团队秉承"一套代码运行多端,一端所见即多端所见"的初心,在最初支持 web weex wx 三端之后,凭借着多态协议设计思想,灵活的工程化配置,以及 跨端标准协议, CML 团队可以很快的扩展新端,比如支付宝小程序和百度小程序。

对于字节跳动小程序,考虑到 CML 开源社区的比较活跃,以及很多同行有着极大的兴趣共建,内部讨论之后,一致决定由外部贡献者根据跨端标准协议去扩展字节跳动小程序,目前已经完成了支持字节跳动小程序的开发。

对于已有的 CML 的项目按照接入字节跳动小程序步骤,即可直接复用;

CML 官方的体验仓库包括:cml-demo cml-flexbox cml-yanxuan cml-todomvc

地址在这里:https://github.com/chameleon-team

下载字节跳动小程序开发者工具:https://microapp.bytedance.com/docs/devtool/versionUpdate.html

clone 下来以上仓库之后,切换到 master-tt 分支,执行 cml tt dev,在开发者工具中即可预览效果;

以上项目在字节跳动小程序中的预览效果图如下:

5914034fc1f7e2347e28b4c9cae782dd.png

那么具体该如何接入字节跳动小程序呢?

一、如何接入字节跳动小程序

升级最新的 chameleon-tool

npm i chameleon-tool@0.4.0 -g

升级npm包,引入字节跳动小程序相关包

升级的包如下

"chameleon-api": "^0.5.3",

"chameleon-runtime": "0.1.4",

"chameleon-store": "0.0.3",

"chameleon-ui-builtin": "^0.4.1",

"cml-ui": "^0.3.1"

引入的新包如下

"cml-tt-api": "0.2.3",

"cml-tt-plugin": "0.2.3",

"cml-tt-runtime": "0.2.3",

"cml-tt-store": "0.2.3",

"cml-tt-ui": "0.2.3",

"cml-tt-ui-builtin": "0.2.3",

修改 chameleon.config.js 相关配置

1 引入 path 模块

const path = require('path')

2 新增配置

builtinNpmName: 'cml-tt-ui-builtin',

extPlatform: {

tt: 'cml-tt-plugin',

},

babelPath: [

path.join(__dirname,'node_modules/cml-tt-ui-builtin'),

path.join(__dirname,'node_modules/cml-tt-runtime'),

path.join(__dirname,'node_modules/cml-tt-api'),

path.join(__dirname,'node_modules/cml-tt-ui'),

path.join(__dirname,'node_modules/cml-tt-store'),

path.join(__dirname,'node_modules/cml-tt-mixins'),

path.join(__dirname,'node_modules/mobx'),

],

修改项目代码

1 修改项目中相关包的引用

import cml from "chameleon-api";

import store from "chameleon-store";

改为

import cml from "cml-tt-api";

import store from "cml-tt-stroe";

2 项目中开发者自定义的多态组件 以及 多态接口 都要增加字节跳动这一端的实现

详细教程参考:https://cmljs.org/doc/example/tt_miniapp.html

二、扩展字节跳动小程序日志

了解扩展新端标准编译侧的 webpack 原理

chameleon-tool 中对于外部扩展的 webpack 配置的源码 参考:https://github.com/didi/chameleon/blob/0.3.x-alpah-merge-mvvm/packages/chameleon-tool/configs/mvvm/getExtendConfig.js

这里重点讲下处理 .cml 后缀文件的 mvvm-cml-loader 和 mvvm-pack 中的MvvmGraphPlugin

配置如下

entry: {

app: path.join(cml.projectRoot, 'src/app/app.cml')

},

module: {

rules: [

...utils.styleLoaders({type}),

{

test: /\.cml$/,

use: [{

loader: 'mvvm-cml-loader',

options: {

loaders: getCmlLoaders(),

cmlType: type,

media,

check: cml.config.get().check

}

}]

}

]

},

plugins: [

new MvvmGraphPlugin({

cmlType: type,

media

}, platformPlugin)

]

mvvm-cml-loader 源码:https://github.com/didi/chameleon/blob/0.3.x-alpah-merge-mvvm/packages/mvvm-cml-loader/index.js

主要作用是以 app.cml 为入口,通过内联 loader 的形式循环递归的添加依赖,将所有的依赖添加到 webpack 构建过程中。

mvvm-pack 源码:https://github.com/didi/chameleon/tree/0.3.x-alpah-merge-mvvm/packages/mvvm-pack

mvvmGraphPlugin.js 中劫持了 webpack 的输出,通过 mvvmCompiler 生成构建图。

compiler.plugin('should-emit', function(compilation) {

try {

mvvmCompiler.run(compilation.modules);

} catch (e) {

cml.log.error(e);

}

// 返回false 不进入emit阶段

return false;

})

acfa37992bc7952265448e7bac810928.png

以上就是 CML 脚手架产生的树状结构图,递归传递给 cml-XX-plugin 来转义目标语法。

实现 cml-tt-plugin

目标:将 template、script、style 等节点编译成符合字节跳动小程序的语法,然后打包输出成符合字节跳动小程序的结构;

cml-tt-plugin:https://github.com/chameleon-team/cml-tt-sets/blob/master/packages/cml-tt-plugin/index.js

根据上面生成的构建图,贡献者在编译插件 cml-tt-plugin中可以对构建图中所有节点(包括 js 节点 json节点 style节点 template节点等)编译成符合要扩展的端的语法,然后在pack中可以进行打包输出成符合对应端的结构。

module.exports = class DemoPlugin {

constructor(options) {

......

}

/**

* @description 注册插件

* @param {compiler} 编译对象

* */

register(compiler) {

// 编译script节点,比如做模块化

compiler.hook('compile-script', function(currentNode, parentNodeType) {

})

// 编译template节点 语法转义

compiler.hook('compile-template', function(currentNode, parentNodeType) {

})

// 编译style节点 比如尺寸单位转义

compiler.hook('compile-style', function(currentNode, parentNodeType) {

})

// 编译结束进入打包阶段

compiler.hook('pack', function(projectGraph) {

// 遍历编译图的节点,进行各项目的拼接

// 调用writeFile方法写入文件

// compiler.writeFile()

})

......

}}

更为详细的 开发编译插件的教程 参考https://cml.js.org/doc/extend/start.html

以扩展字节跳动的 template 编译为例

compiler.hook('compile-template', function(currentNode, parentNodeType) {

// 部分template处理也需要用到options

const options = currentNode.extra;

currentNode.output = templateParser(currentNode.source, options)

})

这个templateParser函数就是将 CML 协议下的模板语法 转化为符合字节跳动小程序的语法

CML 协议下模板语法:https://cml.js.org/doc/extend/template.html

字节跳动小程序模板语法:https://developer.toutiao.com/docs/framework/ttml.html

c-if="{{value}}">

转化为

tt:if="{{value}}">

模板编译的具体实现参考:https://github.com/chameleon-team/cml-tt-sets/blob/master/packages/cml-tt-plugin/index.js

各个节点编译完之后,可以再 pack 阶段自定义打包,部分代码如下

compiler.hook('pack', function(projectGraph) {

let hasCompiledNode = [];

let bootstrapCode = compiler.amd.getModuleBootstrap();

compiler.writeFile('/static/js/manifest.js', bootstrapCode);

let commonjsContent = `var manifest = require('./manifest.js');\n`;

commonjsContent += `var cmldefine = manifest.cmldefine;\n`;

// 遍历节点

outputNode(projectGraph);

compiler.writeFile('/static/js/common.js', commonjsContent);

//...})

具体实现参考:https://github.com/chameleon-team/cml-tt-sets/blob/master/packages/cml-tt-plugin/index.js

实现 cml-tt-runtime

目标:实现运行时,代理字节跳动小程序 App,Page,Component 方法以及生命周期

cml-tt-runtime:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-runtime

运行时的主要作用是抹平各端的生命周期差异性,进行数据响应式绑定等 实现运行时的参考教程:https://cml.js.org/doc/extend/runtime.html

这里以page实现逻辑为例:

// 编译时自动插入用户配置的运行时方法

import {createPage} from 'cml-tt-runtime';

createPage(exports.default);

以上两行代码是在 mvvm-cml-loader 中插入的,具体实现参考源码:https://github.com/didi/chameleon/blob/0.3.x-alpah-merge-mvvm/packages/mvvm-cml-loader/selector.js

中对于 script 节点的处理;

我们只需要实现对应端的以下几个方法:

createApp createPage createComponent

具体实现参考:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-runtime/src/tt/instance

以 cml-tt-runtime 中的 createPage 实现为例:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-runtime

cml-tt-runtime/index.js

import { createApp } from './src/interfaces/createApp/index.js';

import { createPage } from './src/interfaces/createPage/index.js';

import { createComponent } from './src/interfaces/createComponent/index.js';

export default {

createApp,

createPage,

createComponent

}

cml-tt-runtime/src/interfaces/createPage/index.js

import createPgInterface from './index.interface';

export function createPage(options) {

return createPgInterface.createPage(options)

}

cml-tt-runtime/src/interfaces/createPage/index.interface

//这里要将 chameleon-runtime中的 createPage接口 include 进来

<include src="chameleon-runtime/src/interfaces/createPage/index.interface">include>

<script cml-type="tt"> import {Page} from '../../tt'

class Method implements createPageInterface {

createPage(options) {

return new Page(options);

}

}

export default new Method();

script>

实现 cml-tt-api

目标:基于跨端协议,实现字节跳动小程序对应的 API

cml-tt-api:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-api

实现API的部分特别简单,只需两步

第一:引入官方标准 interface 文件

第二:扩展实现新端,实现对应端的方法

具体实现如下:

cml-tt-api/src/interfaces/alert/index.interface

// 引入官方标准interface文件

<include src="chameleon-api/src/interfaces/alert/index.interface">include>

// 扩展实现新端,实现对应端的方法

<script cml-type="tt">class Method implements uiInterface {

alert(opt, successCallBack, failCallBack) {

let { message, confirmTitle} = opt;

tt.showModal({

title: confirmTitle,

content: message,

showCancel: false,

success() {

successCallBack(confirmTitle);

},

fail(){

failCallBack(confirmTitle);

}

});

}}

export default new Method();

script>

实现 cml-tt-store

目标:基于 mobx 实现一套响应式数据系统

cml-tt-store:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-store

实现 store 同样只需要两步:

第一:引入官方标准 interface 文件

第二:扩展实现新端,实现对应端的方法

//引入官方标准 interface 文件

<include src="chameleon-store/src/interfaces/createStore/index.interface">include>

<script cml-type="tt">

import createStore from '../../platform/tt'

//扩展实现新端,实现对应端的方法

class Method implements createStoreInterface {

createStore(options) {

return createStore(options)

}

}

export default new Method();

script>

具体实现代码参考:https://github.com/chameleon-team/cml-tt-sets/blob/master/packages/cml-tt-store/src/platform/common/mini/index.js

实现 cml-tt-ui-builtin 和 cml-tt-ui

目标:UI 组件库是用来实现多端一致性的基础,参考原有的组件库实现,可以快速扩展出字节跳动小程序端的 UI 组件。

cml-tt-ui:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-ui

cml-tt-ui-builtin:https://github.com/chameleon-team/cml-tt-sets/tree/master/packages/cml-tt-ui-builtin

扩展新端组件教程参考:https://cml.js.org/doc/extend/ui-builtin.html

共建成果

应社区内广大开发者的提议,CML 团队制定了一套 MVVM+ 的 协议标准,并且再此标准上,规定了 扩展新端标准流程 ,CML 团队和以上贡献者,紧密协作,共建字节跳动新端,不仅如期完成了各种支持库的开发,比如 cml-tt-ui cml-tt-api cml-tt-plugin cml-tt-mixins 等,同时还对已有的一些 CML 项目在字节跳动端的表现进行了多次的测试,在按照 接入字节跳动小程序步骤 操作之后,已有的 CML 项目可以在构建后直接运行在字节跳动小程序中。

随着越来越多的小程序厂商入局 CML 团队会秉着"一套代码运行多端,一端所见即多端所见"的理想,继续支持各个小程序的开发和应用.

550aeb012c5bfcf845108d1b7f9a8783.png

为你推荐

【第1551期】编写chameleon跨端组件的正确姿势

Chameleon团队发布第一个视频教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值