Giter Club home page Giter Club logo

remax's Introduction

Learn once, write anywhere
使用真正的 React 构建小程序

CI build status Codecov npm dingding

《使用 React 开发小程序》

Remax 将 React 运行在小程序环境中,让你可以使用完整的 React 进行小程序开发。

  • 真正的 React - 不同于静态编译的方案,在 Remax 中使用 React 没有任何限制,包括 React Hooks。你可以把 Remax 理解为针对小程序的 React Native。
  • 多端支持 - 使用 Remax 把代码转换到多个小程序平台。
  • TypeScript - 完整的 TypeScript 支持,给你满满的安全感。

文档

你可以从我们的网站上找到详细的文档。

也可以通过快速开始指南来立即体验 Remax。

示例

https://github.com/remaxjs/examples

贡献者

查看《贡献指南》

协议

MIT

remax's People

Contributors

afc163 avatar ahonn avatar arniu avatar chenshuai2144 avatar clarence-pan avatar colmugx avatar coppyc avatar darmody avatar dependabot-preview[bot] avatar dependabot[bot] avatar dominicleo avatar douxc avatar hehex9 avatar hellohejinyu avatar injs avatar ironlu233 avatar juvham avatar linjiajian999 avatar liujiayii avatar mushan0x0 avatar newset avatar noyobo avatar pochodaydayup avatar qc-l avatar rikumi avatar watsonhaw5566 avatar xcodebuild avatar yesmeck avatar yesw6a avatar yutingzhao1991 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

remax's Issues

支付宝小程序自主封装的组件状态报错!

支付宝小程序,自己封装的组件,添加和维护组件内的状态或者是逻辑,浏览器会报错。
目前试了 hook无状态组件和component都有此问题。
Cannot read property 'onShow' of null

多端代码统一的思考

长话短说

由于国内小程序众多,一套代码在多端运行的需求高涨,然而如果在lib 层面去做多端抹平,可以看到会有这些问题

  • 每个端对 api,组件的定义不同,lib 抹平后,如何让开发者更灵活地控制
  • 如果使用 typescript 编码,只能看到一份 type 定义,例如 Taro 看到的就是微信的 type 定义
  • 不同的小程序,特性不同,平台不同,需求不同(不论是整体还是细节),一套代码运行在多端本身是不是个伪命题?

我的建议:

  • remax 划分成 remax/alipay remax/wechat ...
  • 每个平台都完成各自的组件和 api
  • 毕竟大多数人只有一个小程序端的开发需求,可以直接对应平台完成工作
  • 有跨端开发需求的,通过脚手架引导开发者对不同平台的差异,根据具体业务做抹平处理。如:
// components/Button.js
import { Platform } from 'remax';
import { Button as AlipayButton } from 'remax/alipay';
import { Button as WechatButton } from 'remax/wechat';

export default function Button(props) {
  if (Platform.isWechat)  return <WechatButton {...props} />;
  if (Platform.isAlipay)  return <AlipaytButton {...props} />;
}

api 用相似的逻辑,根据具体业务做处理

提供 Page 类型

import { PageComponent } from 'remax';

const Page: PageComponent = ({ lifecyle }) => {

}

支付宝小程序自主封装的组件状态报错!

支付宝小程序,自己封装的组件,添加和维护组件内的状态或者是逻辑,浏览器会报错。
目前试了 hook无状态组件和component都有此问题。
Cannot read property 'onShow' of null

Error raised when component unmount

Here is a demo that can reproduce the bug.

export const App = () => {
  const [show, setShow] = React.useState(false);
  return (
    <View>
      {show && <text>hi</text>}
      <Button onClick={() => setShow(!show)}>click me</Button>
    </view>
  )
}

When clic the button twice you will see this error:

image

项目配置文件

区分不同端的配置文件:

  • 支付宝 app.alipay.json
  • 微信 app.weapp.json
  • ... 其他平台

支付宝小程序组件走查

所有组件都要测试一遍,看有没有问题和遗漏

视图容器

  • swiper
  • scroll-view
  • cover-view
  • movable-view
  • movable-area

基础内容

  • text
  • icon
  • progress
  • rich-text

表单组件

  • button
  • form
  • label
  • input
  • textarea
  • radio
  • radio-group
  • checkbox
  • checkbox-group
  • switch
  • slider
  • picker-view
  • picker

导航

  • navigator

媒体组件

  • image

画布

  • canvas

地图

  • map

开放组件

  • web-view
  • 关注生活号
  • 智能客服

在小程序中使用 React with Hooks

介绍一下 Remax

Remax 是一个跨多端小程序 React 开发方案,之所以称其为“方案”而非框架是因为这并非一个新的框架,其主要能力就是让 React 能够直接运行在 微信小程序/支付宝小程序/字节跳动小程序/H5(当然这个本来就支持) 等环境。

