Skip to main content
MorJS can take a WeChat mini-program codebase and compile it to a fully functional Alipay mini-program. The compiler rewrites file extensions, transforms template directives, renames the global object, and injects a runtime shim that bridges API differences at runtime.

Configuration

Set sourceType to wechat and target to alipay in your mor.config.ts:
// mor.config.ts
import { defineConfig } from '@morjs/cli'

export default defineConfig([
  {
    name: 'alipay',
    sourceType: 'wechat',   // source DSL is WeChat
    target: 'alipay',       // compile to Alipay
    compileMode: 'bundle',
  }
])
sourceType defaults to wechat. If your project only has .wxml files and no .axml files, MorJS will auto-detect the DSL without an explicit setting.

File Extension Mapping

The compiler rewrites every source file extension to the Alipay equivalent:
WeChatAlipayPurpose
.wxml.axmlTemplate
.wxss.acssStyles
.wxs.sjsScript modules
.js.jsPage / component logic
.json.jsonConfiguration
The default output directory is dist/alipay.

Global Object: wxmy

Alipay exposes its API through my; WeChat uses wx. MorJS handles this transformation at compile time through the autoInjectRuntime.api setting, which accepts one of three modes defined in GlobalObjectTransformTypes:
Replaces wx with a MorJS proxy object (mor) and inserts a import-style injection at the top of each script file. The proxy holds a fully normalised API surface that maps WeChat calls to Alipay equivalents, including argument renaming, promise wrapping, and return-value mapping.
autoInjectRuntime: {
  api: 'enhanced'
}
This is the recommended mode. It enables the runtime API transform table described in the API Differences section below.
A lightweight textual replacement: every occurrence of the identifier wx is replaced with my. No additional import is injected. Use this when your code calls only APIs that have identical signatures on both platforms.
autoInjectRuntime: {
  api: 'lite'
}
Only replaces wx.<method>() call expressions — bare references like const g = wx are left untouched.
autoInjectRuntime: {
  api: 'minimal'
}

Template Directive Mapping

WeChat template directives (wx:) are rewritten to Alipay directives (a:) at compile time:
WeChat directiveAlipay directive
wx:ifa:if
wx:elifa:elif
wx:elsea:else
wx:fora:for
wx:for-itema:for-item
wx:for-indexa:for-index
wx:keya:key
Script module tags are also renamed:
WeChatAlipay
<wxs src="..." module="m"><import-sjs from="..." name="m" />
Alipay’s <import-sjs> tag does not support inline script content (isSupportSjsContent: false). Split any inline <wxs> blocks into separate .sjs files before migrating.

Runtime Injection: autoInjectRuntime

In enhanced mode, MorJS replaces the WeChat constructor calls with its own runtime wrappers so that Alipay-specific lifecycle conventions are satisfied automatically:
WeChat callInjected MorJS runtime
App({})aApp({}) from @morjs/runtime-mini
Page({})aPage({})
Component({})aComponent({})
Behavior({})mapped to Alipay Mixin({}) via behaviorOrMixin
You can selectively disable injection per entity:
autoInjectRuntime: {
  app: true,
  page: true,
  component: true,
  behavior: true,  // Behavior → Mixin for Alipay targets
  api: 'enhanced'
}

API Differences

The enhanced runtime (apisToAlipay.ts) translates the following WeChat APIs to their Alipay equivalents automatically. No code changes are required in your source.
WeChat APIAlipay APINotes
wx.showActionSheet({ itemList })my.showActionSheet({ items })Parameter renamed
wx.showToast({ title, icon })my.showToast({ content, type })icon: 'loading' delegates to my.showLoading
wx.showLoading({ title })my.showLoading({ content })Parameter renamed
wx.showModal()my.confirm() / my.alert()showCancel: false uses alert
wx.setNavigationBarTitlemy.setNavigationBarMapped
wx.setNavigationBarColormy.setNavigationBarMapped; front color auto-derived from background
wx.previewImage({ current, urls })my.previewImage({ current (index), urls })current converted from URL to numeric index

Component Lifecycle Mapping

WeChat and Alipay components have different lifecycle names. The aComponent runtime maps them:
WeChatAlipay
createdonInit
attacheddidMount (via composed lifecycle)
readydidMount
detacheddidUnmount
erroronError
The Behavior({}) constructor is mapped to Alipay’s Mixin({}) via the behaviorOrMixin runtime module.

Common Gotchas

Alipay’s <import-sjs> tag cannot contain inline script. Any WeChat page that embeds JS inside a <wxs> tag must have that code extracted into a separate .sjs file and referenced with from=.
Alipay does not support a raw style prop on custom components. MorJS automatically renames stylemorStyle on component nodes and adds a corresponding observer that copies the value back. Avoid passing computed style strings directly as style to custom components — use a wrapper view instead.
The Alipay compiler resolves npm package main fields in the order: alipaymodulemain. Ensure any cross-platform component library you depend on exports an alipay field in its package.json or the correct file will be missing.
Alipay compiles scripts to ES2015 with ESNext module syntax by default, whereas WeChat uses ES5 + CommonJS. Libraries that ship only CommonJS bundles may need to be processed via processNodeModules.
Alipay does not support setting styleIsolation through the Component constructor options. Set it in the component’s .json file instead:
{
  "component": true,
  "styleIsolation": "shared"
}
wx.createSelectorQuery().in(component) scopes query results to a component. Alipay’s equivalent does not take a component argument; the runtime shim keeps the .in() method but it has no effect. Queries will search the full page tree.

Conditional Compilation

Use MorJS conditional compilation to ship platform-specific code in the same source file:
// @morjs/cli strips blocks that don't match the current target
/* #if TARGET === 'alipay' */
my.alert({ content: 'Alipay only' })
/* #elif TARGET === 'wechat' */
wx.showModal({ title: 'WeChat only' })
/* #end */
File-level conditional compilation is also supported via the .wx.js / .my.js suffix convention configured in conditionalCompile.fileExt.

Build docs developers (and LLMs) love