可能会有人要会问 “React 不是早就可以运行在小程序中了么“?本文会介绍一下现如今的一些小程序框架的解决方案,以及为什么我们认为把 React 直接搬进小程序是个更为合理的方案。

静态编译类框架

由于大多开发者都更熟悉 React 和 Vue 的 API 和语法,加上小程序本身的开发方式确实让人痛苦,于是便有了一些框架来将这些熟悉的语法编译到小程序的 WXML/WXSS/JS 上,其中比较具有代表性的例如 taro,其目标就是让开发者能够用 React 的开发方式编写小程序。

而这类框架的实现原理其实并非真的是一个 React 或者类 React 框架,而是把看起来像是 JSX 的模板通过静态编译的方式翻译成小程序自身的模板。

这样做的限制非常明显,那就是 JSX 是 JavaScript 的拓展语言(React Blog 写的是 is a syntax extension to JavaScript),而小程序所采用的 WXML 却是一个表达能力非常受限的模板语言,我们不可能完成从一个通用编程语言到模板语言的编译。

而静态编译类框架为了做到这一点,采取的方式就是限制开发者的写法,这也是为什么上面称之为看起来像是 JSX 的模板,这也是为什么 taro 对 JSX 的写法做出了诸多限制。

image
image
image
image

这种方案大多声称这些限制并没有限制生产力,或者符合最佳实践等等。然而我们其实都知道这是由于小程序本身的坑造成的,静态编译方案编译的永远都只会是模板语言,而不是 JSX。

React Hooks

之所以我说这些限制并非基于最佳实践,是因为 React 本身对于 JSX 的定位就 并非模板

JSX is a syntax extension to JavaScript.

在最近 React 团队已经向我们介绍了 Hooks,期望可以 functional component 不仅仅可以是无状态组件,也可以是 useState 的。

import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

React 官方博客提到 Classes confuse both people and machines,我们也明显可以看到基于 function 的组件明显更为简洁,噪声更小,未来 React 社区的方向更是会逐渐从 class component 过渡到 functional component。

在这种趋势下,把 JSX 当做模板写,且未来永远也不可能支持 functional component 的方案绝非真的基于最佳实践的选择。

在 Remax 中,我们完全可以使用全新的 Hooks API 来开发组件

image

因为 Remax 中的 React 就是 React.js,而 JSX 就是 JavaScript 的超集。

上图中使用小程序的原生语法,classname 和 inline style 就只能写成

<view class="weui-navbar__item {{activeIndex == index ? 'weui-bar__item_on' : ''}}">
</view>
<view style="left: {{sliderLeft}}px; transform: translateX({{sliderOffset}}px); -webkit-transform: translateX({{sliderOffset}}px);"></view>

而使用 remax 后就可以写成正常的 react:

 const innerStyle = {
    left: `${sliderLeft}px`,
    transform: `translateX(${sliderOffset}px);`,
    '-webkit-transform': `translateX(${sliderOffset}px)`,
    width: sliderWidth,
  };
const itemClassName = classnames({
   'weui-navbar__item': true,
    'weui-bar__item_on': activeIndex === index,
});

return <View className={itemClassName}>
    <View style={innerStyle} />
    </View>

实现原理

核心部分

Remax 的实现原理和基于静态编译的方案有所不同,其核心其实是重新实现了 ReactDOM 的部分。

众所周知,React 本身的设计就是支持跨端渲染的,render 部分和 React 的核心逻辑是解耦的(甚至不在一个 npm 包里)。主要的 render 有 ReactDOM(浏览器),ReactDOMServer(服务器端)和 ReactNative。

Remax 要做的事情和 ReactNative 要做的事情非常类似,我们重新接管了 ReactDOM 的 render。

在原有的 React 页面中,React 在完成 Diff 发现需要修改界面时,又 ReactDOM 把改变 Patch 到页面上。

image

而在小程序中由于我们不能直接修改页面,则由 React 完成 DIFF 后由 Remax 把修改 Patch 到内存中的虚拟 DOM 上,然后再通过小程序自己的虚拟 DOM 最后把改变同步到页面上。

image

在这里我把这个过程说得非常简单,但实际上是有些坑要填的,主要也都是来自于小程序的限制,后续会有新的文章展开来讲。但是这种实现方式使得我们完全可以把 React 的代码放在小程序的环境中运行。

工程化

工程化很理所当然的用 Webpack 来实现, 除了我们常用的打包等功能外,Webpack 插件也使我们很容易构建一些我们需要的东西出来,例如我们需要在每个 js 入口除了放一个 js 外还需要添加一个 wxml 文件,就可以通过一个很简单的 Webpack 插件来实现。

function GeneraeWxmlWebpackPlugin() {
  const content = `<view>...</view>`;
  const apply = (compiler) => {
    const emit = (compilation, cb) => {
      const {
        chunks,
      } = compilation;
      chunks.forEach((item) => {
        compilation.assets[`${item.name}.wxml`] = {
          source: () => content,
          size: () => content.length,
        };
      });

      cb();
    };

    if (compiler.hooks) {
      const plugin = { name: 'GeneraeWxmlWebpackPlugin' };
      compiler.hooks.emit.tapAsync(plugin, emit);
    } else {
      compiler.plugin('emit', emit);
    }
  };

  return {
    apply,
  };
}

跨端

这种方案想实现同一套代码跨到 H5 端显然没有什么问题,至于支付宝小程序目前验证了一下可行性也是可行的。

miniapp1

1547346366247-2ff00034-c5fc-449a-bc5c-7c65302c96b6

项目结构

这个项目主要由几块组成

  • @remax/core
    核心部分,负责 React 组件的 render
  • @remax/cli
    顾名思义,CLI 工具,用于构建生成相应的小程序项目等工作
  • @remax/components
    底层 Component,包括诸如 View 等一些基础组件,用于抹平不同环境的差异
  • @remax/ui
    自带的基础组件库,这部分还待开发,目前只有一两个示例组件

由于目前整个项目才刚刚起步,暂时还不能用于生产环境,目前的几个主要开发者(和打算参与的)有 @codefalling @bramblex @ahonn @SimplyY

目前的 DEMO 可以扫码体验:
image

或者在可以按照 https://github.com/CodeFalling/remax#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B 体验本地 DEMO。

如果有人想要参与进来一起开发可以联系我,开发相关的细节文档会陆续更新在 https://github.com/CodeFalling/remax/wiki/%E5%85%A5%E9%97%A8

推荐阅读

增加环境判断

import { REMAX } from 'remax'

const isWeapp = REMAX.TARGET.CURRENT === REMAX.TARGET.WEAPP
const isAlipay = REMAX.TARGET.CURRENT === REMAX.TARGET.ALIPAY

REMAX 作为常量,方便以后扩展

REMAX.TARGET 存储环境变量
REMAX.TARGET.CURRENT 当前环境
REMAX.TARGET.WEAPP 微信小程序对应常量值
REMAX.TARGET.ALIPAY 支付宝小程序对应常量值
... 其他平台

Class Component 导出有问题

这样导出会报错

export default class Component {}

但是下面这种写法没问题

class Component{};

export default Component;

集成测试

现在每个 PR 都需要手动 clone 下来编译,跑 demo 查看功能是否正常。

是否有办法加上集成测试和单元测试

引用小程序组件

import * as React from 'react';
import { View } from 'remax';
import Card from 'mini-antui/es/card/index'; // 小程序组件

export default () => {
  return (
    <View>
      <Card
        title="卡片标题2"
        subTitle="副标题非必填2"
        info="点击了第二个card"
      />
    </View>
  );
}

rollup watch 问题

  1. 删掉 entry 文件,watch 会报错
  2. 新增的 config.js 由于没有被真正的 import,也不会进入 watch

支持微信小程序吗

我看到Roadmap里,有微信小程序和WeUI。这个微信方面的功能,现在能使用了吗?

文档

  • 基础
    • 快速开始
    • 基本介绍
    • 样式
  • 指南
    • 跨端开发

支付宝小程序页面回调

小程序文档 https://docs.alipay.com/mini/framework/page-detail#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%87%BD%E6%95%B0

onShow

Class Method : onShow
Hook: useShow

Hook 用法:

const Page = ({ lifecycle }) => {
  lifecycle.useShow(() => { 
    console.log('page show');
  })
  
  return <div>Foo</div>;
}

export default Page;

onHide

Class Method: onHide
Hook: useHide 用法同上

onPullDownRefresh

Class Method: onPullDownRefresh
Hook: usePullDownRefresh 用法同上

onReachBottom

Class Method: onReachBottom
Hook: useReachBottom 用法同上

onPageScroll

Class Method: onPageScroll
Hook: usePageScroll 用法同上

onShareAppMessage

Class Method: onShareAppMessage
Hook: useShareAppMessage 用法同上

onTitleClick

Class Method: onTitleClick
Hook: useTitleClick 用法同上

onOptionMenuClick

Class Method: onOptionMenuClick
Hook: useOptionMenuClick 用法同上

onPopMenuClick

Class Method: onPopMenuClick
Hook: usePopMenuClick 用法同上

onPullIntercept

Class Method: onPullIntercept
Hook: usePullIntercept 用法同上

调整生命周期 hooks API

原来:

const Page = ({ lifecycle }) => {
  lifecycle.useShow(() => {
    console.log('hello');
  }); 

  return <View>123</View>;
}

调整为:

import { useShow } from 'remax';

const Page = () => {
  useShow(() => {
    console.log('hello');
  }); 

  return <View>123</View>;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.