From ebc78e8788f83e8fda0e146758af43b878125c10 Mon Sep 17 00:00:00 2001
From: "armslave.yy" <armslave.yy@alibaba-inc.com>
Date: Sat, 12 Sep 2020 17:46:44 +0800
Subject: [PATCH] refactor: code-generator code style
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

1. rax 出码合并
2. code style 修复

注：合并的代码中带了 datasource 的

Link: https://code.aone.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/codereview/3717159

* Merge branch 'feat/rax-code-generator' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into feat/rax-code-generator

# Conflicts:
#	packages/code-generator/src/generator/ProjectBuilder.ts
#	packages/code-generator/src/parser/SchemaParser.ts
#	packages/code-generator/src/plugins/component/rax/jsx.ts
#	packages/code-generator/src/plugins/project/constants.ts
#	packages/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
#	packages/code-generator/src/plugins/project/i18n.ts
#	packages/code-generator/src/publisher/disk/index.ts
#	packages/code-generator/src/publisher/disk/utils.ts
#	packages/code-generator/src/types/core.ts
#	packages/code-generator/src/types/schema.ts
#	packages/code-generator/src/utils/compositeType.ts
#	packages/code-generator/src/utils/nodeToJSX.ts

* refactor: code-generator

* Merge remote-tracking branch 'origin/refactor/code-style' into refactor/code-style-code-generator

# Conflicts:
#	.vscode/launch.json
---
 .eslintignore                                 |   2 +
 .vscode/launch.json                           |  11 +-
 packages/code-generator/.eslintignore         |   1 +
 packages/code-generator/README.md             |  26 +-
 packages/code-generator/build.json            |   5 +
 packages/code-generator/demo/demo.js          |  12 +-
 packages/code-generator/package.json          |  21 +-
 .../code-generator/src/const/generator.ts     |  33 +-
 .../src/generator/ChunkBuilder.ts             |   2 +
 .../src/generator/CodeBuilder.ts              |  38 +-
 .../src/generator/ModuleBuilder.ts            |  27 +-
 .../src/generator/ProjectBuilder.ts           |  57 ++-
 packages/code-generator/src/index.ts          |  14 +-
 .../code-generator/src/model/ResultDir.ts     |  33 --
 .../code-generator/src/model/ResultFile.ts    |  15 -
 .../code-generator/src/parser/SchemaParser.ts |  80 +--
 .../src/plugins/common/esmodule.ts            |  46 +-
 .../src/plugins/common/requireUtils.ts        |   8 +-
 .../src/plugins/component/rax/commonDeps.ts   |  35 ++
 .../src/plugins/component/rax/const.ts        |  18 +
 .../plugins/component/rax/containerClass.ts   | 144 ++++++
 .../component/rax/containerInitState.ts       |  68 +++
 .../component/rax/containerInjectContext.ts   | 116 +++++
 .../rax/containerInjectDataSourceEngine.ts    | 157 ++++++
 .../component/rax/containerInjectUtils.ts     |  74 +++
 .../component/rax/containerLifeCycle.ts       | 120 +++++
 .../plugins/component/rax/containerMethods.ts |  95 ++++
 .../src/plugins/component/rax/jsx.ts          | 350 +++++++++++++
 .../plugins/component/react/containerClass.ts |  26 +-
 .../component/react/containerDataSource.ts    |   7 +-
 .../component/react/containerInitState.ts     |   6 +-
 .../component/react/containerLifeCycle.ts     |   2 +-
 .../component/react/containerMethod.ts        |   2 +-
 .../src/plugins/component/react/jsx.ts        |  15 +-
 .../component/react/reactCommonDeps.ts        |   1 -
 .../src/plugins/component/recore/const.ts     |   3 -
 .../component/recore/pageDataSource.ts        |  13 +-
 .../src/plugins/component/recore/pageStyle.ts |   2 +-
 .../plugins/component/recore/pageVmBody.ts    |  30 +-
 .../plugins/component/recore/pageVmHeader.ts  |   7 +-
 .../src/plugins/project/constants.ts          |  59 ++-
 .../project/framework/icejs/plugins/entry.ts  |   8 +-
 .../framework/icejs/plugins/entryHtml.ts      |   4 +-
 .../framework/icejs/plugins/packageJSON.ts    |   9 +-
 .../project/framework/icejs/plugins/router.ts |   4 +-
 .../icejs/template/files/README.md.ts         |   8 +-
 .../icejs/template/files/abc.json.ts          |  20 +-
 .../icejs/template/files/build.json.ts        |  22 +-
 .../icejs/template/files/editorconfig.ts      |   8 +-
 .../icejs/template/files/eslintignore.ts      |   8 +-
 .../icejs/template/files/eslintrc.js.ts       |   8 +-
 .../icejs/template/files/gitignore.ts         |   8 +-
 .../icejs/template/files/jsconfig.json.ts     |   8 +-
 .../icejs/template/files/prettierignore.ts    |   8 +-
 .../icejs/template/files/prettierrc.js.ts     |   8 +-
 .../components/Footer/index.jsx.ts            |   8 +-
 .../components/Footer/index.module.scss.ts    |   8 +-
 .../BasicLayout/components/Logo/index.jsx.ts  |   8 +-
 .../components/Logo/index.module.scss.ts      |   8 +-
 .../components/PageNav/index.jsx.ts           |   8 +-
 .../src/layouts/BasicLayout/index.jsx.ts      |   8 +-
 .../src/layouts/BasicLayout/menuConfig.js.ts  |   8 +-
 .../icejs/template/files/stylelintignore.ts   |   8 +-
 .../icejs/template/files/stylelintrc.js.ts    |   8 +-
 .../icejs/template/files/tsconfig.json.ts     |   8 +-
 .../project/framework/icejs/template/index.ts |  13 +-
 .../plugins/project/framework/rax/index.ts    |  19 +
 .../framework/rax/plugins/appConfig.ts        |  46 ++
 .../framework/rax/plugins/buildConfig.ts      |  52 ++
 .../project/framework/rax/plugins/entry.ts    |  51 ++
 .../framework/rax/plugins/entryDocument.ts    |  59 +++
 .../framework/rax/plugins/globalStyle.ts      |  64 +++
 .../framework/rax/plugins/packageJSON.ts      | 115 +++++
 .../framework/rax/template/files/README.md.ts |  27 +
 .../framework/rax/template/files/abc.json.ts  |  19 +
 .../rax/template/files/build.json.ts          |  24 +
 .../rax/template/files/editorconfig.ts        |  25 +
 .../rax/template/files/eslintignore.ts        |  23 +
 .../rax/template/files/eslintrc.js.ts         |  16 +
 .../framework/rax/template/files/gitignore.ts |  29 ++
 .../project/framework/rax/template/index.ts   |  78 +++
 .../recore/template/files/.editorconfig.ts    |  10 +-
 .../recore/template/files/.eslintignore.ts    |   9 +-
 .../recore/template/files/.gitignore.ts       |  10 +-
 .../recore/template/files/.prettierrc.ts      |  10 +-
 .../recore/template/files/README.md.ts        |   9 +-
 .../recore/template/files/abc.json.ts         |   9 +-
 .../recore/template/files/build.json.ts       |   9 +-
 .../recore/template/files/package.json.ts     |   9 +-
 .../template/files/public/index.html.ts       |   9 +-
 .../template/files/src/config/app.ts.ts       |   9 +-
 .../files/src/config/components.ts.ts         |  11 +-
 .../template/files/src/config/utils.ts.ts     |   9 +-
 .../recore/template/files/src/index.ts.ts     |   9 +-
 .../recore/template/files/src/router.ts.ts    |   9 +-
 .../recore/template/files/tsconfig.json.ts    |   9 +-
 .../framework/recore/template/index.ts        |  12 +-
 .../src/plugins/project/i18n.ts               | 104 ++--
 .../src/plugins/project/utils.ts              |  12 +-
 .../src/postprocessor/prettier/index.ts       |   2 +
 .../src/publisher/disk/index.ts               |  35 +-
 .../src/publisher/disk/utils.ts               |  48 +-
 .../code-generator/src/publisher/zip/index.ts |  11 +-
 .../code-generator/src/publisher/zip/utils.ts |  26 +-
 .../code-generator/src/solutions/rax-app.ts   |  66 +++
 packages/code-generator/src/types/core.ts     | 135 ++---
 packages/code-generator/src/types/deps.ts     |   2 +-
 packages/code-generator/src/types/error.ts    |  13 +-
 packages/code-generator/src/types/index.ts    |   3 +-
 .../code-generator/src/types/intermediate.ts  |  44 +-
 packages/code-generator/src/types/jsx.ts      |  29 ++
 .../code-generator/src/types/publisher.ts     |  10 +-
 packages/code-generator/src/types/result.ts   |  88 ----
 packages/code-generator/src/types/schema.ts   | 241 ---------
 .../code-generator/src/utils/OrderedSet.ts    |  33 ++
 packages/code-generator/src/utils/Scope.ts    |  27 +
 .../code-generator/src/utils/ScopeBindings.ts |  56 ++
 .../code-generator/src/utils/aopHelper.ts     |  28 +
 packages/code-generator/src/utils/common.ts   |   4 +-
 .../code-generator/src/utils/compositeType.ts | 187 ++++---
 .../src/utils/expressionParser.ts             | 243 +++++++++
 .../code-generator/src/utils/jsExpression.ts  |  21 +-
 packages/code-generator/src/utils/jsSlot.ts   |  40 +-
 .../code-generator/src/utils/nodeToJSX.ts     | 482 ++++++++++--------
 .../code-generator/src/utils/resultHelper.ts  |  35 ++
 packages/code-generator/src/utils/schema.ts   |  87 ++++
 .../src/utils/templateHelper.ts               |  22 +-
 packages/code-generator/src/utils/version.ts  |  29 ++
 packages/code-generator/test-cases/.gitignore |   1 +
 .../demo1/expected/demo-project/.editorconfig |  12 +
 .../demo1/expected/demo-project/.eslintignore |  11 +
 .../demo1/expected/demo-project/.eslintrc.js  |   3 +
 .../demo1/expected/demo-project/.gitignore    |  17 +
 .../demo1/expected/demo-project/README.md     |  15 +
 .../demo1/expected/demo-project/abc.json      |   7 +
 .../demo1/expected/demo-project/build.json    |  12 +
 .../demo1/expected/demo-project/package.json  |  37 ++
 .../demo1/expected/demo-project/src/app.js    |   6 +
 .../demo1/expected/demo-project/src/app.json  |  11 +
 .../expected/demo-project/src/constants.js    |   3 +
 .../demo-project/src/document/index.jsx       |  25 +
 .../expected/demo-project/src/global.scss     |   3 +
 .../demo1/expected/demo-project/src/i18n.js   |  31 ++
 .../demo-project/src/pages/Home/index.css     |   0
 .../demo-project/src/pages/Home/index.jsx     | 157 ++++++
 .../demo1/expected/demo-project/src/utils.js  |   1 +
 .../test-cases/rax-app/demo1/schema.json5     |  55 ++
 .../demo2/expected/demo-project/.editorconfig |  12 +
 .../demo2/expected/demo-project/.eslintignore |  11 +
 .../demo2/expected/demo-project/.eslintrc.js  |   3 +
 .../demo2/expected/demo-project/.gitignore    |  17 +
 .../demo2/expected/demo-project/README.md     |  15 +
 .../demo2/expected/demo-project/abc.json      |   7 +
 .../demo2/expected/demo-project/build.json    |  12 +
 .../demo2/expected/demo-project/package.json  |  41 ++
 .../demo2/expected/demo-project/src/app.js    |   6 +
 .../demo2/expected/demo-project/src/app.json  |  11 +
 .../expected/demo-project/src/constants.js    |   3 +
 .../demo-project/src/document/index.jsx       |  25 +
 .../expected/demo-project/src/global.scss     |   9 +
 .../demo2/expected/demo-project/src/i18n.js   |  31 ++
 .../demo-project/src/pages/Home/index.css     |   0
 .../demo-project/src/pages/Home/index.jsx     | 340 ++++++++++++
 .../demo2/expected/demo-project/src/utils.js  |  26 +
 .../test-cases/rax-app/demo2/schema.json5     | 375 ++++++++++++++
 .../demo3/expected/demo-project/.editorconfig |  12 +
 .../demo3/expected/demo-project/.eslintignore |  11 +
 .../demo3/expected/demo-project/.eslintrc.js  |   3 +
 .../demo3/expected/demo-project/.gitignore    |  17 +
 .../demo3/expected/demo-project/README.md     |  15 +
 .../demo3/expected/demo-project/abc.json      |   7 +
 .../demo3/expected/demo-project/build.json    |  12 +
 .../demo3/expected/demo-project/package.json  |  39 ++
 .../demo3/expected/demo-project/src/app.js    |   6 +
 .../demo3/expected/demo-project/src/app.json  |  19 +
 .../expected/demo-project/src/constants.js    |   3 +
 .../demo-project/src/document/index.jsx       |  25 +
 .../expected/demo-project/src/global.scss     |   9 +
 .../demo3/expected/demo-project/src/i18n.js   |  31 ++
 .../demo-project/src/pages/Detail/index.css   |   0
 .../demo-project/src/pages/Detail/index.jsx   | 168 ++++++
 .../demo-project/src/pages/Home/index.css     |   0
 .../demo-project/src/pages/Home/index.jsx     | 168 ++++++
 .../demo-project/src/pages/List/index.css     |   0
 .../demo-project/src/pages/List/index.jsx     | 171 +++++++
 .../demo3/expected/demo-project/src/utils.js  |   1 +
 .../test-cases/rax-app/demo3/schema.json5     | 176 +++++++
 .../test-cases/rax-app/demo4/README.md        |   1 +
 .../demo4/expected/demo-project/.editorconfig |  12 +
 .../demo4/expected/demo-project/.eslintignore |  11 +
 .../demo4/expected/demo-project/.eslintrc.js  |   3 +
 .../demo4/expected/demo-project/.gitignore    |  17 +
 .../demo4/expected/demo-project/README.md     |  15 +
 .../demo4/expected/demo-project/abc.json      |   7 +
 .../demo4/expected/demo-project/build.json    |  15 +
 .../demo4/expected/demo-project/package.json  |  39 ++
 .../demo4/expected/demo-project/src/app.js    |   6 +
 .../demo4/expected/demo-project/src/app.json  |  11 +
 .../expected/demo-project/src/constants.js    |   3 +
 .../demo-project/src/document/index.jsx       |  25 +
 .../expected/demo-project/src/global.scss     |   9 +
 .../demo4/expected/demo-project/src/i18n.js   |  31 ++
 .../demo-project/src/pages/Home/index.css     |   0
 .../demo-project/src/pages/Home/index.jsx     | 165 ++++++
 .../demo4/expected/demo-project/src/utils.js  |   1 +
 .../test-cases/rax-app/demo4/schema.json5     |  85 +++
 .../demo5/expected/demo-project/.editorconfig |  12 +
 .../demo5/expected/demo-project/.eslintignore |  11 +
 .../demo5/expected/demo-project/.eslintrc.js  |   3 +
 .../demo5/expected/demo-project/.gitignore    |  17 +
 .../demo5/expected/demo-project/README.md     |  15 +
 .../demo5/expected/demo-project/abc.json      |   7 +
 .../demo5/expected/demo-project/build.json    |  12 +
 .../demo5/expected/demo-project/package.json  |  37 ++
 .../demo5/expected/demo-project/src/app.js    |   6 +
 .../demo5/expected/demo-project/src/app.json  |  11 +
 .../expected/demo-project/src/constants.js    |   3 +
 .../demo-project/src/document/index.jsx       |  25 +
 .../expected/demo-project/src/global.scss     |   3 +
 .../demo5/expected/demo-project/src/i18n.js   |  38 ++
 .../demo-project/src/pages/Home/index.css     |   0
 .../demo-project/src/pages/Home/index.jsx     | 163 ++++++
 .../demo5/expected/demo-project/src/utils.js  |   1 +
 .../test-cases/rax-app/demo5/schema.json5     |  73 +++
 packages/code-generator/test/rax-app.test.ts  | 118 +++++
 ...parseExpressionConvertThis2Context.test.ts |  79 +++
 .../parseExpressionGetGlobalVariables.test.ts | 114 +++++
 .../code-generator/test/utils/version.test.ts |  50 ++
 .../code-generator/tools/createTemplate.js    |  10 +-
 packages/code-generator/tsconfig.json         |  11 +-
 packages/datasource-engine/.gitignore         |   5 +
 .../handlers/fetch/index.d.ts                 |   1 +
 .../datasource-engine/handlers/fetch/index.js |   1 +
 .../handlers/mtop/index.d.ts                  |   1 +
 .../datasource-engine/handlers/mtop/index.js  |   1 +
 .../handlers/url-params/index.d.ts            |   1 +
 .../handlers/url-params/index.js              |   1 +
 packages/datasource-engine/package.json       |  34 ++
 .../src/core/DataSourceEngine.ts              | 121 +++++
 .../src/core/RuntimeDataSource.ts             |  91 ++++
 packages/datasource-engine/src/core/index.ts  |   1 +
 .../datasource-engine/src/handlers/fetch.ts   |  24 +
 .../datasource-engine/src/handlers/mtop.ts    |  18 +
 .../src/handlers/url-params.ts                |  12 +
 packages/datasource-engine/src/index.ts       |   2 +
 .../src/types/DataSourceConfig.ts             |   6 +
 .../src/types/DataSourceConfigItem.ts         |  17 +
 .../src/types/DataSourceEngineOptions.ts      |   7 +
 .../src/types/DataSourceOptions.ts            |  10 +
 .../src/types/DataSourceResponse.ts           |   3 +
 .../src/types/IDataSourceEngine.ts            |   9 +
 .../src/types/IDataSourceEngineFactory.ts     |  12 +
 .../src/types/IRuntimeContext.ts              |  24 +
 .../src/types/IRuntimeDataSource.ts           |  22 +
 .../src/types/RequestHandler.ts               |   7 +
 .../src/types/RuntimeDataSourceStatus.ts      |  14 +
 packages/datasource-engine/src/types/index.ts |   1 +
 packages/datasource-engine/src/typing.d.ts    |   1 +
 packages/datasource-engine/tsconfig.json      |  80 +++
 packages/types/src/code-intermediate.ts       |  14 +
 packages/types/src/code-result.ts             |  59 +++
 packages/types/src/data-source.ts             |  26 +-
 packages/types/src/index.ts                   |   2 +
 packages/types/src/schema.ts                  |  41 +-
 packages/types/src/utils.ts                   |  22 +-
 packages/types/src/value-type.ts              |  35 +-
 266 files changed, 7819 insertions(+), 1393 deletions(-)
 create mode 100644 packages/code-generator/.eslintignore
 create mode 100644 packages/code-generator/build.json
 delete mode 100644 packages/code-generator/src/model/ResultDir.ts
 delete mode 100644 packages/code-generator/src/model/ResultFile.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/commonDeps.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/const.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerClass.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerInitState.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerInjectContext.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerLifeCycle.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/containerMethods.ts
 create mode 100644 packages/code-generator/src/plugins/component/rax/jsx.ts
 delete mode 100644 packages/code-generator/src/plugins/component/recore/const.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/index.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/appConfig.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/buildConfig.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/entry.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/entryDocument.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/globalStyle.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/README.md.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/abc.json.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/build.json.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/editorconfig.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/eslintignore.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/eslintrc.js.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/files/gitignore.ts
 create mode 100644 packages/code-generator/src/plugins/project/framework/rax/template/index.ts
 create mode 100644 packages/code-generator/src/solutions/rax-app.ts
 create mode 100644 packages/code-generator/src/types/jsx.ts
 delete mode 100644 packages/code-generator/src/types/result.ts
 delete mode 100644 packages/code-generator/src/types/schema.ts
 create mode 100644 packages/code-generator/src/utils/OrderedSet.ts
 create mode 100644 packages/code-generator/src/utils/Scope.ts
 create mode 100644 packages/code-generator/src/utils/ScopeBindings.ts
 create mode 100644 packages/code-generator/src/utils/aopHelper.ts
 create mode 100644 packages/code-generator/src/utils/expressionParser.ts
 create mode 100644 packages/code-generator/src/utils/resultHelper.ts
 create mode 100644 packages/code-generator/src/utils/schema.ts
 create mode 100644 packages/code-generator/src/utils/version.ts
 create mode 100644 packages/code-generator/test-cases/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.editorconfig
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintrc.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/abc.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/build.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/package.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/constants.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/document/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/global.scss
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/i18n.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/utils.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo1/schema.json5
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.editorconfig
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintrc.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/abc.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/build.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/package.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/constants.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/document/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/global.scss
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/i18n.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/utils.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo2/schema.json5
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.editorconfig
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintrc.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/abc.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/build.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/package.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/constants.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/document/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/global.scss
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/i18n.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/utils.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo3/schema.json5
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.editorconfig
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintrc.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/abc.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/build.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/package.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/constants.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/document/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/global.scss
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/i18n.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/utils.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo4/schema.json5
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.editorconfig
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintrc.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.gitignore
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/README.md
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/abc.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/build.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/package.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.json
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/constants.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/document/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/global.scss
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/i18n.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.css
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.jsx
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/utils.js
 create mode 100644 packages/code-generator/test-cases/rax-app/demo5/schema.json5
 create mode 100644 packages/code-generator/test/rax-app.test.ts
 create mode 100644 packages/code-generator/test/utils/expressionParser/parseExpressionConvertThis2Context.test.ts
 create mode 100644 packages/code-generator/test/utils/expressionParser/parseExpressionGetGlobalVariables.test.ts
 create mode 100644 packages/code-generator/test/utils/version.test.ts
 create mode 100644 packages/datasource-engine/.gitignore
 create mode 100644 packages/datasource-engine/handlers/fetch/index.d.ts
 create mode 100644 packages/datasource-engine/handlers/fetch/index.js
 create mode 100644 packages/datasource-engine/handlers/mtop/index.d.ts
 create mode 100644 packages/datasource-engine/handlers/mtop/index.js
 create mode 100644 packages/datasource-engine/handlers/url-params/index.d.ts
 create mode 100644 packages/datasource-engine/handlers/url-params/index.js
 create mode 100644 packages/datasource-engine/package.json
 create mode 100644 packages/datasource-engine/src/core/DataSourceEngine.ts
 create mode 100644 packages/datasource-engine/src/core/RuntimeDataSource.ts
 create mode 100644 packages/datasource-engine/src/core/index.ts
 create mode 100644 packages/datasource-engine/src/handlers/fetch.ts
 create mode 100644 packages/datasource-engine/src/handlers/mtop.ts
 create mode 100644 packages/datasource-engine/src/handlers/url-params.ts
 create mode 100644 packages/datasource-engine/src/index.ts
 create mode 100644 packages/datasource-engine/src/types/DataSourceConfig.ts
 create mode 100644 packages/datasource-engine/src/types/DataSourceConfigItem.ts
 create mode 100644 packages/datasource-engine/src/types/DataSourceEngineOptions.ts
 create mode 100644 packages/datasource-engine/src/types/DataSourceOptions.ts
 create mode 100644 packages/datasource-engine/src/types/DataSourceResponse.ts
 create mode 100644 packages/datasource-engine/src/types/IDataSourceEngine.ts
 create mode 100644 packages/datasource-engine/src/types/IDataSourceEngineFactory.ts
 create mode 100644 packages/datasource-engine/src/types/IRuntimeContext.ts
 create mode 100644 packages/datasource-engine/src/types/IRuntimeDataSource.ts
 create mode 100644 packages/datasource-engine/src/types/RequestHandler.ts
 create mode 100644 packages/datasource-engine/src/types/RuntimeDataSourceStatus.ts
 create mode 100644 packages/datasource-engine/src/types/index.ts
 create mode 100644 packages/datasource-engine/src/typing.d.ts
 create mode 100644 packages/datasource-engine/tsconfig.json
 create mode 100644 packages/types/src/code-intermediate.ts
 create mode 100644 packages/types/src/code-result.ts

diff --git a/.eslintignore b/.eslintignore
index eaf713eb7..7b0cf9688 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,5 +1,7 @@
 # 忽略目录
 node_modules
+test-cases
+output
 build
 dist
 demo
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 98523af22..68ac35b55 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -9,7 +9,16 @@
       "type": "node",
       "request": "launch",
       "runtimeExecutable": "${workspaceFolder}/packages/material-parser/node_modules/.bin/ava",
-      "runtimeArgs": ["debug", "--break", "${workspaceFolder}/packages/material-parser/test/antd.ts"]
+      "runtimeArgs": ["debug", "--break", "${file}"]
+    },
+    {
+      "name": "ava code-gen",
+      "type": "node",
+      "request": "launch",
+      "runtimeExecutable": "node",
+      "runtimeArgs": ["${workspaceFolder}/node_modules/.bin/ava", "--serial", "${file}"],
+      "cwd": "${workspaceFolder}/packages/code-generator",
+      "outputCapture": "std"
     }
   ]
 }
diff --git a/packages/code-generator/.eslintignore b/packages/code-generator/.eslintignore
new file mode 100644
index 000000000..bcfd4b921
--- /dev/null
+++ b/packages/code-generator/.eslintignore
@@ -0,0 +1 @@
+test-cases/
diff --git a/packages/code-generator/README.md b/packages/code-generator/README.md
index fe71e6c6a..35b2d9aba 100644
--- a/packages/code-generator/README.md
+++ b/packages/code-generator/README.md
@@ -1,9 +1,31 @@
 # 出码模块
 
+详细介绍看这里：<https://yuque.antfin-inc.com/docs/share/2b342641-6e01-4c77-b8e0-30421f55f69b>
+
 ## 安装接入
 
-
 ## 自定义导出
 
-
 ## 开始开发
+
+本项目隶属于 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine), 需要和整个 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine) 一起开发。
+
+所以先要初始化整个 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine) 的环境：
+
+1. 克隆 [ali-lowcode-engine](http://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine): `git clone git@gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine.git`
+2. 运行 `setup` 脚本，初始化环境： `npm run setup`
+
+然后，因为本项目依赖 `@ali/lowcode-types` 所以需要先构建下 `type`，即执行: `lerna run build --scope @ali/lowcode-types`
+
+最后，可以运行 `npm start` 命令启动本地调试（本项目通过 `ava` 进行单元测试，故 `start` 脚本其实就是 `watch` 模式的 `ava`):
+
+```sh
+# 到本项目目录下执行：（推荐）
+npm start
+
+# 或直接执行 ava：
+npx ava --watch
+
+# 或在 ali-lowcode-engine 工程根目录下执行: (不推荐，因为命令太长而且没法响应输入)
+lerna run start --stream --scope @ali/lowcode-code-generator
+```
diff --git a/packages/code-generator/build.json b/packages/code-generator/build.json
new file mode 100644
index 000000000..bd5cf18dd
--- /dev/null
+++ b/packages/code-generator/build.json
@@ -0,0 +1,5 @@
+{
+  "plugins": [
+    "build-plugin-component"
+  ]
+}
diff --git a/packages/code-generator/demo/demo.js b/packages/code-generator/demo/demo.js
index 1c760446d..2b6e02f52 100644
--- a/packages/code-generator/demo/demo.js
+++ b/packages/code-generator/demo/demo.js
@@ -59,7 +59,9 @@ function main() {
 
   builder.generateProject(schemaJson).then((result) => {
     displayResultInConsole(result);
-    writeResultToDisk(result, 'output/lowcodeDemo').then((response) => console.log('Write to disk: ', JSON.stringify(response)));
+    writeResultToDisk(result, 'output/lowcodeDemo').then((response) =>
+      console.log('Write to disk: ', JSON.stringify(response)),
+    );
     return result;
   });
 }
@@ -160,12 +162,14 @@ function exportProject() {
 
   builder.generateProject(schemaJson).then((result) => {
     displayResultInConsole(result);
-    writeResultToDisk(result, 'output/lowcodeDemo').then((response) => console.log('Write to disk: ', JSON.stringify(response)));
+    writeResultToDisk(result, 'output/lowcodeDemo').then((response) =>
+      console.log('Write to disk: ', JSON.stringify(response)),
+    );
     return result;
   });
 }
 
 // main();
 // exportModule();
-// exportProject();
-demo();
+exportProject();
+// demo();
diff --git a/packages/code-generator/package.json b/packages/code-generator/package.json
index 3d9840d6a..dd87e5f0a 100644
--- a/packages/code-generator/package.json
+++ b/packages/code-generator/package.json
@@ -3,18 +3,23 @@
   "version": "1.0.8-0",
   "description": "出码引擎 for LowCode Engine",
   "main": "lib/index.js",
+  "module": "es/index.js",
+  "typings": "es/index.d.ts",
   "files": [
     "lib",
+    "es",
     "demo"
   ],
   "scripts": {
-    "build": "rimraf lib && tsc",
+    "start": "ava --watch",
+    "build": "rimraf lib && build-scripts build --skip-demo",
     "demo": "node ./demo/demo.js",
     "test": "ava",
     "template": "node ./tools/createTemplate.js"
   },
   "dependencies": {
     "@ali/am-eslint-config": "*",
+    "@ali/lowcode-types": "^0.8.14",
     "@ali/my-prettier": "^1.0.0",
     "@babel/generator": "^7.9.5",
     "@babel/parser": "^7.9.4",
@@ -24,24 +29,34 @@
     "change-case": "^3.1.0",
     "jszip": "^3.5.0",
     "prettier": "^2.0.2",
+    "semver": "^7.3.2",
     "short-uuid": "^3.1.1"
   },
   "devDependencies": {
+    "@alib/build-scripts": "^0.1.18",
     "@types/babel__traverse": "^7.0.10",
     "ava": "^1.0.1",
     "rimraf": "^3.0.2",
     "ts-loader": "^6.2.2",
-    "ts-node": "^7.0.1",
+    "ts-node": "^8.10.2",
     "tsconfig-paths": "^3.9.0"
   },
   "ava": {
     "compileEnhancements": false,
     "snapshotDir": "test/fixtures/__snapshots__",
+    "files": [
+      "test/**/*.test.ts"
+    ],
     "extensions": [
       "ts"
     ],
     "require": [
-      "ts-node/register"
+      "ts-node/register/transpile-only"
+    ],
+    "sources": [
+      "src/**/*",
+      "test/**/*",
+      "test-cases/**/expected/**/*"
     ]
   },
   "publishConfig": {
diff --git a/packages/code-generator/src/const/generator.ts b/packages/code-generator/src/const/generator.ts
index 3d3950420..11fe67b81 100644
--- a/packages/code-generator/src/const/generator.ts
+++ b/packages/code-generator/src/const/generator.ts
@@ -1,6 +1,7 @@
 export const COMMON_CHUNK_NAME = {
   ExternalDepsImport: 'CommonExternalDependencyImport',
   InternalDepsImport: 'CommonInternalDependencyImport',
+  ImportAliasDefine: 'CommonImportAliasDefine',
   FileVarDefine: 'CommonFileScopeVarDefine',
   FileUtilDefine: 'CommonFileScopeMethodDefine',
   FileMainContent: 'CommonFileMainContent',
@@ -21,24 +22,29 @@ export const CLASS_DEFINE_CHUNK_NAME = {
   InsVar: 'CommonClassDefineInsVar',
   InsVarMethod: 'CommonClassDefineInsVarMethod',
   InsMethod: 'CommonClassDefineInsMethod',
+  InsPrivateMethod: 'CommonClassDefineInsPrivateMethod',
   End: 'CommonClassDefineEnd',
 };
 
 export const DEFAULT_LINK_AFTER = {
   [COMMON_CHUNK_NAME.ExternalDepsImport]: [],
   [COMMON_CHUNK_NAME.InternalDepsImport]: [COMMON_CHUNK_NAME.ExternalDepsImport],
+  [COMMON_CHUNK_NAME.ImportAliasDefine]: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
   [COMMON_CHUNK_NAME.FileVarDefine]: [
     COMMON_CHUNK_NAME.ExternalDepsImport,
     COMMON_CHUNK_NAME.InternalDepsImport,
+    COMMON_CHUNK_NAME.ImportAliasDefine,
   ],
   [COMMON_CHUNK_NAME.FileUtilDefine]: [
     COMMON_CHUNK_NAME.ExternalDepsImport,
     COMMON_CHUNK_NAME.InternalDepsImport,
+    COMMON_CHUNK_NAME.ImportAliasDefine,
     COMMON_CHUNK_NAME.FileVarDefine,
   ],
   [CLASS_DEFINE_CHUNK_NAME.Start]: [
     COMMON_CHUNK_NAME.ExternalDepsImport,
     COMMON_CHUNK_NAME.InternalDepsImport,
+    COMMON_CHUNK_NAME.ImportAliasDefine,
     COMMON_CHUNK_NAME.FileVarDefine,
     COMMON_CHUNK_NAME.FileUtilDefine,
   ],
@@ -49,20 +55,13 @@ export const DEFAULT_LINK_AFTER = {
     CLASS_DEFINE_CHUNK_NAME.InsVar,
     CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
   ],
-  [CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [
-    CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
-  ],
+  [CLASS_DEFINE_CHUNK_NAME.ConstructorContent]: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart],
   [CLASS_DEFINE_CHUNK_NAME.ConstructorEnd]: [
     CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
     CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
   ],
-  [CLASS_DEFINE_CHUNK_NAME.StaticVar]: [
-    CLASS_DEFINE_CHUNK_NAME.Start,
-  ],
-  [CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [
-    CLASS_DEFINE_CHUNK_NAME.Start,
-    CLASS_DEFINE_CHUNK_NAME.StaticVar,
-  ],
+  [CLASS_DEFINE_CHUNK_NAME.StaticVar]: [CLASS_DEFINE_CHUNK_NAME.Start],
+  [CLASS_DEFINE_CHUNK_NAME.StaticMethod]: [CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.StaticVar],
   [CLASS_DEFINE_CHUNK_NAME.InsVar]: [
     CLASS_DEFINE_CHUNK_NAME.Start,
     CLASS_DEFINE_CHUNK_NAME.StaticVar,
@@ -82,7 +81,7 @@ export const DEFAULT_LINK_AFTER = {
     CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
     CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
   ],
-  [CLASS_DEFINE_CHUNK_NAME.End]: [
+  [CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod]: [
     CLASS_DEFINE_CHUNK_NAME.Start,
     CLASS_DEFINE_CHUNK_NAME.StaticVar,
     CLASS_DEFINE_CHUNK_NAME.StaticMethod,
@@ -91,9 +90,20 @@ export const DEFAULT_LINK_AFTER = {
     CLASS_DEFINE_CHUNK_NAME.InsMethod,
     CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
   ],
+  [CLASS_DEFINE_CHUNK_NAME.End]: [
+    CLASS_DEFINE_CHUNK_NAME.Start,
+    CLASS_DEFINE_CHUNK_NAME.StaticVar,
+    CLASS_DEFINE_CHUNK_NAME.StaticMethod,
+    CLASS_DEFINE_CHUNK_NAME.InsVar,
+    CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
+    CLASS_DEFINE_CHUNK_NAME.InsMethod,
+    CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+    CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
+  ],
   [COMMON_CHUNK_NAME.FileMainContent]: [
     COMMON_CHUNK_NAME.ExternalDepsImport,
     COMMON_CHUNK_NAME.InternalDepsImport,
+    COMMON_CHUNK_NAME.ImportAliasDefine,
     COMMON_CHUNK_NAME.FileVarDefine,
     COMMON_CHUNK_NAME.FileUtilDefine,
     CLASS_DEFINE_CHUNK_NAME.End,
@@ -101,6 +111,7 @@ export const DEFAULT_LINK_AFTER = {
   [COMMON_CHUNK_NAME.FileExport]: [
     COMMON_CHUNK_NAME.ExternalDepsImport,
     COMMON_CHUNK_NAME.InternalDepsImport,
+    COMMON_CHUNK_NAME.ImportAliasDefine,
     COMMON_CHUNK_NAME.FileVarDefine,
     COMMON_CHUNK_NAME.FileUtilDefine,
     CLASS_DEFINE_CHUNK_NAME.End,
diff --git a/packages/code-generator/src/generator/ChunkBuilder.ts b/packages/code-generator/src/generator/ChunkBuilder.ts
index 67ecd504e..d9dc8e3c6 100644
--- a/packages/code-generator/src/generator/ChunkBuilder.ts
+++ b/packages/code-generator/src/generator/ChunkBuilder.ts
@@ -21,6 +21,7 @@ export const groupChunks = (chunks: ICodeChunk[]): ICodeChunk[][] => {
   const col = chunks.reduce((chunksSet: Record<string, ChunkGroupInfo[]>, chunk) => {
     const fileKey = chunk.subModule || COMMON_SUB_MODULE_NAME;
     if (!chunksSet[fileKey]) {
+      // eslint-disable-next-line no-param-reassign
       chunksSet[fileKey] = [];
     }
     const res = whichFamily(chunk.fileType as FileType);
@@ -56,6 +57,7 @@ export const groupChunks = (chunks: ICodeChunk[]): ICodeChunk[][] => {
       let t: string = info.chunk.fileType;
       if (info.familyIdx !== undefined) {
         t = FILE_TYPE_FAMILY[info.familyIdx][tmp[key][info.familyIdx]];
+        // eslint-disable-next-line no-param-reassign
         info.chunk.fileType = t;
       }
       if (!byType[t]) {
diff --git a/packages/code-generator/src/generator/CodeBuilder.ts b/packages/code-generator/src/generator/CodeBuilder.ts
index 21b471f50..9a850d4a4 100644
--- a/packages/code-generator/src/generator/CodeBuilder.ts
+++ b/packages/code-generator/src/generator/CodeBuilder.ts
@@ -1,18 +1,13 @@
-import {
-  ChunkContent,
-  ChunkType,
-  CodeGeneratorError,
-  CodeGeneratorFunction,
-  ICodeBuilder,
-  ICodeChunk,
-} from '../types';
+import { ChunkContent, ChunkType, CodeGeneratorError, CodeGeneratorFunction, ICodeBuilder, ICodeChunk } from '../types';
 
 export default class Builder implements ICodeBuilder {
   private chunkDefinitions: ICodeChunk[] = [];
 
   private generators: { [key: string]: CodeGeneratorFunction<ChunkContent> } = {
-    [ChunkType.STRING]: (str: string) => str, // no-op for string chunks
-    [ChunkType.JSON]: (json: object) => JSON.stringify(json), // stringify json to string
+    // no-op for string chunks
+    [ChunkType.STRING]: (str: string) => str,
+    // stringify json to string
+    [ChunkType.JSON]: (json: Record<string, unknown>) => JSON.stringify(json),
   };
 
   constructor(chunkDefinitions: ICodeChunk[] = []) {
@@ -23,13 +18,13 @@ export default class Builder implements ICodeBuilder {
    * Links all chunks together based on their requirements. Returns an array
    * of ordered chunk names which need to be compiled and glued together.
    */
-  public link(chunkDefinitions: ICodeChunk[] = []): string {
+  link(chunkDefinitions: ICodeChunk[] = []): string {
     const chunks = chunkDefinitions || this.chunkDefinitions;
     if (chunks.length <= 0) {
       return '';
     }
 
-    const unprocessedChunks = chunks.map(chunk => {
+    const unprocessedChunks = chunks.map((chunk) => {
       return {
         name: chunk.name,
         type: chunk.type,
@@ -50,9 +45,7 @@ export default class Builder implements ICodeBuilder {
       }
 
       if (unprocessedChunks[indexToRemove].linkAfter.length > 0) {
-        throw new CodeGeneratorError(
-          'Operation aborted. Reason: cyclic dependency between chunks.',
-        );
+        throw new CodeGeneratorError('Operation aborted. Reason: cyclic dependency between chunks.');
       }
 
       const { type, content, name } = unprocessedChunks[indexToRemove];
@@ -62,10 +55,13 @@ export default class Builder implements ICodeBuilder {
       }
 
       unprocessedChunks.splice(indexToRemove, 1);
-      if (!unprocessedChunks.some(ch => ch.name === name)) {
+      if (!unprocessedChunks.some((ch) => ch.name === name)) {
         unprocessedChunks.forEach(
           // remove the processed chunk from all the linkAfter arrays from the remaining chunks
-          ch => (ch.linkAfter = ch.linkAfter.filter(after => after !== name)),
+          (ch) => {
+            // eslint-disable-next-line no-param-reassign
+            ch.linkAfter = ch.linkAfter.filter((after) => after !== name);
+          },
         );
       }
     }
@@ -73,14 +69,12 @@ export default class Builder implements ICodeBuilder {
     return resultingString.join('\n');
   }
 
-  public generateByType(type: string, content: unknown): string {
+  generateByType(type: string, content: unknown): string {
     if (!content) {
       return '';
     }
     if (Array.isArray(content)) {
-      return content
-        .map(contentItem => this.generateByType(type, contentItem))
-        .join('\n');
+      return content.map((contentItem) => this.generateByType(type, contentItem)).join('\n');
     }
 
     if (!this.generators[type]) {
@@ -95,6 +89,6 @@ export default class Builder implements ICodeBuilder {
   // remove invalid chunks (which did not end up being created) from the linkAfter fields
   // one use-case is when you want to remove the import plugin
   private cleanupInvalidChunks(linkAfter: string[], chunks: ICodeChunk[]) {
-    return linkAfter.filter(chunkName => chunks.some(chunk => chunk.name === chunkName));
+    return linkAfter.filter((chunkName) => chunks.some((chunk) => chunk.name === chunkName));
   }
 }
diff --git a/packages/code-generator/src/generator/ModuleBuilder.ts b/packages/code-generator/src/generator/ModuleBuilder.ts
index f70abc669..e31fdc58b 100644
--- a/packages/code-generator/src/generator/ModuleBuilder.ts
+++ b/packages/code-generator/src/generator/ModuleBuilder.ts
@@ -1,13 +1,12 @@
+import { ProjectSchema, ResultFile, ResultDir } from '@ali/lowcode-types';
+
 import {
   BuilderComponentPlugin,
   CodeGeneratorError,
-  IBasicSchema,
   ICodeChunk,
   ICompiledModule,
   IModuleBuilder,
   IParseResult,
-  IResultDir,
-  IResultFile,
   ISchemaParser,
   PostProcessor,
 } from '../types';
@@ -17,9 +16,7 @@ import { COMMON_SUB_MODULE_NAME } from '../const/generator';
 import SchemaParser from '../parser/SchemaParser';
 import ChunkBuilder from './ChunkBuilder';
 import CodeBuilder from './CodeBuilder';
-
-import ResultDir from '../model/ResultDir';
-import ResultFile from '../model/ResultFile';
+import { createResultFile, createResultDir, addFile } from '../utils/resultHelper';
 
 export function createModuleBuilder(
   options: {
@@ -40,24 +37,24 @@ export function createModuleBuilder(
       throw new CodeGeneratorError('No plugins found. Component generation cannot work without any plugins!');
     }
 
-    let files: IResultFile[] = [];
+    let files: ResultFile[] = [];
 
     const { chunks } = await chunkGenerator.run(input);
     chunks.forEach((fileChunkList) => {
       const content = linker.link(fileChunkList);
-      const file = new ResultFile(fileChunkList[0].subModule || moduleMainName, fileChunkList[0].fileType, content);
+      const file = createResultFile(fileChunkList[0].subModule || moduleMainName, fileChunkList[0].fileType, content);
       files.push(file);
     });
 
     if (options.postProcessors.length > 0) {
       files = files.map((file) => {
-        let { content } = file;
+        let content = file.content;
         const type = file.ext;
         options.postProcessors.forEach((processer) => {
           content = processer(content, type);
         });
 
-        return new ResultFile(file.name, type, content);
+        return createResultFile(file.name, type, content);
       });
     }
 
@@ -66,7 +63,7 @@ export function createModuleBuilder(
     };
   };
 
-  const generateModuleCode = async (schema: IBasicSchema | string): Promise<IResultDir> => {
+  const generateModuleCode = async (schema: ProjectSchema | string): Promise<ResultDir> => {
     // Init
     const schemaParser: ISchemaParser = new SchemaParser();
     const parseResult: IParseResult = schemaParser.parse(schema);
@@ -74,19 +71,19 @@ export function createModuleBuilder(
     const containerInfo = parseResult.containers[0];
     const { files } = await generateModule(containerInfo);
 
-    const dir = new ResultDir(containerInfo.moduleName);
-    files.forEach((file) => dir.addFile(file));
+    const dir = createResultDir(containerInfo.moduleName);
+    files.forEach((file) => addFile(dir, file));
 
     return dir;
   };
 
   const linkCodeChunks = (chunks: Record<string, ICodeChunk[]>, fileName: string) => {
-    const files: IResultFile[] = [];
+    const files: ResultFile[] = [];
 
     Object.keys(chunks).forEach((fileKey) => {
       const fileChunkList = chunks[fileKey];
       const content = linker.link(fileChunkList);
-      const file = new ResultFile(fileChunkList[0].subModule || fileName, fileChunkList[0].fileType, content);
+      const file = createResultFile(fileChunkList[0].subModule || fileName, fileChunkList[0].fileType, content);
       files.push(file);
     });
 
diff --git a/packages/code-generator/src/generator/ProjectBuilder.ts b/packages/code-generator/src/generator/ProjectBuilder.ts
index a10ad67e8..5486cd538 100644
--- a/packages/code-generator/src/generator/ProjectBuilder.ts
+++ b/packages/code-generator/src/generator/ProjectBuilder.ts
@@ -1,36 +1,35 @@
+import { ResultDir, ResultFile, ProjectSchema } from '@ali/lowcode-types';
+
 import {
   IModuleBuilder,
   IParseResult,
   IProjectBuilder,
   IProjectPlugins,
-  IProjectSchema,
   IProjectTemplate,
-  IResultDir,
-  IResultFile,
   ISchemaParser,
   PostProcessor,
 } from '../types';
 
-import ResultDir from '../model/ResultDir';
 import SchemaParser from '../parser/SchemaParser';
+import { createResultDir, addDirectory, addFile } from '../utils/resultHelper';
 
 import { createModuleBuilder } from '../generator/ModuleBuilder';
 
 interface IModuleInfo {
   moduleName?: string;
   path: string[];
-  files: IResultFile[];
+  files: ResultFile[];
 }
 
-function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
-  let current: IResultDir = root;
+function getDirFromRoot(root: ResultDir, path: string[]): ResultDir {
+  let current: ResultDir = root;
   path.forEach((p) => {
     const exist = current.dirs.find((d) => d.name === p);
     if (exist) {
       current = exist;
     } else {
-      const newDir = new ResultDir(p);
-      current.addDirectory(newDir);
+      const newDir = createResultDir(p);
+      addDirectory(current, newDir);
       current = newDir;
     }
   });
@@ -59,7 +58,7 @@ export class ProjectBuilder implements IProjectBuilder {
     this.postProcessors = postProcessors;
   }
 
-  async generateProject(schema: IProjectSchema | string): Promise<IResultDir> {
+  async generateProject(schema: ProjectSchema | string): Promise<ResultDir> {
     // Init
     const schemaParser: ISchemaParser = new SchemaParser();
     const builders = this.createModuleBuilders();
@@ -119,6 +118,27 @@ export class ProjectBuilder implements IProjectBuilder {
         files,
       });
     }
+
+    // appConfig
+    if (builders.appConfig) {
+      const { files } = await builders.appConfig.generateModule(parseResult);
+
+      buildResult.push({
+        path: this.template.slots.appConfig.path,
+        files,
+      });
+    }
+
+    // buildConfig
+    if (builders.buildConfig) {
+      const { files } = await builders.buildConfig.generateModule(parseResult);
+
+      buildResult.push({
+        path: this.template.slots.buildConfig.path,
+        files,
+      });
+    }
+
     // constants?
     if (parseResult.project && builders.constants && this.template.slots.constants) {
       const { files } = await builders.constants.generateModule(parseResult.project);
@@ -128,6 +148,7 @@ export class ProjectBuilder implements IProjectBuilder {
         files,
       });
     }
+
     // utils?
     if (parseResult.globalUtils && builders.utils && this.template.slots.utils) {
       const { files } = await builders.utils.generateModule(parseResult.globalUtils);
@@ -137,15 +158,17 @@ export class ProjectBuilder implements IProjectBuilder {
         files,
       });
     }
+
     // i18n?
-    if (parseResult.globalI18n && builders.i18n && this.template.slots.i18n) {
-      const { files } = await builders.i18n.generateModule(parseResult.globalI18n);
+    if (builders.i18n && this.template.slots.i18n) {
+      const { files } = await builders.i18n.generateModule(parseResult.project);
 
       buildResult.push({
         path: this.template.slots.i18n.path,
         files,
       });
     }
+
     // globalStyle
     if (parseResult.project && builders.globalStyle) {
       const { files } = await builders.globalStyle.generateModule(parseResult.project);
@@ -155,6 +178,7 @@ export class ProjectBuilder implements IProjectBuilder {
         files,
       });
     }
+
     // htmlEntry
     if (parseResult.project && builders.htmlEntry) {
       const { files } = await builders.htmlEntry.generateModule(parseResult.project);
@@ -164,6 +188,7 @@ export class ProjectBuilder implements IProjectBuilder {
         files,
       });
     }
+
     // packageJSON
     if (parseResult.project && builders.packageJSON) {
       const { files } = await builders.packageJSON.generateModule(parseResult.project);
@@ -174,17 +199,19 @@ export class ProjectBuilder implements IProjectBuilder {
       });
     }
 
+    // TODO: 更多 slots 的处理？？是不是可以考虑把 template 中所有的 slots 都处理下？
+
     // Post Process
 
     // Combine Modules
     buildResult.forEach((moduleInfo) => {
       let targetDir = getDirFromRoot(projectRoot, moduleInfo.path);
       if (moduleInfo.moduleName) {
-        const dir = new ResultDir(moduleInfo.moduleName);
-        targetDir.addDirectory(dir);
+        const dir = createResultDir(moduleInfo.moduleName);
+        addDirectory(targetDir, dir);
         targetDir = dir;
       }
-      moduleInfo.files.forEach((file) => targetDir.addFile(file));
+      moduleInfo.files.forEach((file) => addFile(targetDir, file));
     });
 
     return projectRoot;
diff --git a/packages/code-generator/src/index.ts b/packages/code-generator/src/index.ts
index 79e527354..3d368be5a 100644
--- a/packages/code-generator/src/index.ts
+++ b/packages/code-generator/src/index.ts
@@ -7,7 +7,8 @@ import { createModuleBuilder } from './generator/ModuleBuilder';
 import { createDiskPublisher } from './publisher/disk';
 import { createZipPublisher } from './publisher/zip';
 import createIceJsProjectBuilder from './solutions/icejs';
-import createRecoreProjectBuilder from './solutions/recore';
+// import createRecoreProjectBuilder from './solutions/recore';
+import createRaxAppProjectBuilder from './solutions/rax-app';
 
 // 引入说明
 import { REACT_CHUNK_NAME } from './plugins/component/react/const';
@@ -34,11 +35,15 @@ import prettier from './postprocessor/prettier';
 import * as utilsCommon from './utils/common';
 import * as utilsCompositeType from './utils/compositeType';
 import * as utilsJsExpression from './utils/jsExpression';
+import * as utilsJsSlot from './utils/jsSlot';
 import * as utilsNodeToJSX from './utils/nodeToJSX';
+import * as utilsResultHelper from './utils/resultHelper';
 import * as utilsTemplateHelper from './utils/templateHelper';
+import * as utilsValidate from './utils/validate';
 
 // 引入内置解决方案模块
 import icejs from './plugins/project/framework/icejs';
+import rax from './plugins/project/framework/rax';
 
 export * from './types';
 
@@ -47,10 +52,12 @@ export default {
   createModuleBuilder,
   solutions: {
     icejs: createIceJsProjectBuilder,
-    recore: createRecoreProjectBuilder,
+    // recore: createRecoreProjectBuilder,
+    rax: createRaxAppProjectBuilder,
   },
   solutionParts: {
     icejs,
+    rax,
   },
   publishers: {
     disk: createDiskPublisher,
@@ -87,8 +94,11 @@ export default {
     common: utilsCommon,
     compositeType: utilsCompositeType,
     jsExpression: utilsJsExpression,
+    jsSlot: utilsJsSlot,
     nodeToJSX: utilsNodeToJSX,
+    resultHelper: utilsResultHelper,
     templateHelper: utilsTemplateHelper,
+    validate: utilsValidate,
   },
   chunkNames: {
     COMMON_CHUNK_NAME,
diff --git a/packages/code-generator/src/model/ResultDir.ts b/packages/code-generator/src/model/ResultDir.ts
deleted file mode 100644
index c456a9459..000000000
--- a/packages/code-generator/src/model/ResultDir.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { CodeGeneratorError, IResultDir, IResultFile } from '../types';
-
-export default class ResultDir implements IResultDir {
-  public name: string;
-
-  public dirs: IResultDir[];
-
-  public files: IResultFile[];
-
-  constructor(name: string) {
-    this.name = name;
-    this.dirs = [];
-    this.files = [];
-  }
-
-  public addDirectory(dir: IResultDir): void {
-    if (this.dirs.findIndex(d => d.name === dir.name) < 0) {
-      this.dirs.push(dir);
-    } else {
-      throw new CodeGeneratorError('Adding same directory to one directory');
-    }
-  }
-
-  public addFile(file: IResultFile): void {
-    if (
-      this.files.findIndex(f => f.name === file.name && f.ext === file.ext) < 0
-    ) {
-      this.files.push(file);
-    } else {
-      throw new CodeGeneratorError('Adding same file to one directory');
-    }
-  }
-}
diff --git a/packages/code-generator/src/model/ResultFile.ts b/packages/code-generator/src/model/ResultFile.ts
deleted file mode 100644
index b8064bfab..000000000
--- a/packages/code-generator/src/model/ResultFile.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { IResultFile } from '../types';
-
-export default class ResultFile implements IResultFile {
-  public name: string;
-
-  public ext: string;
-
-  public content: string;
-
-  constructor(name: string, ext = 'jsx', content = '') {
-    this.name = name;
-    this.ext = ext;
-    this.content = content;
-  }
-}
diff --git a/packages/code-generator/src/parser/SchemaParser.ts b/packages/code-generator/src/parser/SchemaParser.ts
index 61ca7c806..b05df3ec5 100644
--- a/packages/code-generator/src/parser/SchemaParser.ts
+++ b/packages/code-generator/src/parser/SchemaParser.ts
@@ -2,30 +2,28 @@
  * 解析器是对输入的固定格式数据做拆解，使其符合引擎后续步骤预期，完成统一处理逻辑的步骤。
  * 本解析器面向的是标准 schema 协议。
  */
+import changeCase from 'change-case';
+import { UtilItem, NodeDataType, NodeSchema, ContainerSchema, ProjectSchema, PropsMap } from '@ali/lowcode-types';
 
 import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
 
-import { handleSubNodes } from '../utils/nodeToJSX';
+import { handleSubNodes } from '../utils/schema';
 import { uniqueArray } from '../utils/common';
 
 import {
-  ChildNodeType,
   CodeGeneratorError,
   CompatibilityError,
   DependencyType,
-  IBasicSchema,
-  IComponentNodeItem,
   IContainerInfo,
-  IContainerNodeItem,
+  IDependency,
   IExternalDependency,
   IInternalDependency,
   InternalDependencyType,
-  IPageMeta,
   IParseResult,
-  IProjectSchema,
   ISchemaParser,
-  IUtilItem,
   INpmPackage,
+  IRouterInfo,
+  IPageMeta,
 } from '../types';
 
 const defaultContainer: IContainerInfo = {
@@ -38,7 +36,7 @@ const defaultContainer: IContainerInfo = {
 };
 
 class SchemaParser implements ISchemaParser {
-  validate(schema: IBasicSchema): boolean {
+  validate(schema: ProjectSchema): boolean {
     if (SUPPORT_SCHEMA_VERSION_LIST.indexOf(schema.version) < 0) {
       throw new CompatibilityError(`Not support schema with version [${schema.version}]`);
     }
@@ -46,13 +44,13 @@ class SchemaParser implements ISchemaParser {
     return true;
   }
 
-  parse(schemaSrc: IProjectSchema | string): IParseResult {
+  parse(schemaSrc: ProjectSchema | string): IParseResult {
     // TODO: collect utils depends in JSExpression
     const compDeps: Record<string, IExternalDependency> = {};
     const internalDeps: Record<string, IInternalDependency> = {};
     let utilsDeps: IExternalDependency[] = [];
 
-    let schema: IProjectSchema;
+    let schema: ProjectSchema;
     if (typeof schemaSrc === 'string') {
       try {
         schema = JSON.parse(schemaSrc);
@@ -65,31 +63,38 @@ class SchemaParser implements ISchemaParser {
 
     // 解析三方组件依赖
     schema.componentsMap.forEach((info) => {
-      info.dependencyType = DependencyType.External;
-      info.importName = info.componentName;
-      compDeps[info.componentName] = info;
+      if (info.componentName) {
+        compDeps[info.componentName] = {
+          ...info,
+          dependencyType: DependencyType.External,
+          componentName: info.componentName,
+          exportName: info.exportName ?? info.componentName,
+          version: info.version || '*',
+          destructuring: info.destructuring ?? false,
+        };
+      }
     });
 
     let containers: IContainerInfo[];
     // Test if this is a lowcode component without container
     if (schema.componentsTree.length > 0) {
-      const firstRoot: IContainerNodeItem = schema.componentsTree[0] as IContainerNodeItem;
+      const firstRoot: ContainerSchema = schema.componentsTree[0] as ContainerSchema;
 
-      if (!firstRoot.fileName) {
+      if (!('fileName' in firstRoot) || !firstRoot.fileName) {
         // 整个 schema 描述一个容器，且无根节点定义
         const container: IContainerInfo = {
           ...defaultContainer,
-          children: schema.componentsTree as IComponentNodeItem[],
+          children: schema.componentsTree as NodeSchema[],
         };
         containers = [container];
       } else {
         // 普通带 1 到多个容器的 schema
         containers = schema.componentsTree.map((n) => {
-          const subRoot = n as IContainerNodeItem;
+          const subRoot = n as ContainerSchema;
           const container: IContainerInfo = {
             ...subRoot,
             containerType: subRoot.componentName,
-            moduleName: subRoot.fileName, // TODO: 驼峰化名称
+            moduleName: changeCase.pascalCase(subRoot.fileName),
           };
           return container;
         });
@@ -124,6 +129,7 @@ class SchemaParser implements ISchemaParser {
       internalDeps[dep.moduleName] = dep;
     });
 
+    const containersDeps = ([] as IDependency[]).concat(...containers.map((c) => c.deps || []));
     // TODO: 不应该在出码部分解决？
     // 处理 children 写在了 props 里的情况
     containers.forEach((container) => {
@@ -131,11 +137,18 @@ class SchemaParser implements ISchemaParser {
         handleSubNodes<string>(
           container.children,
           {
-            node: (i: IComponentNodeItem) => {
-              if (i.props && i.props.children && !i.children) {
-                i.children = i.props.children as ChildNodeType;
+            node: (i: NodeSchema) => {
+              if (i.props) {
+                if (Array.isArray(i.props)) {
+                  // FIXME: is array type props description
+                } else {
+                  const nodeProps = i.props as PropsMap;
+                  if (nodeProps.children && !i.children) {
+                    i.children = nodeProps.children as NodeDataType;
+                  }
+                }
               }
-              return [''];
+              return '';
             },
           },
           {
@@ -157,18 +170,21 @@ class SchemaParser implements ISchemaParser {
     });
 
     // 分析路由配置
-    const routes = containers
+    const routes: IRouterInfo['routes'] = containers
       .filter((container) => container.containerType === 'Page')
       .map((page) => {
-        const meta = page.meta as IPageMeta;
+        const meta = page.meta;
         if (meta) {
           return {
-            path: meta.router,
+            path: (meta as IPageMeta).router || `/${page.fileName}`, // 如果无法找到页面路由信息，则用 fileName 做兜底
+            fileName: page.fileName,
             componentName: page.moduleName,
           };
         }
+
         return {
           path: '',
+          fileName: page.fileName,
           componentName: page.moduleName,
         };
       });
@@ -178,7 +194,7 @@ class SchemaParser implements ISchemaParser {
       .filter((dep) => !!dep);
 
     // 分析 Utils 依赖
-    let utils: IUtilItem[];
+    let utils: UtilItem[];
     if (schema.utils) {
       utils = schema.utils;
       utilsDeps = schema.utils.filter((u) => u.type !== 'function').map((u) => u.content as IExternalDependency);
@@ -190,7 +206,7 @@ class SchemaParser implements ISchemaParser {
     let npms: INpmPackage[] = [];
     containers.forEach((con) => {
       const p = (con.deps || [])
-        .map((dep) => (dep.dependencyType === DependencyType.External ? dep : null))
+        .map((dep) => { return (dep.dependencyType === DependencyType.External) ? dep : null; })
         .filter((dep) => dep !== null);
       npms.push(...((p as unknown) as INpmPackage[]));
     });
@@ -208,21 +224,21 @@ class SchemaParser implements ISchemaParser {
         deps: routerDeps,
       },
       project: {
-        meta: schema.meta,
-        config: schema.config,
         css: schema.css,
         constants: schema.constants,
         i18n: schema.i18n,
+        containersDeps,
+        utilsDeps,
         packages: npms,
       },
     };
   }
 
-  getComponentNames(children: ChildNodeType): string[] {
+  getComponentNames(children: NodeDataType): string[] {
     return handleSubNodes<string>(
       children,
       {
-        node: (i: IComponentNodeItem) => [i.componentName],
+        node: (i: NodeSchema) => i.componentName,
       },
       {
         rerun: true,
diff --git a/packages/code-generator/src/plugins/common/esmodule.ts b/packages/code-generator/src/plugins/common/esmodule.ts
index 2fbff2fed..c8a5bb8c6 100644
--- a/packages/code-generator/src/plugins/common/esmodule.ts
+++ b/packages/code-generator/src/plugins/common/esmodule.ts
@@ -50,7 +50,12 @@ function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> {
   return depMap;
 }
 
-function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: string): ICodeChunk[] {
+function buildPackageImport(
+  pkg: string,
+  deps: IDependency[],
+  targetFileType: string,
+  useAliasName: boolean,
+): ICodeChunk[] {
   const chunks: ICodeChunk[] = [];
   let defaultImport = '';
   let defaultImportAs = '';
@@ -58,8 +63,9 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
 
   deps.forEach((dep) => {
     const srcName = dep.exportName;
-    let targetName = dep.importName || dep.exportName;
+    let targetName = dep.componentName || dep.exportName;
 
+    // 如果是自组件，则导出父组件，并且根据自组件命名规则，判断是否需要定义标识符
     if (dep.subName) {
       if (targetName !== `${srcName}.${dep.subName}`) {
         if (!isValidIdentifier(targetName)) {
@@ -69,9 +75,14 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
         chunks.push({
           type: ChunkType.STRING,
           fileType: targetFileType,
-          name: COMMON_CHUNK_NAME.FileVarDefine,
+          name: COMMON_CHUNK_NAME.ImportAliasDefine,
           content: `const ${targetName} = ${srcName}.${dep.subName};`,
           linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
+          ext: {
+            originalName: `${srcName}.${dep.subName}`,
+            aliasName: targetName,
+            dependency: dep,
+          },
         });
       }
 
@@ -86,13 +97,28 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
       defaultImport = srcName;
       defaultImportAs = targetName;
     }
+
+    if (targetName !== srcName) {
+      chunks.push({
+        type: ChunkType.STRING,
+        fileType: targetFileType,
+        name: COMMON_CHUNK_NAME.ImportAliasDefine,
+        content: '',
+        linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
+        ext: {
+          originalName: srcName,
+          aliasName: targetName,
+          dependency: dep,
+        },
+      });
+    }
   });
 
-  const items = Object.keys(imports).map((src) => (src === imports[src] ? src : `${src} as ${imports[src]}`));
+  const items = Object.keys(imports).map((src) => { return src === imports[src] || !useAliasName ? src : `${src} as ${imports[src]}`; });
 
   const statementL = ['import'];
   if (defaultImport) {
-    statementL.push(defaultImportAs);
+    statementL.push(useAliasName ? defaultImportAs : defaultImport);
     if (items.length > 0) {
       statementL.push(',');
     }
@@ -127,13 +153,15 @@ function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: st
 }
 
 type PluginConfig = {
-  fileType: string;
+  fileType?: string; // 导出的文件类型
+  useAliasName?: boolean; // 是否使用 componentName 重命名组件 identifier
 };
 
 const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => {
-  const cfg: PluginConfig = {
+  const cfg = {
     fileType: FileType.JS,
-    ...config,
+    useAliasName: true,
+    ...(config || {}),
   };
 
   const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
@@ -147,7 +175,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: Plu
       const packs = groupDepsByPack(ir.deps);
 
       Object.keys(packs).forEach((pkg) => {
-        const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType);
+        const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType, cfg.useAliasName);
         next.chunks.push(...chunks);
       });
     }
diff --git a/packages/code-generator/src/plugins/common/requireUtils.ts b/packages/code-generator/src/plugins/common/requireUtils.ts
index 6d2fcfe92..4dacf68e5 100644
--- a/packages/code-generator/src/plugins/common/requireUtils.ts
+++ b/packages/code-generator/src/plugins/common/requireUtils.ts
@@ -1,12 +1,6 @@
 import { COMMON_CHUNK_NAME } from '../../const/generator';
 
-import {
-  BuilderComponentPlugin,
-  BuilderComponentPluginFactory,
-  ChunkType,
-  FileType,
-  ICodeStruct,
-} from '../../types';
+import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, FileType, ICodeStruct } from '../../types';
 
 // TODO: How to merge this logic to common deps
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
diff --git a/packages/code-generator/src/plugins/component/rax/commonDeps.ts b/packages/code-generator/src/plugins/component/rax/commonDeps.ts
new file mode 100644
index 000000000..4a2c53bdd
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/commonDeps.ts
@@ -0,0 +1,35 @@
+import { COMMON_CHUNK_NAME } from '../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+} from '../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: COMMON_CHUNK_NAME.ExternalDepsImport,
+      content: `
+        // 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+        // 例外：rax 框架的导出名和各种组件名除外。
+        import { createElement, Component } from 'rax';
+        import { withRouter as __$$withRouter } from 'rax-app';
+      `,
+      linkAfter: [],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/const.ts b/packages/code-generator/src/plugins/component/rax/const.ts
new file mode 100644
index 000000000..a0a07b550
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/const.ts
@@ -0,0 +1,18 @@
+export const RAX_CHUNK_NAME = {
+  ClassDidMountBegin: 'RaxComponentClassDidMountBegin',
+  ClassDidMountContent: 'RaxComponentClassDidMountContent',
+  ClassDidMountEnd: 'RaxComponentClassDidMountEnd',
+  ClassWillUnmountBegin: 'RaxComponentClassWillUnmountBegin',
+  ClassWillUnmountContent: 'RaxComponentClassWillUnmountContent',
+  ClassWillUnmountEnd: 'RaxComponentClassWillUnmountEnd',
+  ClassRenderBegin: 'RaxComponentClassRenderBegin',
+  ClassRenderPre: 'RaxComponentClassRenderPre',
+  ClassRenderJSX: 'RaxComponentClassRenderJSX',
+  ClassRenderEnd: 'RaxComponentClassRenderEnd',
+  MethodsBegin: 'RaxComponentMethodsBegin',
+  MethodsContent: 'RaxComponentMethodsContent',
+  MethodsEnd: 'RaxComponentMethodsEnd',
+  LifeCyclesBegin: 'RaxComponentLifeCyclesBegin',
+  LifeCyclesContent: 'RaxComponentLifeCyclesContent',
+  LifeCyclesEnd: 'RaxComponentLifeCyclesEnd',
+};
diff --git a/packages/code-generator/src/plugins/component/rax/containerClass.ts b/packages/code-generator/src/plugins/component/rax/containerClass.ts
new file mode 100644
index 000000000..8104e53e8
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerClass.ts
@@ -0,0 +1,144 @@
+import changeCase from 'change-case';
+import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
+import { RAX_CHUNK_NAME } from './const';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IContainerInfo,
+} from '../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IContainerInfo;
+
+    // 将模块名转换成 PascalCase 的格式，并添加特定后缀，防止命名冲突
+    const componentClassName = `${changeCase.pascalCase(ir.moduleName)}$$Page`;
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: CLASS_DEFINE_CHUNK_NAME.Start,
+      content: `class ${componentClassName} extends Component {`,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+      ],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: CLASS_DEFINE_CHUNK_NAME.End,
+      content: '}',
+      linkAfter: [
+        CLASS_DEFINE_CHUNK_NAME.Start,
+        CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+        RAX_CHUNK_NAME.ClassRenderEnd,
+        RAX_CHUNK_NAME.MethodsEnd,
+      ],
+    });
+
+    // next.chunks.push({
+    //   type: ChunkType.STRING,
+    //   fileType: FileType.JSX,
+    //   name: CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
+    //   content: 'constructor(props, context) { super(props); ',
+    //   linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+    // });
+
+    // next.chunks.push({
+    //   type: ChunkType.STRING,
+    //   fileType: FileType.JSX,
+    //   name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
+    //   content: '}',
+    //   linkAfter: [
+    //     CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
+    //     CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
+    //   ],
+    // });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassDidMountBegin,
+      content: 'componentDidMount() {',
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.InsVar, CLASS_DEFINE_CHUNK_NAME.InsMethod],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassDidMountEnd,
+      content: '}',
+      linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin, RAX_CHUNK_NAME.ClassDidMountContent],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassWillUnmountBegin,
+      content: 'componentWillUnmount() {',
+      linkAfter: [
+        CLASS_DEFINE_CHUNK_NAME.Start,
+        CLASS_DEFINE_CHUNK_NAME.InsVar,
+        CLASS_DEFINE_CHUNK_NAME.InsMethod,
+        RAX_CHUNK_NAME.ClassDidMountEnd,
+      ],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassWillUnmountEnd,
+      content: '}',
+      linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin, RAX_CHUNK_NAME.ClassWillUnmountContent],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassRenderBegin,
+      content: 'render() {',
+      linkAfter: [RAX_CHUNK_NAME.ClassDidMountEnd, RAX_CHUNK_NAME.ClassWillUnmountEnd],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: RAX_CHUNK_NAME.ClassRenderEnd,
+      content: '}',
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin, RAX_CHUNK_NAME.ClassRenderPre, RAX_CHUNK_NAME.ClassRenderJSX],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: COMMON_CHUNK_NAME.FileExport,
+      content: `export default __$$withRouter(${componentClassName});`,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+        CLASS_DEFINE_CHUNK_NAME.End,
+      ],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/containerInitState.ts b/packages/code-generator/src/plugins/component/rax/containerInitState.ts
new file mode 100644
index 000000000..9974281bb
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerInitState.ts
@@ -0,0 +1,68 @@
+import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
+
+import { generateCompositeType } from '../../../utils/compositeType';
+import Scope from '../../../utils/Scope';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IContainerInfo,
+} from '../../../types';
+
+type PluginConfig = {
+  fileType: string;
+  implementType: 'inConstructor' | 'insMember' | 'hooks';
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    implementType: 'insMember',
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IContainerInfo;
+    const scope = Scope.createRootScope();
+
+    if (ir.state) {
+      const state = ir.state;
+      const fields = Object.keys(state).map<string>((stateName) => {
+        // TODO: 这里用什么 handlers?
+        const value = generateCompositeType(state[stateName], scope);
+        return `${stateName}: ${value}`;
+      });
+
+      if (cfg.implementType === 'inConstructor') {
+        next.chunks.push({
+          type: ChunkType.STRING,
+          fileType: cfg.fileType,
+          name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
+          content: `this.state = { ${fields.join(',')} };`,
+          linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
+        });
+      } else if (cfg.implementType === 'insMember') {
+        next.chunks.push({
+          type: ChunkType.STRING,
+          fileType: cfg.fileType,
+          name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+          content: `state = { ${fields.join(',')} };`,
+          linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsVar]],
+        });
+      }
+      // TODO: hooks state??
+    }
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts b/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts
new file mode 100644
index 000000000..ebceb424e
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerInjectContext.ts
@@ -0,0 +1,116 @@
+import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+} from '../../../types';
+import { RAX_CHUNK_NAME } from './const';
+
+type PluginConfig = {
+  fileType: string;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.InternalDepsImport,
+      content: 'import __$$constants from \'../../constants\';',
+      linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
+    });
+
+    // TODO: i18n 是可选的，如果没有 i18n 这个文件怎么办？该怎么判断？
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.InternalDepsImport,
+      content: 'import * as __$$i18n from \'../../i18n\';',
+      linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+      content: `
+        _context = this._createContext();
+      `,
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+      content: `
+        _createContext() {
+          const self = this;
+
+          // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+          self._latestState = self.state;
+
+          const context = {
+            get state() {
+              // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+              return self._latestState;
+            },
+            setState(newState) {
+              self._latestState = { ...self._latestState, ...newState };
+              self.setState(newState);
+            },
+            get dataSourceMap() {
+              return self._dataSourceEngine.dataSourceMap || {};
+            },
+            async reloadDataSource() {
+              await self._dataSourceEngine.reloadDataSource();
+            },
+            get utils() {
+              return self._utils;
+            },
+            get page() {
+              return context;
+            },
+            get component() {
+              return context;
+            },
+            get props() {
+              return self.props;
+            },
+            get constants() {
+              return __$$constants;
+            },
+            i18n: __$$i18n.i18n,
+            i18nFormat: __$$i18n.i18nFormat,
+            getLocale: __$$i18n.getLocale,
+            setLocale(locale) {
+              __$$i18n.setLocale(locale);
+              self.forceUpdate();
+            },
+            ...this._methods,
+          };
+
+          return context;
+        }
+      `,
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts b/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
new file mode 100644
index 000000000..dd811d52a
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerInjectDataSourceEngine.ts
@@ -0,0 +1,157 @@
+/* eslint-disable @typescript-eslint/indent */
+
+import { CompositeValue, JSExpression, DataSourceConfig, isJSExpression, isJSFunction } from '@ali/lowcode-types';
+import changeCase from 'change-case';
+
+import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
+import Scope from '../../../utils/Scope';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IScope,
+} from '../../../types';
+
+import { generateCompositeType } from '../../../utils/compositeType';
+import { parseExpressionConvertThis2Context } from '../../../utils/expressionParser';
+import { isContainerSchema } from '../../../utils/schema';
+import { RAX_CHUNK_NAME } from './const';
+
+type PluginConfig = {
+  fileType: string;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const scope = Scope.createRootScope();
+    const dataSourceConfig = isContainerSchema(pre.ir) ? pre.ir.dataSource : null;
+    const dataSourceItems: DataSourceConfig[] = (dataSourceConfig && dataSourceConfig.list) || [];
+    const dataSourceEngineOptions = { runtimeConfig: true };
+    if (dataSourceItems.length > 0) {
+      const requestHandlersMap = {} as Record<string, JSExpression>;
+
+      dataSourceItems.forEach((ds) => {
+        const dsType = ds.type || 'fetch';
+        if (!(dsType in requestHandlersMap) && dsType !== 'custom') {
+          const handlerFactoryName = '__$$create' + changeCase.pascal(dsType) + 'RequestHandler';
+
+          requestHandlersMap[dsType] = {
+            type: 'JSExpression',
+            value: handlerFactoryName + (dsType === 'urlParams' ? '(this.props.location.search)' : '()'),
+          };
+
+          const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`;
+          const handlerPkgName = `@ali/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
+
+          next.chunks.push({
+            type: ChunkType.STRING,
+            fileType: FileType.JSX,
+            name: COMMON_CHUNK_NAME.ExternalDepsImport,
+            content: `
+              import { ${handlerFactoryExportName} as ${handlerFactoryName} } from '${handlerPkgName}';
+            `,
+            linkAfter: [],
+          });
+        }
+      });
+
+      Object.assign(dataSourceEngineOptions, { requestHandlersMap });
+    }
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: COMMON_CHUNK_NAME.ExternalDepsImport,
+      content: `
+        import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+      `,
+      linkAfter: [],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+      content: `
+        _dataSourceConfig = this._defineDataSourceConfig();
+        _dataSourceEngine = __$$createDataSourceEngine(
+          this._dataSourceConfig,
+          this._context,
+          ${generateCompositeType(dataSourceEngineOptions, scope)}
+        );`,
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: RAX_CHUNK_NAME.ClassDidMountContent,
+      content: `
+        this._dataSourceEngine.reloadDataSource();
+      `,
+      linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+      content: `
+_defineDataSourceConfig() {
+  const __$$context = this._context;
+  return (${generateCompositeType(
+    {
+      ...dataSourceConfig,
+      list: [
+        ...dataSourceItems.map((item) => ({
+          ...item,
+          isInit: wrapAsFunction(item.isInit, scope),
+          options: wrapAsFunction(item.options, scope),
+        })),
+      ],
+    },
+    scope,
+    {
+      handlers: {
+        function: (jsFunc) => parseExpressionConvertThis2Context(jsFunc.value, '__$$context'),
+        expression: (jsExpr) => parseExpressionConvertThis2Context(jsExpr.value, '__$$context'),
+      },
+    },
+  )});
+}
+      `,
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
+
+function wrapAsFunction(value: CompositeValue, scope: IScope): CompositeValue {
+  if (isJSExpression(value) || isJSFunction(value)) {
+    return {
+      type: 'JSExpression',
+      value: `function(){ return ((${value.value}))}`,
+    };
+  }
+
+  return {
+    type: 'JSExpression',
+    value: `function(){return((${generateCompositeType(value, scope)}))}`,
+  };
+}
diff --git a/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts b/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts
new file mode 100644
index 000000000..6ab39657d
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerInjectUtils.ts
@@ -0,0 +1,74 @@
+import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+} from '../../../types';
+import { RAX_CHUNK_NAME } from './const';
+
+type PluginConfig = {
+  fileType: string;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.InternalDepsImport,
+      // TODO: 下面这个路径有没有更好的方式来获取？而非写死
+      content: `
+        import __$$projectUtils from '../../utils';
+      `,
+      linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+      content: '_utils = this._defineUtils();',
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+
+      // 绑定下上下文，这样在所有的 utils 里面都能通过 this.xxx 来访问上下文了
+      content: `
+        _defineUtils() {
+          const utils = {
+            ...__$$projectUtils,
+          };
+
+          Object.entries(utils).forEach(([name, util]) => {
+            if (typeof util === 'function') {
+              utils[name] = util.bind(this._context);
+            }
+          });
+
+          return utils;
+        }`,
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/containerLifeCycle.ts b/packages/code-generator/src/plugins/component/rax/containerLifeCycle.ts
new file mode 100644
index 000000000..c67ee257e
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerLifeCycle.ts
@@ -0,0 +1,120 @@
+import _ from 'lodash';
+
+import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
+import { RAX_CHUNK_NAME } from './const';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  FileType,
+  ChunkType,
+  ICodeStruct,
+  IContainerInfo,
+} from '../../../types';
+
+type PluginConfig = {
+  fileType: string;
+  exportNameMapping: Record<string, string>;
+  normalizeNameMapping: Record<string, string>;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    exportNameMapping: {},
+    normalizeNameMapping: {},
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    // Rax 先只支持 didMount 和 willUnmount 吧
+
+    const ir = next.ir as IContainerInfo;
+    const lifeCycles = ir.lifeCycles;
+
+    if (lifeCycles && !_.isEmpty(lifeCycles)) {
+      Object.entries(lifeCycles).forEach(([lifeCycleName, lifeCycleMethodExpr]) => {
+        const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
+        const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
+
+        next.chunks.push({
+          type: ChunkType.STRING,
+          fileType: cfg.fileType,
+          name: RAX_CHUNK_NAME.LifeCyclesContent,
+          content: `${exportName}: (${lifeCycleMethodExpr.value}),`,
+          linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin],
+        });
+
+        if (normalizeName === 'didMount') {
+          next.chunks.push({
+            type: ChunkType.STRING,
+            fileType: cfg.fileType,
+            name: RAX_CHUNK_NAME.ClassDidMountContent,
+            content: `this._lifeCycles.${exportName}();`,
+            linkAfter: [RAX_CHUNK_NAME.ClassDidMountBegin],
+          });
+        } else if (normalizeName === 'willUnmount') {
+          next.chunks.push({
+            type: ChunkType.STRING,
+            fileType: cfg.fileType,
+            name: RAX_CHUNK_NAME.ClassWillUnmountContent,
+            content: `this._lifeCycles.${exportName}();`,
+            linkAfter: [RAX_CHUNK_NAME.ClassWillUnmountBegin],
+          });
+        } else {
+          // TODO: print warnings? Unknown life cycle
+        }
+      });
+
+      next.chunks.push({
+        type: ChunkType.STRING,
+        fileType: cfg.fileType,
+        name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+        content: '_lifeCycles = this._defineLifeCycles();',
+        linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+      });
+
+      next.chunks.push({
+        type: ChunkType.STRING,
+        fileType: cfg.fileType,
+        name: RAX_CHUNK_NAME.LifeCyclesBegin,
+        content: `
+          _defineLifeCycles() {
+            const __$$lifeCycles = ({
+        `,
+        linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd, CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod],
+      });
+
+      next.chunks.push({
+        type: ChunkType.STRING,
+        fileType: cfg.fileType,
+        name: RAX_CHUNK_NAME.LifeCyclesEnd,
+        content: `
+            });
+
+            // 为所有的方法绑定上下文
+            Object.entries(__$$lifeCycles).forEach(([lifeCycleName, lifeCycleMethod]) => {
+              if (typeof lifeCycleMethod === 'function') {
+                __$$lifeCycles[lifeCycleName] = (...args) => {
+                  return lifeCycleMethod.apply(this._context, args);
+                }
+              }
+            });
+
+            return __$$lifeCycles;
+          }
+        `,
+        linkAfter: [RAX_CHUNK_NAME.LifeCyclesBegin, RAX_CHUNK_NAME.LifeCyclesContent],
+      });
+    }
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/containerMethods.ts b/packages/code-generator/src/plugins/component/rax/containerMethods.ts
new file mode 100644
index 000000000..042462456
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/containerMethods.ts
@@ -0,0 +1,95 @@
+import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IContainerInfo,
+} from '../../../types';
+
+import { RAX_CHUNK_NAME } from './const';
+
+type PluginConfig = {
+  fileType: string;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IContainerInfo;
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: CLASS_DEFINE_CHUNK_NAME.InsVar,
+      content: `
+         _methods = this._defineMethods();
+      `,
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: RAX_CHUNK_NAME.MethodsBegin,
+      content: `
+        _defineMethods() {
+          const __$$methods = ({
+      `,
+      linkAfter: [
+        RAX_CHUNK_NAME.ClassRenderEnd,
+        CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
+        RAX_CHUNK_NAME.LifeCyclesEnd,
+      ],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: RAX_CHUNK_NAME.MethodsEnd,
+      content: `
+          });
+
+          // 为所有的方法绑定上下文
+          Object.entries(__$$methods).forEach(([methodName, method]) => {
+            if (typeof method === 'function') {
+              __$$methods[methodName] = (...args) => {
+                return method.apply(this._context, args);
+              }
+            }
+          });
+
+          return __$$methods;
+        }
+      `,
+      linkAfter: [RAX_CHUNK_NAME.MethodsBegin, RAX_CHUNK_NAME.MethodsContent],
+    });
+
+    if (ir.methods && Object.keys(ir.methods).length > 0) {
+      Object.entries(ir.methods).forEach(([methodName, methodDefine]) => {
+        next.chunks.push({
+          type: ChunkType.STRING,
+          fileType: cfg.fileType,
+          name: RAX_CHUNK_NAME.MethodsContent,
+          content: `${methodName}: (${methodDefine.value}),`,
+          linkAfter: [RAX_CHUNK_NAME.MethodsBegin],
+        });
+      });
+    }
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/component/rax/jsx.ts b/packages/code-generator/src/plugins/component/rax/jsx.ts
new file mode 100644
index 000000000..3ee0ff872
--- /dev/null
+++ b/packages/code-generator/src/plugins/component/rax/jsx.ts
@@ -0,0 +1,350 @@
+import { NodeSchema, JSExpression, NpmInfo, CompositeValue, isJSExpression } from '@ali/lowcode-types';
+
+import _ from 'lodash';
+import changeCase from 'change-case';
+import { Expression } from '@babel/types';
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  CodePiece,
+  FileType,
+  ICodeChunk,
+  ICodeStruct,
+  IContainerInfo,
+  PIECE_TYPE,
+  HandlerSet,
+  IScope,
+  NodeGeneratorConfig,
+  NodePlugin,
+  AttrPlugin,
+} from '../../../types';
+
+import { RAX_CHUNK_NAME } from './const';
+import { COMMON_CHUNK_NAME } from '../../../const/generator';
+
+import { generateExpression } from '../../../utils/jsExpression';
+import { createNodeGenerator, generateConditionReactCtrl, generateReactExprInJS } from '../../../utils/nodeToJSX';
+import { generateCompositeType } from '../../../utils/compositeType';
+import Scope from '../../../utils/Scope';
+import {
+  parseExpression,
+  parseExpressionConvertThis2Context,
+  parseExpressionGetGlobalVariables,
+} from '../../../utils/expressionParser';
+
+type PluginConfig = {
+  fileType: string;
+};
+
+// TODO: componentName 若并非大写字符打头，甚至并非是一个有效的 JS 标识符怎么办？？
+// FIXME: 我想了下，这块应该放到解析阶段就去做掉，对所有 componentName 做 identifier validate，然后对不合法的做统一替换。
+const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
+  const cfg: PluginConfig = {
+    fileType: FileType.JSX,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IContainerInfo;
+    const rootScope = Scope.createRootScope();
+
+    // Rax 构建到小程序的时候，不能给组件起起别名，得直接引用，故这里将所有的别名替换掉
+    // 先收集下所有的 alias 的映射
+    const componentsNameAliasMap = new Map<string, string>();
+    next.chunks.forEach((chunk) => {
+      if (isImportAliasDefineChunk(chunk)) {
+        componentsNameAliasMap.set(chunk.ext.aliasName, chunk.ext.originalName);
+      }
+    });
+
+    // 注意：这里其实隐含了一个假设：schema 中的 componentName 应该是一个有效的 JS 标识符，而且是大写字母打头的
+    const mapComponentNameToAliasOrKeepIt =
+      (componentName: string) => componentsNameAliasMap.get(componentName) || componentName;
+
+    // 然后过滤掉所有的别名 chunks
+    next.chunks = next.chunks.filter((chunk) => !isImportAliasDefineChunk(chunk));
+
+    // 如果直接按目前的 React 的方式之间出码 JSX 的话，会有 3 个问题：
+    // 1. 小程序出码的时候，循环变量没法拿到
+    // 2. 小程序出码的时候，很容易出现 Uncaught TypeError: Cannot read property 'avatar' of undefined
+    //    这样的异常(如下图的 50 行) -- 因为若直接出码，Rax 构建到小程序的时候会立即计算所有在视图中用到的变量
+    // 3. 通过 this.xxx 能拿到的东西太多了，而且自定义的 methods 可能会无意间破坏 Rax 框架或小程序框架在页面 this 上的东东
+    const customHandlers: HandlerSet<string> = {
+      expression(input: JSExpression, scope: IScope) {
+        return transformJsExpr(generateExpression(input), scope);
+      },
+      function(input, scope: IScope) {
+        return transformThis2Context(input.value || 'null', scope);
+      },
+    };
+
+    // 创建代码生成器
+    const commonNodeGenerator = createNodeGenerator({
+      handlers: customHandlers,
+      tagMapping: mapComponentNameToAliasOrKeepIt,
+      nodePlugins: [generateReactExprInJS, generateConditionReactCtrl, generateRaxLoopCtrl],
+      attrPlugins: [generateNodeAttrForRax],
+    });
+
+    // 生成 JSX 代码
+    const jsxContent = commonNodeGenerator(ir, rootScope);
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.ExternalDepsImport,
+      content: 'import { isMiniApp as __$$isMiniApp } from \'universal-env\';',
+      linkAfter: [],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: RAX_CHUNK_NAME.ClassRenderPre,
+      // TODO: setState, dataSourceMap, reloadDataSource, utils,
+      //       i18n, i18nFormat, getLocale, setLocale
+      //       这些在 Rax 的编译模式下不能在视图中直接访问，需要转化成 this.xxx
+      content: `
+        const __$$context = this._context;
+        const { state, setState, dataSourceMap, reloadDataSource, utils, constants, i18n, i18nFormat, getLocale, setLocale } = __$$context;
+      `,
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: RAX_CHUNK_NAME.ClassRenderJSX,
+      content: `return ${jsxContent};`,
+      linkAfter: [RAX_CHUNK_NAME.ClassRenderBegin, RAX_CHUNK_NAME.ClassRenderPre],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.CustomContent,
+      content: `
+
+        function __$$eval(expr) {
+          try {
+            return expr();
+          } catch (err) {
+            console.warn('Failed to evaluate: ', expr, err);
+          }
+        }
+
+        function __$$evalArray(expr) {
+          const res = __$$eval(expr);
+          return Array.isArray(res) ? res : [];
+        }
+
+      `,
+      linkAfter: [COMMON_CHUNK_NAME.FileExport],
+    });
+
+    return next;
+  };
+
+  return plugin;
+};
+
+export default pluginFactory;
+
+function transformJsExpr(expr: string, scope: IScope) {
+  if (!expr) {
+    return 'undefined';
+  }
+
+  if (isLiteralAtomicExpr(expr)) {
+    return expr;
+  }
+
+  const exprAst = parseExpression(expr);
+
+  // 对于下面这些比较安全的字面值，可以直接返回对应的表达式，而非包一层
+  if (isSimpleStraightLiteral(exprAst)) {
+    return expr;
+  }
+
+  switch (exprAst.type) {
+    // 对于直接写个函数的，则不用再包下，因为这样不会抛出异常的
+    case 'ArrowFunctionExpression':
+    case 'FunctionExpression':
+      return transformThis2Context(exprAst, scope);
+
+    default:
+      break;
+  }
+
+  // 其他的都需要包一层
+  return `__$$eval(() => (${transformThis2Context(exprAst, scope)}))`;
+}
+
+/** 判断是非是一些简单直接的字面值 */
+function isSimpleStraightLiteral(expr: Expression): boolean {
+  switch (expr.type) {
+    case 'BigIntLiteral':
+    case 'BooleanLiteral':
+    case 'DecimalLiteral':
+    case 'NullLiteral':
+    case 'NumericLiteral':
+    case 'RegExpLiteral':
+    case 'StringLiteral':
+      return true;
+    default:
+      return false;
+  }
+}
+
+function isImportAliasDefineChunk(
+  chunk: ICodeChunk,
+): chunk is ICodeChunk & {
+  ext: {
+    aliasName: string;
+    originalName: string;
+    dependency: NpmInfo;
+  };
+} {
+  return (
+    chunk.name === COMMON_CHUNK_NAME.ImportAliasDefine &&
+    !!chunk.ext &&
+    typeof chunk.ext.aliasName === 'string' &&
+    typeof chunk.ext.originalName === 'string' &&
+    !!(chunk.ext.dependency as NpmInfo | null)?.componentName
+  );
+}
+
+/**
+ * 判断是否是原子类型的表达式
+ */
+function isLiteralAtomicExpr(expr: string): boolean {
+  return expr === 'null' || expr === 'undefined' || expr === 'true' || expr === 'false' || /^-?\d+(\.\d+)?$/.test(expr);
+}
+
+/**
+ * 将所有的 this.xxx 替换为 __$$context.xxx
+ * @param expr
+ */
+function transformThis2Context(expr: string | Expression, scope: IScope): string {
+  // 下面这种字符串替换的方式虽然简单直接，但是对于复杂场景会误匹配，故后期改成了解析 AST 然后修改 AST 最后再重新生成代码的方式
+  // return expr
+  //   .replace(/\bthis\.item\./g, () => 'item.')
+  //   .replace(/\bthis\.index\./g, () => 'index.')
+  //   .replace(/\bthis\./g, () => '__$$context.');
+
+  return parseExpressionConvertThis2Context(expr, '__$$context', scope.bindings?.getAllBindings() || []);
+}
+
+function generateRaxLoopCtrl(
+  nodeItem: NodeSchema,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+  next?: NodePlugin,
+): CodePiece[] {
+  if (nodeItem.loop) {
+    const loopItemName = nodeItem.loopArgs?.[0] || 'item';
+    const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
+    const subScope = scope.createSubScope([loopItemName, loopIndexName]);
+    const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : [];
+
+    const loopDataExpr = `__$$evalArray(() => (${transformThis2Context(
+      generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }),
+      scope,
+    )}))`;
+
+    pieces.unshift({
+      value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => (`,
+      type: PIECE_TYPE.BEFORE,
+    });
+
+    pieces.push({
+      value: '))',
+      type: PIECE_TYPE.AFTER,
+    });
+
+    return pieces;
+  }
+
+  return next ? next(nodeItem, scope, config) : [];
+}
+
+function generateNodeAttrForRax(
+  attrData: { attrName: string; attrValue: CompositeValue },
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+  next?: AttrPlugin,
+): CodePiece[] {
+  if (!/^on/.test(attrData.attrName)) {
+    return next ? next(attrData, scope, config) : [];
+  }
+  // else: onXxx 的都是事件处理函数需要特殊处理下
+  return generateEventHandlerAttrForRax(attrData.attrName, attrData.attrValue, scope, config);
+}
+
+function generateEventHandlerAttrForRax(
+  attrName: string,
+  attrValue: CompositeValue,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+): CodePiece[] {
+  // -- 事件处理函数中 JSExpression 转成 JSFunction 来处理，避免当 JSExpression 处理的时候多包一层 eval 而导致 Rax 转码成小程序的时候出问题
+  const valueExpr = generateCompositeType(
+    isJSExpression(attrValue) ? { type: 'JSFunction', value: attrValue.value } : attrValue,
+    scope,
+    {
+      handlers: config?.handlers,
+    },
+  );
+
+  // 查询当前作用域下的变量
+  const currentScopeVariables = scope.bindings?.getAllBindings() || [];
+  if (currentScopeVariables.length <= 0) {
+    return [
+      {
+        type: PIECE_TYPE.ATTR,
+        value: `${attrName}={${valueExpr}}`,
+      },
+    ];
+  }
+
+  // 提取出所有的未定义的全局变量
+  const undeclaredVariablesInValueExpr = parseExpressionGetGlobalVariables(valueExpr);
+  const referencedLocalVariables =
+    _.intersection(undeclaredVariablesInValueExpr, currentScopeVariables);
+  if (referencedLocalVariables.length <= 0) {
+    return [
+      {
+        type: PIECE_TYPE.ATTR,
+        value: `${attrName}={${valueExpr}}`,
+      },
+    ];
+  }
+
+  const wrappedAttrValueExpr = [
+    '(...__$$args) => {',
+    '  if (__$$isMiniApp) {',
+    '    const __$$event = __$$args[0];',
+    ...referencedLocalVariables.map((localVar) => `const ${localVar} = __$$event.target.dataset.${localVar};`),
+    `    return (${valueExpr}).apply(this, __$$args);`,
+    '  } else {',
+    `    return (${valueExpr}).apply(this, __$$args);`,
+    '  }',
+    '}',
+  ].join('\n');
+
+  return [
+    ...referencedLocalVariables.map((localVar) => ({
+      type: PIECE_TYPE.ATTR,
+      value: `data-${changeCase.snake(localVar)}={${localVar}}`,
+    })),
+    {
+      type: PIECE_TYPE.ATTR,
+      value: `${attrName}={${wrappedAttrValueExpr}}`,
+    },
+  ];
+}
diff --git a/packages/code-generator/src/plugins/component/react/containerClass.ts b/packages/code-generator/src/plugins/component/react/containerClass.ts
index b84e7aa6e..6ba6ae640 100644
--- a/packages/code-generator/src/plugins/component/react/containerClass.ts
+++ b/packages/code-generator/src/plugins/component/react/containerClass.ts
@@ -1,3 +1,4 @@
+import changeCase from 'change-case';
 import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
 import { REACT_CHUNK_NAME } from './const';
 
@@ -18,14 +19,18 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
 
     const ir = next.ir as IContainerInfo;
 
+    // 将模块名转换成 PascalCase 的格式，并添加特定后缀，防止命名冲突
+    const componentClassName = `${changeCase.pascalCase(ir.moduleName)}$$Page`;
+
     next.chunks.push({
       type: ChunkType.STRING,
       fileType: FileType.JSX,
       name: CLASS_DEFINE_CHUNK_NAME.Start,
-      content: `class ${ir.moduleName} extends React.Component {`,
+      content: `class ${componentClassName} extends React.Component {`,
       linkAfter: [
         COMMON_CHUNK_NAME.ExternalDepsImport,
         COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
         COMMON_CHUNK_NAME.FileVarDefine,
         COMMON_CHUNK_NAME.FileUtilDefine,
       ],
@@ -36,7 +41,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       fileType: FileType.JSX,
       name: CLASS_DEFINE_CHUNK_NAME.End,
       content: '}',
-      linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, REACT_CHUNK_NAME.ClassRenderEnd],
+      linkAfter: [
+        CLASS_DEFINE_CHUNK_NAME.Start,
+        REACT_CHUNK_NAME.ClassRenderEnd,
+      ],
     });
 
     next.chunks.push({
@@ -52,10 +60,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       fileType: FileType.JSX,
       name: CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
       content: '}',
-      linkAfter: [
-        CLASS_DEFINE_CHUNK_NAME.ConstructorStart,
-        CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
-      ],
+      linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart, CLASS_DEFINE_CHUNK_NAME.ConstructorContent],
     });
 
     next.chunks.push({
@@ -75,21 +80,18 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       fileType: FileType.JSX,
       name: REACT_CHUNK_NAME.ClassRenderEnd,
       content: '}',
-      linkAfter: [
-        REACT_CHUNK_NAME.ClassRenderStart,
-        REACT_CHUNK_NAME.ClassRenderPre,
-        REACT_CHUNK_NAME.ClassRenderJSX,
-      ],
+      linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre, REACT_CHUNK_NAME.ClassRenderJSX],
     });
 
     next.chunks.push({
       type: ChunkType.STRING,
       fileType: FileType.JSX,
       name: COMMON_CHUNK_NAME.FileExport,
-      content: `export default ${ir.moduleName};`,
+      content: `export default ${componentClassName};`,
       linkAfter: [
         COMMON_CHUNK_NAME.ExternalDepsImport,
         COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
         COMMON_CHUNK_NAME.FileVarDefine,
         COMMON_CHUNK_NAME.FileUtilDefine,
         CLASS_DEFINE_CHUNK_NAME.End,
diff --git a/packages/code-generator/src/plugins/component/react/containerDataSource.ts b/packages/code-generator/src/plugins/component/react/containerDataSource.ts
index 8907dea36..84accc118 100644
--- a/packages/code-generator/src/plugins/component/react/containerDataSource.ts
+++ b/packages/code-generator/src/plugins/component/react/containerDataSource.ts
@@ -1,6 +1,7 @@
 import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
 
 import { generateCompositeType } from '../../../utils/compositeType';
+import Scope from '../../../utils/Scope';
 
 import {
   BuilderComponentPlugin,
@@ -28,10 +29,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
 
     const ir = next.ir as IContainerInfo;
 
+    const scope = Scope.createRootScope();
+
     if (ir.state) {
-      const { state } = ir;
+      const state = ir.state;
       const fields = Object.keys(state).map<string>((stateName) => {
-        const value = generateCompositeType(state[stateName]);
+        const value = generateCompositeType(state[stateName], scope);
         return `${stateName}: ${value},`;
       });
 
diff --git a/packages/code-generator/src/plugins/component/react/containerInitState.ts b/packages/code-generator/src/plugins/component/react/containerInitState.ts
index 3ab10463c..503e7ed0f 100644
--- a/packages/code-generator/src/plugins/component/react/containerInitState.ts
+++ b/packages/code-generator/src/plugins/component/react/containerInitState.ts
@@ -1,6 +1,7 @@
 import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
 
 import { generateCompositeType } from '../../../utils/compositeType';
+import Scope from '../../../utils/Scope';
 
 import {
   BuilderComponentPlugin,
@@ -29,11 +30,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
     };
 
     const ir = next.ir as IContainerInfo;
+    const scope = Scope.createRootScope();
 
     if (ir.state) {
-      const { state } = ir;
+      const state = ir.state;
       const fields = Object.keys(state).map<string>((stateName) => {
-        const value = generateCompositeType(state[stateName]);
+        const value = generateCompositeType(state[stateName], scope);
         return `${stateName}: ${value},`;
       });
 
diff --git a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts
index 585cd6d7e..000355b7d 100644
--- a/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts
+++ b/packages/code-generator/src/plugins/component/react/containerLifeCycle.ts
@@ -35,7 +35,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
     const ir = next.ir as IContainerInfo;
 
     if (ir.lifeCycles) {
-      const { lifeCycles } = ir;
+      const lifeCycles = ir.lifeCycles;
       const chunks = Object.keys(lifeCycles).map<ICodeChunk>((lifeCycleName) => {
         const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
         const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
diff --git a/packages/code-generator/src/plugins/component/react/containerMethod.ts b/packages/code-generator/src/plugins/component/react/containerMethod.ts
index ecc89d828..148f2cffd 100644
--- a/packages/code-generator/src/plugins/component/react/containerMethod.ts
+++ b/packages/code-generator/src/plugins/component/react/containerMethod.ts
@@ -30,7 +30,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
     const ir = next.ir as IContainerInfo;
 
     if (ir.methods) {
-      const { methods } = ir;
+      const methods = ir.methods;
       const chunks = Object.keys(methods).map<ICodeChunk>((methodName) => ({
         type: ChunkType.STRING,
         fileType: cfg.fileType,
diff --git a/packages/code-generator/src/plugins/component/react/jsx.ts b/packages/code-generator/src/plugins/component/react/jsx.ts
index 78ee3f790..ada4be7b7 100644
--- a/packages/code-generator/src/plugins/component/react/jsx.ts
+++ b/packages/code-generator/src/plugins/component/react/jsx.ts
@@ -10,6 +10,7 @@ import {
 import { REACT_CHUNK_NAME } from './const';
 
 import { createReactNodeGenerator } from '../../../utils/nodeToJSX';
+import Scope from '../../../utils/Scope';
 
 type PluginConfig = {
   fileType?: string;
@@ -23,7 +24,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
     ...config,
   };
 
-  const generator = createReactNodeGenerator({ nodeTypeMapping: cfg.nodeTypeMapping });
+  const { nodeTypeMapping } = cfg;
+
+  const generator = createReactNodeGenerator({
+    tagMapping: (v) => nodeTypeMapping[v] || v,
+  });
 
   const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
     const next: ICodeStruct = {
@@ -31,17 +36,15 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
     };
 
     const ir = next.ir as IContainerInfo;
-    const jsxContent = generator(ir);
+    const scope = Scope.createRootScope();
+    const jsxContent = generator(ir, scope);
 
     next.chunks.push({
       type: ChunkType.STRING,
       fileType: cfg.fileType,
       name: REACT_CHUNK_NAME.ClassRenderJSX,
       content: `return ${jsxContent};`,
-      linkAfter: [
-        REACT_CHUNK_NAME.ClassRenderStart,
-        REACT_CHUNK_NAME.ClassRenderPre,
-      ],
+      linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre],
     });
 
     return next;
diff --git a/packages/code-generator/src/plugins/component/react/reactCommonDeps.ts b/packages/code-generator/src/plugins/component/react/reactCommonDeps.ts
index 51af22e4f..2e71f8d90 100644
--- a/packages/code-generator/src/plugins/component/react/reactCommonDeps.ts
+++ b/packages/code-generator/src/plugins/component/react/reactCommonDeps.ts
@@ -6,7 +6,6 @@ import {
   ChunkType,
   FileType,
   ICodeStruct,
-  IContainerInfo,
 } from '../../../types';
 
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
diff --git a/packages/code-generator/src/plugins/component/recore/const.ts b/packages/code-generator/src/plugins/component/recore/const.ts
deleted file mode 100644
index b848f42aa..000000000
--- a/packages/code-generator/src/plugins/component/recore/const.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const RECORE_CHUNK_NAME = {
-
-};
diff --git a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts
index 8464ff180..a071f65c9 100644
--- a/packages/code-generator/src/plugins/component/recore/pageDataSource.ts
+++ b/packages/code-generator/src/plugins/component/recore/pageDataSource.ts
@@ -1,4 +1,7 @@
+import { JSExpression, CompositeValue } from '@ali/lowcode-types';
+
 import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
+import Scope from '../../../utils/Scope';
 
 import {
   BuilderComponentPlugin,
@@ -7,15 +10,13 @@ import {
   FileType,
   ICodeStruct,
   IContainerInfo,
-  IJSExpression,
-  CompositeValue,
 } from '../../../types';
 
 import { generateCompositeType } from '../../../utils/compositeType';
 import { generateExpression } from '../../../utils/jsExpression';
 
 function packJsExpression(exp: unknown): string {
-  const expression = exp as IJSExpression;
+  const expression = exp as JSExpression;
   const funcStr = generateExpression(expression);
   return `function() { return (${funcStr}); }`;
 }
@@ -27,6 +28,8 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
     };
 
     const ir = next.ir as IContainerInfo;
+    const scope = Scope.createRootScope();
+
     if (ir.dataSource) {
       const { dataSource } = ir;
       const { list, ...rest } = dataSource;
@@ -35,13 +38,13 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
 
       const extConfigs = Object.keys(rest).map((extConfigName) => {
         const value = (rest as Record<string, CompositeValue>)[extConfigName];
-        const valueStr = generateCompositeType(value);
+        const valueStr = generateCompositeType(value, scope);
         return `${extConfigName}: ${valueStr}`;
       });
 
       attrs = [...attrs, ...extConfigs];
 
-      const listProp = generateCompositeType((list as unknown) as CompositeValue, {
+      const listProp = generateCompositeType((list as unknown) as CompositeValue, scope, {
         handlers: {
           expression: packJsExpression,
         },
diff --git a/packages/code-generator/src/plugins/component/recore/pageStyle.ts b/packages/code-generator/src/plugins/component/recore/pageStyle.ts
index fc8ca41b5..2a6a8eeca 100644
--- a/packages/code-generator/src/plugins/component/recore/pageStyle.ts
+++ b/packages/code-generator/src/plugins/component/recore/pageStyle.ts
@@ -22,7 +22,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
         type: ChunkType.STRING,
         fileType: FileType.TS,
         name: CLASS_DEFINE_CHUNK_NAME.StaticVar,
-        content: `static cssText = '${ir.css.replace(/\'/g, '\\\'')}';`,
+        content: `static cssText = '${ir.css.replace(/'/g, "\\'")}';`,
         linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.StaticVar]],
       });
     }
diff --git a/packages/code-generator/src/plugins/component/recore/pageVmBody.ts b/packages/code-generator/src/plugins/component/recore/pageVmBody.ts
index 9f5a33d7c..e30327372 100644
--- a/packages/code-generator/src/plugins/component/recore/pageVmBody.ts
+++ b/packages/code-generator/src/plugins/component/recore/pageVmBody.ts
@@ -1,21 +1,22 @@
+import { NodeSchema } from '@ali/lowcode-types';
+
 import {
   BuilderComponentPlugin,
   BuilderComponentPluginFactory,
   ChunkType,
   ICodeStruct,
   IContainerInfo,
-  IComponentNodeItem,
-  INodeGeneratorContext,
+  IScope,
   CodePiece,
   PIECE_TYPE,
 } from '../../../types';
 import { COMMON_CHUNK_NAME } from '../../../const/generator';
 
-import { createNodeGenerator, generateString } from '../../../utils/nodeToJSX';
-import { generateExpression } from '../../../utils/jsExpression';
+import { createNodeGenerator } from '../../../utils/nodeToJSX';
 import { generateCompositeType } from '../../../utils/compositeType';
+import Scope from '../../../utils/Scope';
 
-const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
+const generateGlobalProps = (nodeItem: NodeSchema): CodePiece[] => {
   return [
     {
       value: `{...globalProps.${nodeItem.componentName}}`,
@@ -24,11 +25,11 @@ const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNod
   ];
 };
 
-const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
+const generateCtrlLine = (nodeItem: NodeSchema, scope: IScope): CodePiece[] => {
   const pieces: CodePiece[] = [];
 
   if (nodeItem.loop && nodeItem.loopArgs) {
-    const loopDataExp = generateCompositeType(nodeItem.loop);
+    const loopDataExp = generateCompositeType(nodeItem.loop, scope);
     pieces.push({
       type: PIECE_TYPE.ATTR,
       value: `x-for={${loopDataExp}}`,
@@ -41,7 +42,7 @@ const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeIt
   }
 
   if (nodeItem.condition) {
-    const conditionExp = generateCompositeType(nodeItem.condition);
+    const conditionExp = generateCompositeType(nodeItem.condition, scope);
     pieces.push({
       type: PIECE_TYPE.ATTR,
       value: `x-if={${conditionExp}}`,
@@ -52,13 +53,9 @@ const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeIt
 };
 
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
-  const generator = createNodeGenerator(
-    {
-      string: generateString,
-      expression: (input) => [generateExpression(input)],
-    },
-    [generateGlobalProps, generateCtrlLine],
-  );
+  const generator = createNodeGenerator({
+    nodePlugins: [generateGlobalProps, generateCtrlLine],
+  });
 
   const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
     const next: ICodeStruct = {
@@ -66,8 +63,9 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
     };
 
     const ir = next.ir as IContainerInfo;
+    const scope = Scope.createRootScope();
 
-    const vxContent = generator(ir);
+    const vxContent = generator(ir, scope);
 
     next.chunks.push({
       type: ChunkType.STRING,
diff --git a/packages/code-generator/src/plugins/component/recore/pageVmHeader.ts b/packages/code-generator/src/plugins/component/recore/pageVmHeader.ts
index 71ee2335c..8bfaa3dd1 100644
--- a/packages/code-generator/src/plugins/component/recore/pageVmHeader.ts
+++ b/packages/code-generator/src/plugins/component/recore/pageVmHeader.ts
@@ -1,11 +1,6 @@
 import { COMMON_CHUNK_NAME } from '../../../const/generator';
 
-import {
-  BuilderComponentPlugin,
-  BuilderComponentPluginFactory,
-  ChunkType,
-  ICodeStruct,
-} from '../../../types';
+import { BuilderComponentPlugin, BuilderComponentPluginFactory, ChunkType, ICodeStruct } from '../../../types';
 
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
   const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
diff --git a/packages/code-generator/src/plugins/project/constants.ts b/packages/code-generator/src/plugins/project/constants.ts
index d274499b4..08870e507 100644
--- a/packages/code-generator/src/plugins/project/constants.ts
+++ b/packages/code-generator/src/plugins/project/constants.ts
@@ -8,6 +8,7 @@ import {
   ICodeStruct,
   IProjectInfo,
 } from '../../types';
+import Scope from '../../utils/Scope';
 
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
   const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
@@ -16,35 +17,39 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
     };
 
     const ir = next.ir as IProjectInfo;
-    if (ir.constants) {
-      const constantStr = generateCompositeType(ir.constants);
+    const scope = Scope.createRootScope();
+    const constantStr = generateCompositeType(ir.constants || {}, scope);
 
-      next.chunks.push({
-        type: ChunkType.STRING,
-        fileType: FileType.JS,
-        name: COMMON_CHUNK_NAME.FileVarDefine,
-        content: `
-          const constantConfig = ${constantStr};
-        `,
-        linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
-      });
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.FileVarDefine,
+      content: `
+        const __$$constants = (${constantStr});
+      `,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+      ],
+    });
 
-      next.chunks.push({
-        type: ChunkType.STRING,
-        fileType: FileType.JS,
-        name: COMMON_CHUNK_NAME.FileExport,
-        content: `
-          export default constantConfig;
-        `,
-        linkAfter: [
-          COMMON_CHUNK_NAME.ExternalDepsImport,
-          COMMON_CHUNK_NAME.InternalDepsImport,
-          COMMON_CHUNK_NAME.FileVarDefine,
-          COMMON_CHUNK_NAME.FileUtilDefine,
-          COMMON_CHUNK_NAME.FileMainContent,
-        ],
-      });
-    }
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.FileExport,
+      content: `
+        export default __$$constants;
+      `,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+        COMMON_CHUNK_NAME.FileMainContent,
+      ],
+    });
 
     return next;
   };
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts
index 0cf3918a7..b5dc2d8f8 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entry.ts
@@ -6,7 +6,6 @@ import {
   ChunkType,
   FileType,
   ICodeStruct,
-  IProjectInfo,
 } from '../../../../../types';
 
 const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
@@ -15,8 +14,6 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       ...pre,
     };
 
-    const ir = next.ir as IProjectInfo;
-
     next.chunks.push({
       type: ChunkType.STRING,
       fileType: FileType.JS,
@@ -34,10 +31,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       content: `
         const appConfig = {
           app: {
-            rootId: '${ir.config.targetRootID}',
+            rootId: 'app',
           },
           router: {
-            type: '${ir.config.historyMode}',
+            type: 'hash',
           },
         };
         createApp(appConfig);
@@ -45,6 +42,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       linkAfter: [
         COMMON_CHUNK_NAME.ExternalDepsImport,
         COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
         COMMON_CHUNK_NAME.FileVarDefine,
         COMMON_CHUNK_NAME.FileUtilDefine,
       ],
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts
index a0ca3cdf1..e5837a8dd 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/entryHtml.ts
@@ -28,10 +28,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
             <meta charset="utf-8" />
             <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1" />
             <meta name="viewport" content="width=device-width" />
-            <title>${ir.meta.name}</title>
+            <title>${ir?.meta?.name || 'Ice App'}</title>
           </head>
           <body>
-            <div id="${ir.config.targetRootID}"></div>
+            <div id="app"></div>
           </body>
         </html>
       `,
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts
index f238b6af0..c3eb5198d 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/packageJSON.ts
@@ -1,3 +1,5 @@
+import { PackageJSON } from '@ali/lowcode-types';
+
 import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
 
 import {
@@ -6,11 +8,10 @@ import {
   ChunkType,
   FileType,
   ICodeStruct,
-  IPackageJSON,
   IProjectInfo,
 } from '../../../../../types';
 
-interface IIceJsPackageJSON extends IPackageJSON {
+interface IIceJsPackageJSON extends PackageJSON {
   ideMode: {
     name: string;
   };
@@ -73,7 +74,9 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       originTemplate: '@alifd/scaffold-lite-js',
     };
 
-    ir.packages.forEach((packageInfo) => (packageJson.dependencies[packageInfo.package] = packageInfo.version));
+    ir.packages.forEach((packageInfo) => {
+      packageJson.dependencies[packageInfo.package] = packageInfo.version;
+    });
 
     next.chunks.push({
       type: ChunkType.JSON,
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts b/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts
index bb2d7c47f..0e2e8c1f7 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/plugins/router.ts
@@ -39,7 +39,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
             children: [
               ${ir.routes
     .map(
-      route => `
+      (route) => `
                     {
                       path: '${route.path}',
                       component: ${route.componentName},
@@ -54,6 +54,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
       linkAfter: [
         COMMON_CHUNK_NAME.ExternalDepsImport,
         COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
         COMMON_CHUNK_NAME.FileUtilDefine,
       ],
     });
@@ -69,6 +70,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
         COMMON_CHUNK_NAME.ExternalDepsImport,
         COMMON_CHUNK_NAME.InternalDepsImport,
         COMMON_CHUNK_NAME.FileUtilDefine,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
         COMMON_CHUNK_NAME.FileVarDefine,
         COMMON_CHUNK_NAME.FileMainContent,
       ],
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts
index c5a268127..1fb96bec0 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/README.md.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'README',
     'md',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts
index 9b99a2185..0f9e8a532 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/abc.json.ts
@@ -1,17 +1,17 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
-    'abc',
-    'json',
-    `
+export default function getFile(): [string[], ResultFile] {
+  return [
+    [],
+    {
+      name: 'abc',
+      ext: 'json',
+      content: `
 {
   "type": "ice-app",
   "builder": "@ali/builder-ice-app"
 }
     `,
-  );
-
-  return [[], file];
+    },
+  ];
 }
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts
index b30c7c58f..533aea2ad 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/build.json.ts
@@ -1,11 +1,12 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
-    'build',
-    'json',
-    `
+export default function getFile(): [string[], ResultFile] {
+  return [
+    [],
+    {
+      name: 'build',
+      ext: 'json',
+      content: `
 {
   "entry": "src/app.js",
   "plugins": [
@@ -26,8 +27,7 @@ export default function getFile(): [string[], IResultFile] {
     "@ali/build-plugin-ice-def"
   ]
 }
-    `,
-  );
-
-  return [[], file];
+      `,
+    },
+  ];
 }
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts
index 14876b397..bf80464dd 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/editorconfig.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.editorconfig',
     '',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts
index 8f6f68e1f..a26db9de1 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintignore.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.eslintignore',
     '',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts
index ad7ce4480..733c3e174 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/eslintrc.js.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.eslintrc',
     'js',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts
index e7bed2e9e..408a93205 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/gitignore.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.gitignore',
     '',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts
index f5b5e9fa2..cde81c77f 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/jsconfig.json.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'jsconfig',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts
index f6d2e9ed2..6206dca28 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierignore.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.prettierignore',
     '',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts
index 66531c8dc..1793891ed 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/prettierrc.js.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.prettierrc',
     'js',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts
index 639337aa5..131728077 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.jsx.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'jsx',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts
index cb57ac646..5093a4cf9 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Footer/index.module.scss.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'module.scss',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts
index cef5376ae..efb8377ed 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.jsx.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'jsx',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts
index 6969595e6..ebbf1e453 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/Logo/index.module.scss.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'module.scss',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts
index b722e6695..302d16d71 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/components/PageNav/index.jsx.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'jsx',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts
index 6f7cd7b92..8a97f76d8 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/index.jsx.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'jsx',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts
index 70ed04738..12b18285b 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/src/layouts/BasicLayout/menuConfig.js.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'menuConfig',
     'js',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts
index 5d369298a..1e7ccc9b3 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintignore.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.stylelintignore',
     '',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts
index 7ed60d2c9..12052b1e1 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/stylelintrc.js.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.stylelintrc',
     'js',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts
index 4b8aab7ed..e99b00d06 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/files/tsconfig.json.ts
@@ -1,8 +1,8 @@
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'tsconfig',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts b/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts
index d048bd389..e6469a67e 100644
--- a/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts
+++ b/packages/code-generator/src/plugins/project/framework/icejs/template/index.ts
@@ -1,8 +1,7 @@
-import ResultDir from '../../../../../model/ResultDir';
-import {
-  IProjectTemplate,
-  IResultDir,
-} from '../../../../../types';
+import { ResultDir } from '@ali/lowcode-types';
+import { IProjectTemplate } from '../../../../../types';
+
+import { createResultDir } from '../../../../../utils/resultHelper';
 import { runFileGenerator } from '../../../../../utils/templateHelper';
 
 import file12 from './files/abc.json';
@@ -68,8 +67,8 @@ const icejsTemplate: IProjectTemplate = {
     },
   },
 
-  generateTemplate(): IResultDir {
-    const root = new ResultDir('.');
+  generateTemplate(): ResultDir {
+    const root = createResultDir('.');
 
     runFileGenerator(root, file1);
     runFileGenerator(root, file2);
diff --git a/packages/code-generator/src/plugins/project/framework/rax/index.ts b/packages/code-generator/src/plugins/project/framework/rax/index.ts
new file mode 100644
index 000000000..a17e82132
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/index.ts
@@ -0,0 +1,19 @@
+import template from './template';
+import entry from './plugins/entry';
+import appConfig from './plugins/appConfig';
+import buildConfig from './plugins/buildConfig';
+import entryDocument from './plugins/entryDocument';
+import globalStyle from './plugins/globalStyle';
+import packageJSON from './plugins/packageJSON';
+
+export default {
+  template,
+  plugins: {
+    appConfig,
+    buildConfig,
+    entry,
+    entryDocument,
+    globalStyle,
+    packageJSON,
+  },
+};
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/appConfig.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/appConfig.ts
new file mode 100644
index 000000000..354e5f93c
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/appConfig.ts
@@ -0,0 +1,46 @@
+import changeCase from 'change-case';
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IParseResult,
+} from '../../../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IParseResult;
+
+    const routes = ir.globalRouter?.routes?.map((route) => ({
+      path: route.path,
+      source: `pages/${changeCase.pascalCase(route.fileName)}/index`,
+    })) || [{ path: '/', source: 'pages/Home/index' }];
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSON,
+      name: COMMON_CHUNK_NAME.CustomContent,
+      content: `
+{
+  "routes": ${JSON.stringify(routes, null, 2)},
+  "window": {
+    "title": ${JSON.stringify(ir.project?.meta?.title || ir.project?.meta?.name || '')}
+  }
+}
+      `,
+      linkAfter: [],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/buildConfig.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/buildConfig.ts
new file mode 100644
index 000000000..070db3ee3
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/buildConfig.ts
@@ -0,0 +1,52 @@
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IParseResult,
+} from '../../../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IParseResult;
+    const miniAppBuildType = ir.project?.config.miniAppBuildType;
+
+    const buildCfg = {
+      inlineStyle: false,
+      plugins: [
+        [
+          'build-plugin-rax-app',
+          {
+            targets: ['web', 'miniapp'],
+            miniapp: miniAppBuildType
+              ? {
+                buildType: miniAppBuildType,
+              }
+              : undefined,
+          },
+        ],
+        '@ali/build-plugin-rax-app-def',
+      ],
+    };
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSON,
+      name: COMMON_CHUNK_NAME.CustomContent,
+      content: JSON.stringify(buildCfg, null, 2) + '\n',
+      linkAfter: [],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/entry.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/entry.ts
new file mode 100644
index 000000000..bea52e2af
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/entry.ts
@@ -0,0 +1,51 @@
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+} from '../../../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.ExternalDepsImport,
+      content: `
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+`,
+      linkAfter: [],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.FileMainContent,
+      content: `
+runApp(appConfig);
+`,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+      ],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/entryDocument.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/entryDocument.ts
new file mode 100644
index 000000000..cb5240139
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/entryDocument.ts
@@ -0,0 +1,59 @@
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IProjectInfo,
+} from '../../../../../types';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IProjectInfo;
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JSX,
+      name: COMMON_CHUNK_NAME.CustomContent,
+      content: `
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>${ir?.meta?.name || 'Rax App'}</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
+`,
+      linkAfter: [],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/globalStyle.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/globalStyle.ts
new file mode 100644
index 000000000..335fc4ffe
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/globalStyle.ts
@@ -0,0 +1,64 @@
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IProjectInfo,
+} from '../../../../../types';
+
+export type GlobalStylePluginConfig = {
+  fileType: string;
+};
+
+const pluginFactory: BuilderComponentPluginFactory<GlobalStylePluginConfig> = (
+  config?: Partial<GlobalStylePluginConfig>,
+) => {
+  const cfg: GlobalStylePluginConfig = {
+    fileType: FileType.SCSS,
+    ...config,
+  };
+
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IProjectInfo;
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.StyleDepsImport,
+      content: '',
+      linkAfter: [],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.StyleCssContent,
+      content: `
+body {
+  -webkit-font-smoothing: antialiased;
+}
+`,
+      linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: cfg.fileType,
+      name: COMMON_CHUNK_NAME.StyleCssContent,
+      content: ir.css || '',
+      linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
diff --git a/packages/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts b/packages/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
new file mode 100644
index 000000000..b834a2855
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/plugins/packageJSON.ts
@@ -0,0 +1,115 @@
+import { NpmInfo, PackageJSON } from '@ali/lowcode-types';
+import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
+
+import {
+  BuilderComponentPlugin,
+  BuilderComponentPluginFactory,
+  ChunkType,
+  FileType,
+  ICodeStruct,
+  IProjectInfo,
+} from '../../../../../types';
+import { isNpmInfo } from '../../../../../utils/schema';
+import { calcCompatibleVersion } from '../../../../../utils/version';
+
+const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
+  const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
+    const next: ICodeStruct = {
+      ...pre,
+    };
+
+    const ir = next.ir as IProjectInfo;
+
+    const npmDeps = getNpmDependencies(ir);
+
+    const packageJson: PackageJSON = {
+      name: '@ali/rax-app-demo',
+      private: true,
+      version: '1.0.0',
+      scripts: {
+        build: 'build-scripts build',
+        start: 'build-scripts start',
+        lint: 'eslint --ext .js --ext .jsx ./',
+      },
+      dependencies: {
+        '@ali/lowcode-datasource-engine': '*',
+        // TODO: 如何动态获取下面这些依赖？
+        '@ali/lowcode-datasource-url-params-handler': '*',
+        '@ali/lowcode-datasource-fetch-handler': '*',
+        '@ali/lowcode-datasource-mtop-handler': '*',
+        '@ali/lowcode-datasource-mopen-handler': '*',
+        'universal-env': '^3.2.0',
+        'intl-messageformat': '^9.3.6',
+        rax: '^1.1.0',
+        'rax-app': '^2.0.0',
+        'rax-document': '^0.1.0',
+        ...npmDeps.reduce(
+          (acc, npm) => ({
+            ...acc,
+            [npm.package]: npm.version || '*',
+          }),
+          {} as Record<string, string>,
+        ),
+      },
+      devDependencies: {
+        'build-plugin-rax-app': '^5.0.0',
+        '@alib/build-scripts': '^0.1.0',
+        '@typescript-eslint/eslint-plugin': '^2.11.0',
+        '@typescript-eslint/parser': '^2.11.0',
+        'babel-eslint': '^10.0.3',
+        eslint: '^6.8.0',
+        'eslint-config-rax': '^0.1.0',
+        'eslint-plugin-import': '^2.20.0',
+        'eslint-plugin-module': '^0.1.0',
+        'eslint-plugin-react': '^7.18.0',
+        '@ali/build-plugin-rax-app-def': '^1.0.0',
+      },
+    };
+
+    next.chunks.push({
+      type: ChunkType.JSON,
+      fileType: FileType.JSON,
+      name: COMMON_CHUNK_NAME.FileMainContent,
+      content: packageJson,
+      linkAfter: [],
+    });
+
+    return next;
+  };
+  return plugin;
+};
+
+export default pluginFactory;
+
+function getNpmDependencies(project: IProjectInfo): NpmInfo[] {
+  const npmDeps: NpmInfo[] = [];
+  const npmNameToPkgMap = new Map<string, NpmInfo>();
+
+  const allDeps = [...(project.containersDeps || []), ...(project.utilsDeps || [])];
+
+  allDeps.forEach((dep) => {
+    if (!isNpmInfo(dep)) {
+      return;
+    }
+
+    const existing = npmNameToPkgMap.get(dep.package);
+    if (!existing) {
+      npmNameToPkgMap.set(dep.package, dep);
+      npmDeps.push(dep);
+      return;
+    }
+
+    if (existing.version !== dep.version) {
+      try {
+        npmNameToPkgMap.set(dep.package, {
+          ...existing,
+          version: calcCompatibleVersion(existing.version, dep.version),
+        });
+      } catch (e) {
+        throw new Error(`Cannot find compatible version for ${dep.package}. Detail: ${e.message}`);
+      }
+    }
+  });
+
+  return npmDeps;
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/README.md.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/README.md.ts
new file mode 100644
index 000000000..6a4969ecf
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/README.md.ts
@@ -0,0 +1,27 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    'README',
+    'md',
+    `# @ali/rax-component-demo
+
+## Getting Started
+
+### \`npm run start\`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### \`npm run build\`
+
+Builds the app for production to the \`build\` folder.
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/abc.json.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/abc.json.ts
new file mode 100644
index 000000000..b199762cd
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/abc.json.ts
@@ -0,0 +1,19 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    'abc',
+    'json',
+    `{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/build.json.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/build.json.ts
new file mode 100644
index 000000000..ba4e9a9f3
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/build.json.ts
@@ -0,0 +1,24 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    'build',
+    'json',
+    `{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"]
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/editorconfig.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/editorconfig.ts
new file mode 100644
index 000000000..8fc51f1f8
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/editorconfig.ts
@@ -0,0 +1,25 @@
+
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    '.editorconfig',
+    '',
+    `# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintignore.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintignore.ts
new file mode 100644
index 000000000..36b7eb0cc
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintignore.ts
@@ -0,0 +1,23 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    '.eslintignore',
+    '',
+    `# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintrc.js.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintrc.js.ts
new file mode 100644
index 000000000..944c925ac
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/eslintrc.js.ts
@@ -0,0 +1,16 @@
+
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    '.eslintrc',
+    'js',
+    `module.exports = {
+  extends: ['rax'],
+};
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/files/gitignore.ts b/packages/code-generator/src/plugins/project/framework/rax/template/files/gitignore.ts
new file mode 100644
index 000000000..a3ff8f6ee
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/files/gitignore.ts
@@ -0,0 +1,29 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
+
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
+    '.gitignore',
+    '',
+    `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
+`,
+  );
+
+  return [[], file];
+}
diff --git a/packages/code-generator/src/plugins/project/framework/rax/template/index.ts b/packages/code-generator/src/plugins/project/framework/rax/template/index.ts
new file mode 100644
index 000000000..53289a3a8
--- /dev/null
+++ b/packages/code-generator/src/plugins/project/framework/rax/template/index.ts
@@ -0,0 +1,78 @@
+import { ResultDir } from '@ali/lowcode-types';
+import { IProjectTemplate } from '../../../../../types';
+
+import { runFileGenerator } from '../../../../../utils/templateHelper';
+import { createResultDir } from '../../../../../utils/resultHelper';
+
+import file0 from './files/editorconfig';
+import file1 from './files/eslintignore';
+import file2 from './files/eslintrc.js';
+import file3 from './files/gitignore';
+import file4 from './files/README.md';
+import file5 from './files/abc.json';
+
+const raxAppTemplate: IProjectTemplate = {
+  slots: {
+    components: {
+      path: ['src', 'components'],
+    },
+    pages: {
+      path: ['src', 'pages'],
+    },
+    router: {
+      path: ['src'],
+      fileName: 'router',
+    },
+    entry: {
+      path: ['src'],
+      fileName: 'app',
+    },
+    appConfig: {
+      path: ['src'],
+      fileName: 'app',
+    },
+    buildConfig: {
+      path: [],
+      fileName: 'build',
+    },
+    constants: {
+      path: ['src'],
+      fileName: 'constants',
+    },
+    utils: {
+      path: ['src'],
+      fileName: 'utils',
+    },
+    i18n: {
+      path: ['src'],
+      fileName: 'i18n',
+    },
+    globalStyle: {
+      path: ['src'],
+      fileName: 'global',
+    },
+    htmlEntry: {
+      path: ['src', 'document'],
+      fileName: 'index',
+    },
+    packageJSON: {
+      path: [],
+      fileName: 'package',
+    },
+  },
+
+  generateTemplate(): ResultDir {
+    const root = createResultDir('.');
+
+    runFileGenerator(root, file0);
+    runFileGenerator(root, file1);
+    runFileGenerator(root, file2);
+    runFileGenerator(root, file3);
+    runFileGenerator(root, file4);
+    runFileGenerator(root, file5);
+
+    return root;
+  },
+};
+
+export default raxAppTemplate;
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/.editorconfig.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/.editorconfig.ts
index 737b32b80..ace9684f8 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/.editorconfig.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/.editorconfig.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.editorconfig',
     '',
     `
@@ -29,4 +28,3 @@ trim_trailing_whitespace = false
 
   return [[], file];
 }
-  
\ No newline at end of file
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/.eslintignore.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/.eslintignore.ts
index 42c1be15c..bb64b9a7e 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/.eslintignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/.eslintignore.ts
@@ -1,9 +1,9 @@
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.eslintignore',
     '',
     `
@@ -23,4 +23,3 @@ packages/solution
 
   return [[], file];
 }
-  
\ No newline at end of file
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/.gitignore.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/.gitignore.ts
index fd89e80eb..cd625e88a 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/.gitignore.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/.gitignore.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.gitignore',
     '',
     `
@@ -54,4 +53,3 @@ Thumbs.db
 
   return [[], file];
 }
-  
\ No newline at end of file
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/.prettierrc.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/.prettierrc.ts
index 19cd24fbc..0b1834cea 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/.prettierrc.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/.prettierrc.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     '.prettierrc',
     '',
     `
@@ -19,4 +18,3 @@ export default function getFile(): [string[], IResultFile] {
 
   return [[], file];
 }
-  
\ No newline at end of file
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/README.md.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/README.md.ts
index f90fd7d87..546c38812 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/README.md.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/README.md.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'README',
     'md',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/abc.json.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/abc.json.ts
index d83eeccfb..7680835ea 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/abc.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/abc.json.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'abc',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/build.json.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/build.json.ts
index 16590134d..8133434fd 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/build.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/build.json.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'build',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/package.json.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/package.json.ts
index 2e82c8266..f6c1cc573 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/package.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/package.json.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'package',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/public/index.html.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/public/index.html.ts
index c0d09de31..e81328b1a 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/public/index.html.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/public/index.html.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'html',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/app.ts.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/app.ts.ts
index b4d86e5e6..6cb5605bc 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/app.ts.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/app.ts.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'app',
     'ts',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/components.ts.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/components.ts.ts
index b08b4593b..db9f218e6 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/components.ts.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/components.ts.ts
@@ -1,15 +1,14 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'components',
     'ts',
     `
 /**
  * 乐高组件
- */ 
+ */
 import Div from '@ali/vc-div/build/view';
 import Text from '@ali/vc-text/build/view';
 import Slot from '@ali/vc-slot/build/view';
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/utils.ts.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/utils.ts.ts
index 241186e48..7ed9659e0 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/utils.ts.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/config/utils.ts.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'utils',
     'ts',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/index.ts.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/index.ts.ts
index 8c12c90bf..bbcad9a1e 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/index.ts.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/index.ts.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'index',
     'ts',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/router.ts.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/router.ts.ts
index 78d1fff61..a183467c9 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/src/router.ts.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/src/router.ts.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'router',
     'ts',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/files/tsconfig.json.ts b/packages/code-generator/src/plugins/project/framework/recore/template/files/tsconfig.json.ts
index cb75cf556..c777f1863 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/files/tsconfig.json.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/files/tsconfig.json.ts
@@ -1,9 +1,8 @@
+import { ResultFile } from '@ali/lowcode-types';
+import { createResultFile } from '../../../../../../utils/resultHelper';
 
-import ResultFile from '../../../../../../model/ResultFile';
-import { IResultFile } from '../../../../../../types';
-
-export default function getFile(): [string[], IResultFile] {
-  const file = new ResultFile(
+export default function getFile(): [string[], ResultFile] {
+  const file = createResultFile(
     'tsconfig',
     'json',
     `
diff --git a/packages/code-generator/src/plugins/project/framework/recore/template/index.ts b/packages/code-generator/src/plugins/project/framework/recore/template/index.ts
index 1fd9565b9..04bd9fe83 100644
--- a/packages/code-generator/src/plugins/project/framework/recore/template/index.ts
+++ b/packages/code-generator/src/plugins/project/framework/recore/template/index.ts
@@ -1,8 +1,6 @@
-import ResultDir from '../../../../../model/ResultDir';
-import {
-  IProjectTemplate,
-  IResultDir,
-} from '../../../../../types';
+import { ResultDir } from '@ali/lowcode-types';
+import { IProjectTemplate } from '../../../../../types';
+import { createResultDir } from '../../../../../utils/resultHelper';
 import { runFileGenerator } from '../../../../../utils/templateHelper';
 
 import file1 from './files/abc.json';
@@ -28,8 +26,8 @@ const icejsTemplate: IProjectTemplate = {
     },
   },
 
-  generateTemplate(): IResultDir {
-    const root = new ResultDir('.');
+  generateTemplate(): ResultDir {
+    const root = createResultDir('.');
 
     runFileGenerator(root, file1);
     runFileGenerator(root, file2);
diff --git a/packages/code-generator/src/plugins/project/i18n.ts b/packages/code-generator/src/plugins/project/i18n.ts
index 4e4675a04..eaac073c8 100644
--- a/packages/code-generator/src/plugins/project/i18n.ts
+++ b/packages/code-generator/src/plugins/project/i18n.ts
@@ -1,5 +1,5 @@
 import { COMMON_CHUNK_NAME } from '../../const/generator';
-import { generateCompositeType } from '../../utils/compositeType';
+
 import {
   BuilderComponentPlugin,
   BuilderComponentPluginFactory,
@@ -16,51 +16,73 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
     };
 
     const ir = next.ir as IProjectInfo;
-    if (ir.i18n) {
-      const i18nStr = generateCompositeType(ir.i18n);
+    const i18nStr = ir.i18n ? JSON.stringify(ir.i18n, null, 2) : '{}';
 
-      next.chunks.push({
-        type: ChunkType.STRING,
-        fileType: FileType.JS,
-        name: COMMON_CHUNK_NAME.FileMainContent,
-        content: `
-          const i18nConfig = ${i18nStr};
-          let locale = 'en_US';
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.FileMainContent,
+      content: `
+        import IntlMessageFormat from 'intl-messageformat';
 
-          const changeLocale = (target) => {
-            locale = target;
-          };
+        const i18nConfig = ${i18nStr};
 
-          const i18n = key => i18nConfig && i18nConfig[locale] && i18nConfig[locale][key] || '';
-        `,
-        linkAfter: [
-          COMMON_CHUNK_NAME.ExternalDepsImport,
-          COMMON_CHUNK_NAME.InternalDepsImport,
-          COMMON_CHUNK_NAME.FileVarDefine,
-          COMMON_CHUNK_NAME.FileUtilDefine,
-        ],
-      });
+        let locale = 'en-US';
 
-      next.chunks.push({
-        type: ChunkType.STRING,
-        fileType: FileType.JS,
-        name: COMMON_CHUNK_NAME.FileExport,
-        content: `
-          export {
-            changeLocale,
-            i18n,
-          };
-        `,
-        linkAfter: [
-          COMMON_CHUNK_NAME.ExternalDepsImport,
-          COMMON_CHUNK_NAME.InternalDepsImport,
-          COMMON_CHUNK_NAME.FileVarDefine,
-          COMMON_CHUNK_NAME.FileUtilDefine,
-          COMMON_CHUNK_NAME.FileMainContent,
-        ],
-      });
-    }
+        const getLocale = () => locale;
 
+        const setLocale = (target) => {
+          locale = target;
+        };
+
+        const i18nFormat = ({ id, defaultMessage }, variables) => {
+          const msg = i18nConfig && i18nConfig[locale] && i18nConfig[locale][id] || defaultMessage;
+          if (msg == null) {
+            console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+            return \`\${id}\`;
+          }
+
+          if (!variables || !variables.length) {
+            return msg;
+          }
+
+          return new IntlMessageFormat(msg, locale).format(variables);
+        }
+
+        const i18n = id => {
+          return i18nFormat({ id });
+        };
+      `,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+      ],
+    });
+
+    next.chunks.push({
+      type: ChunkType.STRING,
+      fileType: FileType.JS,
+      name: COMMON_CHUNK_NAME.FileExport,
+      content: `
+        export {
+          getLocale,
+          setLocale,
+          i18n,
+          i18nFormat,
+        };
+      `,
+      linkAfter: [
+        COMMON_CHUNK_NAME.ExternalDepsImport,
+        COMMON_CHUNK_NAME.InternalDepsImport,
+        COMMON_CHUNK_NAME.ImportAliasDefine,
+        COMMON_CHUNK_NAME.FileVarDefine,
+        COMMON_CHUNK_NAME.FileUtilDefine,
+        COMMON_CHUNK_NAME.FileMainContent,
+      ],
+    });
     return next;
   };
   return plugin;
diff --git a/packages/code-generator/src/plugins/project/utils.ts b/packages/code-generator/src/plugins/project/utils.ts
index 32e7c5d17..5cdb21e81 100644
--- a/packages/code-generator/src/plugins/project/utils.ts
+++ b/packages/code-generator/src/plugins/project/utils.ts
@@ -28,24 +28,26 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
         linkAfter: [
           COMMON_CHUNK_NAME.ExternalDepsImport,
           COMMON_CHUNK_NAME.InternalDepsImport,
+          COMMON_CHUNK_NAME.ImportAliasDefine,
           COMMON_CHUNK_NAME.FileVarDefine,
           COMMON_CHUNK_NAME.FileUtilDefine,
           COMMON_CHUNK_NAME.FileMainContent,
         ],
       });
 
-      ir.utils.forEach(util => {
+      ir.utils.forEach((util) => {
         if (util.type === 'function') {
           next.chunks.push({
             type: ChunkType.STRING,
             fileType: FileType.JS,
             name: COMMON_CHUNK_NAME.FileVarDefine,
             content: `
-              const ${util.name} = ${util.content};
+              const ${util.name} = ${util.content.value};
             `,
             linkAfter: [
               COMMON_CHUNK_NAME.ExternalDepsImport,
               COMMON_CHUNK_NAME.InternalDepsImport,
+              COMMON_CHUNK_NAME.ImportAliasDefine,
             ],
           });
         }
@@ -54,12 +56,11 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
           type: ChunkType.STRING,
           fileType: FileType.JS,
           name: COMMON_CHUNK_NAME.FileExport,
-          content: `
-            ${util.name},
-          `,
+          content: `${util.name},`,
           linkAfter: [
             COMMON_CHUNK_NAME.ExternalDepsImport,
             COMMON_CHUNK_NAME.InternalDepsImport,
+            COMMON_CHUNK_NAME.ImportAliasDefine,
             COMMON_CHUNK_NAME.FileVarDefine,
             COMMON_CHUNK_NAME.FileUtilDefine,
             COMMON_CHUNK_NAME.FileMainContent,
@@ -77,6 +78,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
         linkAfter: [
           COMMON_CHUNK_NAME.ExternalDepsImport,
           COMMON_CHUNK_NAME.InternalDepsImport,
+          COMMON_CHUNK_NAME.ImportAliasDefine,
           COMMON_CHUNK_NAME.FileVarDefine,
           COMMON_CHUNK_NAME.FileUtilDefine,
           COMMON_CHUNK_NAME.FileMainContent,
diff --git a/packages/code-generator/src/postprocessor/prettier/index.ts b/packages/code-generator/src/postprocessor/prettier/index.ts
index 082a3d022..6cdd63d20 100644
--- a/packages/code-generator/src/postprocessor/prettier/index.ts
+++ b/packages/code-generator/src/postprocessor/prettier/index.ts
@@ -21,6 +21,8 @@ const factory: PostProcessorFactory<ProcessorConfig> = (config?: ProcessorConfig
       parser = 'babel';
     } else if (fileType === 'ts' || fileType === 'tsx') {
       parser = 'typescript';
+    } else if (fileType === 'json') {
+      parser = 'json';
     } else if (PARSERS.indexOf(fileType) >= 0) {
       parser = fileType as prettier.BuiltInParserName;
     } else if (cfg.customFileTypeParser[fileType]) {
diff --git a/packages/code-generator/src/publisher/disk/index.ts b/packages/code-generator/src/publisher/disk/index.ts
index bc12ed96f..189dff7e3 100644
--- a/packages/code-generator/src/publisher/disk/index.ts
+++ b/packages/code-generator/src/publisher/disk/index.ts
@@ -1,16 +1,14 @@
-import {
-  IResultDir,
-  PublisherFactory,
-  IPublisher,
-  IPublisherFactoryParams,
-  PublisherError,
-} from '../../types';
-import { writeFolder } from './utils';
+import * as defaultFs from 'fs';
+
+import { ResultDir } from '@ali/lowcode-types';
+import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
+import { writeFolder, IFileSystem } from './utils';
 
 export interface IDiskFactoryParams extends IPublisherFactoryParams {
   outputPath?: string;
   projectSlug?: string;
   createProjectFolder?: boolean;
+  fs?: IFileSystem;
 }
 
 export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
@@ -18,19 +16,19 @@ export interface IDiskPublisher extends IPublisher<IDiskFactoryParams, string> {
   setOutputPath: (path: string) => void;
 }
 
-export const createDiskPublisher: PublisherFactory<
-IDiskFactoryParams,
-IDiskPublisher
-> = (params: IDiskFactoryParams = {}): IDiskPublisher => {
+export const createDiskPublisher: PublisherFactory<IDiskFactoryParams, IDiskPublisher> = (
+  params: IDiskFactoryParams = {},
+): IDiskPublisher => {
   let { project, outputPath = './' } = params;
+  const { fs = defaultFs } = params;
 
-  const getProject = (): IResultDir => {
+  const getProject = (): ResultDir => {
     if (!project) {
       throw new PublisherError('Missing Project');
     }
     return project;
   };
-  const setProject = (projectToSet: IResultDir): void => {
+  const setProject = (projectToSet: ResultDir): void => {
     project = projectToSet;
   };
 
@@ -49,19 +47,14 @@ IDiskPublisher
 
     const projectOutputPath = options.outputPath || outputPath;
     const overrideProjectSlug = options.projectSlug || params.projectSlug;
-    const createProjectFolder =
-      options.createProjectFolder || params.createProjectFolder;
+    const createProjectFolder = options.createProjectFolder || params.createProjectFolder;
 
     if (overrideProjectSlug) {
       projectToPublish.name = overrideProjectSlug;
     }
 
     try {
-      await writeFolder(
-        projectToPublish,
-        projectOutputPath,
-        createProjectFolder,
-      );
+      await writeFolder(projectToPublish, projectOutputPath, createProjectFolder, fs);
       return { success: true, payload: projectOutputPath };
     } catch (error) {
       throw new PublisherError(error);
diff --git a/packages/code-generator/src/publisher/disk/utils.ts b/packages/code-generator/src/publisher/disk/utils.ts
index b07cb83c9..2f12d1bdf 100644
--- a/packages/code-generator/src/publisher/disk/utils.ts
+++ b/packages/code-generator/src/publisher/disk/utils.ts
@@ -1,58 +1,53 @@
-import { existsSync, mkdir, writeFile } from 'fs';
+import * as systemFs from 'fs';
 import { join } from 'path';
+import { ResultDir, ResultFile } from '@ali/lowcode-types';
 
-import { IResultDir, IResultFile } from '../../types';
+export interface IFileSystem {
+  existsSync: typeof systemFs.existsSync;
+  mkdir: typeof systemFs.mkdir;
+  writeFile: typeof systemFs.writeFile;
+}
 
 export const writeFolder = async (
-  folder: IResultDir,
+  folder: ResultDir,
   currentPath: string,
   createProjectFolder = true,
+  fs: IFileSystem = systemFs,
 ): Promise<void> => {
   const { name, files, dirs } = folder;
 
-  const folderPath = createProjectFolder
-    ? join(currentPath, name)
-    : currentPath;
+  const folderPath = createProjectFolder ? join(currentPath, name) : currentPath;
 
-  if (!existsSync(folderPath)) {
-    await createDirectory(folderPath);
+  if (!fs.existsSync(folderPath)) {
+    await createDirectory(folderPath, fs);
   }
 
-  const promises = [
-    writeFilesToFolder(folderPath, files),
-    writeSubFoldersToFolder(folderPath, dirs),
-  ];
+  const promises = [writeFilesToFolder(folderPath, files, fs), writeSubFoldersToFolder(folderPath, dirs, fs)];
 
   await Promise.all(promises);
 };
 
-const writeFilesToFolder = async (
-  folderPath: string,
-  files: IResultFile[],
-): Promise<void> => {
-  const promises = files.map(file => {
+const writeFilesToFolder = async (folderPath: string, files: ResultFile[], fs: IFileSystem): Promise<void> => {
+  const promises = files.map((file) => {
     const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
     const filePath = join(folderPath, fileName);
-    return writeContentToFile(filePath, file.content);
+    return writeContentToFile(filePath, file.content, 'utf8', fs);
   });
 
   await Promise.all(promises);
 };
 
-const writeSubFoldersToFolder = async (
-  folderPath: string,
-  subFolders: IResultDir[],
-): Promise<void> => {
-  const promises = subFolders.map(subFolder => {
+const writeSubFoldersToFolder = async (folderPath: string, subFolders: ResultDir[]): Promise<void> => {
+  const promises = subFolders.map((subFolder) => {
     return writeFolder(subFolder, folderPath);
   });
 
   await Promise.all(promises);
 };
 
-const createDirectory = (pathToDir: string): Promise<void> => {
+const createDirectory = (pathToDir: string, fs: IFileSystem): Promise<void> => {
   return new Promise((resolve, reject) => {
-    mkdir(pathToDir, { recursive: true }, err => {
+    fs.mkdir(pathToDir, { recursive: true }, (err) => {
       err ? reject(err) : resolve();
     });
   });
@@ -62,9 +57,10 @@ const writeContentToFile = (
   filePath: string,
   fileContent: string,
   encoding = 'utf8',
+  fs: IFileSystem,
 ): Promise<void> => {
   return new Promise((resolve, reject) => {
-    writeFile(filePath, fileContent, encoding, err => {
+    fs.writeFile(filePath, fileContent, encoding, (err) => {
       err ? reject(err) : resolve();
     });
   });
diff --git a/packages/code-generator/src/publisher/zip/index.ts b/packages/code-generator/src/publisher/zip/index.ts
index 9e2cbe36f..2048a54cf 100644
--- a/packages/code-generator/src/publisher/zip/index.ts
+++ b/packages/code-generator/src/publisher/zip/index.ts
@@ -1,10 +1,5 @@
-import {
-  IResultDir,
-  PublisherFactory,
-  IPublisher,
-  IPublisherFactoryParams,
-  PublisherError,
-} from '../../types';
+import { ResultDir } from '@ali/lowcode-types';
+import { PublisherFactory, IPublisher, IPublisherFactoryParams, PublisherError } from '../../types';
 import { isNodeProcess, writeZipToDisk, generateProjectZip } from './utils';
 
 // export type ZipBuffer = Buffer | Blob;
@@ -28,7 +23,7 @@ export const createZipPublisher: PublisherFactory<ZipFactoryParams, ZipPublisher
   let { project, outputPath } = params;
 
   const getProject = () => project;
-  const setProject = (projectToSet: IResultDir) => {
+  const setProject = (projectToSet: ResultDir) => {
     project = projectToSet;
   };
 
diff --git a/packages/code-generator/src/publisher/zip/utils.ts b/packages/code-generator/src/publisher/zip/utils.ts
index 54777bb4d..e34bf12c1 100644
--- a/packages/code-generator/src/publisher/zip/utils.ts
+++ b/packages/code-generator/src/publisher/zip/utils.ts
@@ -1,21 +1,17 @@
 import JSZip from 'jszip';
-import { IResultDir, IResultFile } from '../../types';
+import { ResultDir, ResultFile } from '@ali/lowcode-types';
 import { ZipBuffer } from './index';
 
 export const isNodeProcess = (): boolean => {
   return (
-    typeof process === 'object' &&
-    typeof process.versions === 'object' &&
-    typeof process.versions.node !== 'undefined'
+    typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node !== 'undefined'
   );
 };
 
-export const writeZipToDisk = (
-  zipFolderPath: string,
-  content: ZipBuffer,
-  zipName: string,
-): void => {
+export const writeZipToDisk = (zipFolderPath: string, content: ZipBuffer, zipName: string): void => {
+  // eslint-disable-next-line @typescript-eslint/no-var-requires
   const fs = require('fs');
+  // eslint-disable-next-line @typescript-eslint/no-var-requires
   const path = require('path');
 
   if (!fs.existsSync(zipFolderPath)) {
@@ -29,7 +25,7 @@ export const writeZipToDisk = (
   writeStream.end();
 };
 
-export const generateProjectZip = async (project: IResultDir): Promise<ZipBuffer> => {
+export const generateProjectZip = async (project: ResultDir): Promise<ZipBuffer> => {
   let zip = new JSZip();
   zip = writeFolderToZip(project, zip, true);
   // const zipType = isNodeProcess() ? 'nodebuffer' : 'blob';
@@ -37,21 +33,17 @@ export const generateProjectZip = async (project: IResultDir): Promise<ZipBuffer
   return zip.generateAsync({ type: zipType });
 };
 
-const writeFolderToZip = (
-  folder: IResultDir,
-  parentFolder: JSZip,
-  ignoreFolder = false,
-) => {
+const writeFolderToZip = (folder: ResultDir, parentFolder: JSZip, ignoreFolder = false) => {
   const zipFolder = ignoreFolder ? parentFolder : parentFolder.folder(folder.name);
   if (zipFolder !== null) {
-    folder.files.forEach((file: IResultFile) => {
+    folder.files.forEach((file: ResultFile) => {
       // const options = file.contentEncoding === 'base64' ? { base64: true } : {};
       const options = {};
       const fileName = file.ext ? `${file.name}.${file.ext}` : file.name;
       zipFolder.file(fileName, file.content, options);
     });
 
-    folder.dirs.forEach((subFolder: IResultDir) => {
+    folder.dirs.forEach((subFolder: ResultDir) => {
       writeFolderToZip(subFolder, zipFolder);
     });
   }
diff --git a/packages/code-generator/src/solutions/rax-app.ts b/packages/code-generator/src/solutions/rax-app.ts
new file mode 100644
index 000000000..c61eae0d4
--- /dev/null
+++ b/packages/code-generator/src/solutions/rax-app.ts
@@ -0,0 +1,66 @@
+import { IProjectBuilder } from '../types';
+
+import { createProjectBuilder } from '../generator/ProjectBuilder';
+
+import esModule from '../plugins/common/esmodule';
+import containerClass from '../plugins/component/rax/containerClass';
+import containerLifeCycles from '../plugins/component/rax/containerLifeCycle';
+import containerMethods from '../plugins/component/rax/containerMethods';
+import containerInitState from '../plugins/component/rax/containerInitState';
+import containerInjectContext from '../plugins/component/rax/containerInjectContext';
+import containerInjectDataSourceEngine from '../plugins/component/rax/containerInjectDataSourceEngine';
+import containerInjectUtils from '../plugins/component/rax/containerInjectUtils';
+import jsx from '../plugins/component/rax/jsx';
+import commonDeps from '../plugins/component/rax/commonDeps';
+import css from '../plugins/component/style/css';
+import constants from '../plugins/project/constants';
+import i18n from '../plugins/project/i18n';
+import utils from '../plugins/project/utils';
+
+import raxApp from '../plugins/project/framework/rax';
+
+import { prettier } from '../postprocessor';
+
+export default function createIceJsProjectBuilder(): IProjectBuilder {
+  return createProjectBuilder({
+    template: raxApp.template,
+    plugins: {
+      components: [
+        commonDeps(),
+        esModule({ fileType: 'jsx', useAliasName: false }),
+        containerClass(),
+        containerInitState(),
+        containerMethods(),
+        containerInjectContext(),
+        containerInjectDataSourceEngine(),
+        containerInjectUtils(),
+        containerLifeCycles(),
+        jsx(),
+        css(),
+      ],
+      pages: [
+        commonDeps(),
+        esModule({ fileType: 'jsx' }),
+        containerClass(),
+        containerInitState(),
+        containerMethods(),
+        containerInjectContext(),
+        containerInjectDataSourceEngine(),
+        containerInjectUtils(),
+        containerLifeCycles(),
+        jsx(),
+        css(),
+      ],
+      appConfig: [raxApp.plugins.appConfig()],
+      buildConfig: [raxApp.plugins.buildConfig()],
+      entry: [raxApp.plugins.entry()],
+      constants: [constants()],
+      utils: [esModule(), utils()],
+      i18n: [i18n()],
+      globalStyle: [raxApp.plugins.globalStyle()],
+      htmlEntry: [raxApp.plugins.entryDocument()],
+      packageJSON: [raxApp.plugins.packageJSON()],
+    },
+    postProcessors: process.env.NODE_ENV !== 'test' ? [prettier()] : [],
+  });
+}
diff --git a/packages/code-generator/src/types/core.ts b/packages/code-generator/src/types/core.ts
index c50d8cd61..8666f507e 100644
--- a/packages/code-generator/src/types/core.ts
+++ b/packages/code-generator/src/types/core.ts
@@ -1,16 +1,24 @@
 import {
-  IBasicSchema,
-  IParseResult,
-  IProjectSchema,
-  IResultDir,
-  IResultFile,
-  IComponentNodeItem,
-  IJSExpression,
-} from './index';
+  JSONArray,
+  JSONObject,
+  CompositeArray,
+  CompositeObject,
+  ResultDir,
+  ResultFile,
+  NodeDataType,
+  ProjectSchema,
+  JSExpression,
+  JSFunction,
+  JSSlot,
+} from '@ali/lowcode-types';
+
+import { IParseResult } from './intermediate';
+import { IScopeBindings } from '../utils/ScopeBindings';
 
 export enum FileType {
   CSS = 'css',
   SCSS = 'scss',
+  LESS = 'less',
   HTML = 'html',
   JS = 'js',
   JSX = 'jsx',
@@ -41,6 +49,7 @@ export interface ICodeChunk {
   subModule?: string;
   content: ChunkContent;
   linkAfter: string[];
+  ext?: Record<string, unknown>;
 }
 
 export interface IBaseCodeStruct {
@@ -69,13 +78,13 @@ export interface ICodeBuilder {
 }
 
 export interface ICompiledModule {
-  files: IResultFile[];
+  files: ResultFile[];
 }
 
 export interface IModuleBuilder {
   generateModule(input: unknown): Promise<ICompiledModule>;
-  generateModuleCode(schema: IBasicSchema | string): Promise<IResultDir>;
-  linkCodeChunks(chunks: Record<string, ICodeChunk[]>, fileName: string): IResultFile[];
+  generateModuleCode(schema: ProjectSchema | string): Promise<ResultDir>;
+  linkCodeChunks(chunks: Record<string, ICodeChunk[]>, fileName: string): ResultFile[];
   addPlugin(plugin: BuilderComponentPlugin): void;
 }
 
@@ -89,21 +98,21 @@ export interface ICodeGenerator {
   /**
    * 出码接口，把 Schema 转换成代码文件系统描述
    *
-   * @param {(IBasicSchema)} schema 传入的 Schema
-   * @returns {IResultDir}
+   * @param {(ProjectSchema)} schema 传入的 Schema
+   * @returns {ResultDir}
    * @memberof ICodeGenerator
    */
-  toCode(schema: IBasicSchema): Promise<IResultDir>;
+  toCode(schema: ProjectSchema): Promise<ResultDir>;
 }
 
 export interface ISchemaParser {
-  validate(schema: IBasicSchema): boolean;
-  parse(schema: IBasicSchema | string): IParseResult;
+  validate(schema: ProjectSchema): boolean;
+  parse(schema: ProjectSchema | string): IParseResult;
 }
 
 export interface IProjectTemplate {
   slots: Record<string, IProjectSlot>;
-  generateTemplate(): IResultDir;
+  generateTemplate(): ResultDir;
 }
 
 export interface IProjectSlot {
@@ -111,25 +120,12 @@ export interface IProjectSlot {
   fileName?: string;
 }
 
-// export interface IProjectSlots {
-//   components: IProjectSlot;
-//   pages: IProjectSlot;
-//   router: IProjectSlot;
-//   entry: IProjectSlot;
-//   constants?: IProjectSlot;
-//   utils?: IProjectSlot;
-//   i18n?: IProjectSlot;
-//   globalStyle: IProjectSlot;
-//   htmlEntry: IProjectSlot;
-//   packageJSON: IProjectSlot;
-// }
-
 export interface IProjectPlugins {
   [slotName: string]: BuilderComponentPlugin[];
 }
 
 export interface IProjectBuilder {
-  generateProject(schema: IProjectSchema | string): Promise<IResultDir>;
+  generateProject(schema: ProjectSchema | string): Promise<ResultDir>;
 }
 
 export type PostProcessorFactory<T> = (config?: T) => PostProcessor;
@@ -140,62 +136,35 @@ export interface IPluginOptions {
   fileDirDepth: number;
 }
 
-export enum PIECE_TYPE {
-  BEFORE = 'NodeCodePieceBefore',
-  TAG = 'NodeCodePieceTag',
-  ATTR = 'NodeCodePieceAttr',
-  CHILDREN = 'NodeCodePieceChildren',
-  AFTER = 'NodeCodePieceAfter',
-}
+export type BaseGenerator<I, T, C> = (input: I, scope: IScope, config?: C, next?: BaseGenerator<I, T, C>) => T;
+type CompositeTypeGenerator<I, T> =
+  | BaseGenerator<I, T, CompositeValueGeneratorOptions>
+  | Array<BaseGenerator<I, T, CompositeValueGeneratorOptions>>;
 
-export interface CodePiece {
-  value: string;
-  type: PIECE_TYPE;
-}
+export type NodeGenerator<T> = (nodeItem: NodeDataType, scope: IScope) => T;
 
+// FIXME: 在新的实现中，添加了第一参数 this: CustomHandlerSet 作为上下文。究其本质
+// scopeBindings?: IScopeBindings;
+// 这个组合只用来用来处理 CompositeValue 类型，不是这个类型的不要放在这里
 export interface HandlerSet<T> {
-  string?: (input: string) => T[];
-  expression?: (input: IJSExpression) => T[];
-  node?: (input: IComponentNodeItem) => T[];
-  common?: (input: unknown) => T[];
+  string?: CompositeTypeGenerator<string, T>;
+  boolean?: CompositeTypeGenerator<boolean, T>;
+  number?: CompositeTypeGenerator<number, T>;
+  expression?: CompositeTypeGenerator<JSExpression, T>;
+  function?: CompositeTypeGenerator<JSFunction, T>;
+  slot?: CompositeTypeGenerator<JSSlot, T>;
+  array?: CompositeTypeGenerator<JSONArray | CompositeArray, T>;
+  object?: CompositeTypeGenerator<JSONObject | CompositeObject, T>;
 }
 
-export type ExtGeneratorPlugin = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem) => CodePiece[];
+export type CompositeValueGeneratorOptions = {
+  handlers?: HandlerSet<string>;
+  nodeGenerator?: NodeGenerator<string>;
+};
 
-export interface INodeGeneratorConfig {
-  nodeTypeMapping?: Record<string, string>;
-}
-
-export type NodeGenerator = (nodeItem: IComponentNodeItem) => string;
-
-export interface INodeGeneratorContext {
-  generator: NodeGenerator;
-}
-
-// export interface InteratorScope {
-//   [$item: string]: string;           // $item 默认取值 "item"
-//   [$index: string]: string | number; // $index 默认取值 "index"
-//   __proto__: BlockInstance;
-// }
-
-export type CompositeValueCustomHandler = (data: unknown) => string;
-export type CompositeTypeContainerHandler = (value: string) => string;
-export interface CompositeValueCustomHandlerSet {
-  boolean?: CompositeValueCustomHandler;
-  number?: CompositeValueCustomHandler;
-  string?: CompositeValueCustomHandler;
-  array?: CompositeValueCustomHandler;
-  object?: CompositeValueCustomHandler;
-  expression?: CompositeValueCustomHandler;
-}
-
-export interface CompositeTypeContainerHandlerSet {
-  default?: CompositeTypeContainerHandler;
-  string?: CompositeValueCustomHandler;
-}
-
-export interface CompositeValueGeneratorOptions {
-  handlers?: CompositeValueCustomHandlerSet;
-  containerHandlers?: CompositeTypeContainerHandlerSet;
-  nodeGenerator?: NodeGenerator;
+export interface IScope {
+  // 作用域内定义
+  bindings?: IScopeBindings;
+  // TODO: 需要有上下文信息吗？ 描述什么内容
+  createSubScope: (ownIndentifiers: string[]) => IScope;
 }
diff --git a/packages/code-generator/src/types/deps.ts b/packages/code-generator/src/types/deps.ts
index 02be05592..cb2fb5eac 100644
--- a/packages/code-generator/src/types/deps.ts
+++ b/packages/code-generator/src/types/deps.ts
@@ -34,5 +34,5 @@ export interface IDependency {
   subName?: string; // 下标子组件名称
   main?: string; // 包导出组件入口文件路径 /lib/input
   dependencyType?: DependencyType; // 依赖类型 内/外
-  importName?: string; // 导入后名称
+  componentName?: string; // 导入后名称
 }
diff --git a/packages/code-generator/src/types/error.ts b/packages/code-generator/src/types/error.ts
index 8c0393a88..ff3208c87 100644
--- a/packages/code-generator/src/types/error.ts
+++ b/packages/code-generator/src/types/error.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-useless-constructor */
 export class CodeGeneratorError extends Error {
   constructor(message: string) {
     super(message);
@@ -5,23 +6,11 @@ export class CodeGeneratorError extends Error {
   }
 }
 
-// tslint:disable-next-line: max-classes-per-file
 export class ComponentValidationError extends CodeGeneratorError {
-  constructor(errorString: string) {
-    super(errorString);
-  }
 }
 
-// tslint:disable-next-line: max-classes-per-file
 export class CompatibilityError extends CodeGeneratorError {
-  constructor(errorString: string) {
-    super(errorString);
-  }
 }
 
-// tslint:disable-next-line: max-classes-per-file
 export class PublisherError extends CodeGeneratorError {
-  constructor(errorString: string) {
-    super(errorString);
-  }
 }
diff --git a/packages/code-generator/src/types/index.ts b/packages/code-generator/src/types/index.ts
index 102515d43..92ca81924 100644
--- a/packages/code-generator/src/types/index.ts
+++ b/packages/code-generator/src/types/index.ts
@@ -1,7 +1,6 @@
 export * from './core';
 export * from './deps';
 export * from './error';
-export * from './result';
-export * from './schema';
 export * from './intermediate';
 export * from './publisher';
+export * from './jsx';
diff --git a/packages/code-generator/src/types/intermediate.ts b/packages/code-generator/src/types/intermediate.ts
index 317ef7843..11e6cc7b3 100644
--- a/packages/code-generator/src/types/intermediate.ts
+++ b/packages/code-generator/src/types/intermediate.ts
@@ -1,49 +1,51 @@
-import {
-  IAppConfig,
-  IAppMeta,
-  IContainerNodeItem,
-  IDependency,
-  II18nMap,
-  IInternalDependency,
-  INpmPackage,
-  IUtilItem,
-} from './index';
+import { I18nMap, UtilsMap, ContainerSchema, JSONObject } from '@ali/lowcode-types';
+
+import { IDependency, INpmPackage } from './deps';
 
 export interface IParseResult {
   containers: IContainerInfo[];
   globalUtils?: IUtilInfo;
-  globalI18n?: II18nMap;
+  globalI18n?: I18nMap;
   globalRouter?: IRouterInfo;
   project?: IProjectInfo;
 }
 
-export interface IContainerInfo extends IContainerNodeItem, IWithDependency {
-  containerType: string;
-  moduleName: string;
-}
-
 export interface IWithDependency {
   deps?: IDependency[];
 }
 
+export interface IContainerInfo extends ContainerSchema, IWithDependency {
+  containerType: string;
+  moduleName: string;
+}
+
 export interface IUtilInfo extends IWithDependency {
-  utils: IUtilItem[];
+  utils: UtilsMap;
 }
 
 export interface IRouterInfo extends IWithDependency {
   routes: Array<{
     path: string;
+    fileName: string;
     componentName: string;
   }>;
 }
 
 export interface IProjectInfo {
-  config: IAppConfig;
-  meta: IAppMeta;
   css?: string;
-  constants?: Record<string, string>;
-  i18n?: II18nMap;
+  containersDeps?: IDependency[];
+  utilsDeps?: IDependency[];
+  constants?: JSONObject;
+  i18n?: I18nMap;
   packages: INpmPackage[];
+  meta?: {
+    name?: string;
+    title?: string;
+  };
+}
+
+export interface IPageMeta {
+  router?: string;
 }
 
 /**
diff --git a/packages/code-generator/src/types/jsx.ts b/packages/code-generator/src/types/jsx.ts
new file mode 100644
index 000000000..6ec5c7fef
--- /dev/null
+++ b/packages/code-generator/src/types/jsx.ts
@@ -0,0 +1,29 @@
+import { NodeSchema, CompositeValue } from '@ali/lowcode-types';
+import { HandlerSet, BaseGenerator, NodeGenerator } from './core';
+
+export enum PIECE_TYPE {
+  BEFORE = 'NodeCodePieceBefore',
+  TAG = 'NodeCodePieceTag',
+  ATTR = 'NodeCodePieceAttr',
+  CHILDREN = 'NodeCodePieceChildren',
+  AFTER = 'NodeCodePieceAfter',
+}
+
+export interface CodePiece {
+  name?: string;
+  value: string;
+  type: PIECE_TYPE;
+}
+
+export type AttrData = { attrName: string; attrValue: CompositeValue };
+// 对 JSX 出码的理解，目前定制点包含 【包装】【标签名】【属性】
+export type AttrPlugin = BaseGenerator<AttrData, CodePiece[], NodeGeneratorConfig>;
+export type NodePlugin = BaseGenerator<NodeSchema, CodePiece[], NodeGeneratorConfig>;
+
+export type NodeGeneratorConfig = {
+  handlers?: HandlerSet<string>;
+  tagMapping?: (input: string) => string;
+  attrPlugins?: AttrPlugin[];
+  nodePlugins?: NodePlugin[];
+  self?: NodeGenerator<string>;
+};
diff --git a/packages/code-generator/src/types/publisher.ts b/packages/code-generator/src/types/publisher.ts
index a632e4d9b..53e4df9fd 100644
--- a/packages/code-generator/src/types/publisher.ts
+++ b/packages/code-generator/src/types/publisher.ts
@@ -1,17 +1,15 @@
-import {
-  IResultDir,
-} from './index';
+import { ResultDir } from '@ali/lowcode-types';
 
 export type PublisherFactory<T, U> = (configuration?: Partial<T>) => U;
 
 export interface IPublisher<T, U> {
   publish: (options?: T) => Promise<IPublisherResponse<U>>;
-  getProject: () => IResultDir | void;
-  setProject: (project: IResultDir) => void;
+  getProject: () => ResultDir | void;
+  setProject: (project: ResultDir) => void;
 }
 
 export interface IPublisherFactoryParams {
-  project?: IResultDir;
+  project?: ResultDir;
 }
 export interface IPublisherResponse<T> {
   success: boolean;
diff --git a/packages/code-generator/src/types/result.ts b/packages/code-generator/src/types/result.ts
deleted file mode 100644
index 75ed7bb1a..000000000
--- a/packages/code-generator/src/types/result.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * 导出内容结构，文件夹
- *
- * @export
- * @interface IResultDir
- */
-export interface IResultDir {
-  /**
-   * 文件夹名称，Root 名称默认为 .
-   *
-   * @type {string}
-   * @memberof IResultDir
-   */
-  name: string;
-  /**
-   * 子目录
-   *
-   * @type {IResultDir[]}
-   * @memberof IResultDir
-   */
-  dirs: IResultDir[];
-  /**
-   * 文件夹内文件
-   *
-   * @type {IResultFile[]}
-   * @memberof IResultDir
-   */
-  files: IResultFile[];
-  /**
-   * 添加文件
-   *
-   * @param {IResultFile} file
-   * @memberof IResultDir
-   */
-  addFile(file: IResultFile): void;
-  /**
-   * 添加子目录
-   *
-   * @param {IResultDir} dir
-   * @memberof IResultDir
-   */
-  addDirectory(dir: IResultDir): void;
-}
-
-/**
- * 导出内容，对文件的描述
- *
- * @export
- * @interface IResultFile
- */
-export interface IResultFile {
-  /**
-   * 文件名
-   *
-   * @type {string}
-   * @memberof IResultFile
-   */
-  name: string;
-  /**
-   * 文件类型扩展名，例如 .js .less
-   *
-   * @type {string}
-   * @memberof IResultFile
-   */
-  ext: string;
-  /**
-   * 文件内容
-   *
-   * @type {string}
-   * @memberof IResultFile
-   */
-  content: string;
-}
-
-export interface IPackageJSON {
-  name: string;
-  version: string;
-  description?: string;
-  dependencies: Record<string, string>;
-  devDependencies: Record<string, string>;
-  scripts?: Record<string, string>;
-  engines?: Record<string, string>;
-  repository?: {
-    type: string;
-    url: string;
-  };
-  private?: boolean;
-}
diff --git a/packages/code-generator/src/types/schema.ts b/packages/code-generator/src/types/schema.ts
deleted file mode 100644
index e102c54cd..000000000
--- a/packages/code-generator/src/types/schema.ts
+++ /dev/null
@@ -1,241 +0,0 @@
-// 搭建基础协议、搭建入料协议的数据规范
-import { IExternalDependency } from './index';
-
-/**
- * 搭建基础协议 - 函数表达式
- *
- * @export
- * @interface IJSExpression
- */
-export interface IJSExpression {
-  type: 'JSExpression';
-  value: string;
-  [extConfigName: string]: any;
-}
-
-/**
- * 搭建基础协议 - 函数定义
- *
- * @export
- * @interface IJSFunction
- */
-export interface IJSFunction {
-  type: 'JSFunction';
-  value: string;
-  [extConfigName: string]: any;
-}
-
-/**
- * 搭建基础协议 - 函数定义
- *
- * @export
- * @interface IJSSlot
- */
-export interface IJSSlot {
-  type: 'JSSlot';
-  value: IComponentNodeItem[];
-  params?: string[];
-  [extConfigName: string]: any;
-}
-
-// JSON 基本类型
-export interface IJSONObject {
-  [key: string]: JSONValue;
-}
-
-export type JSONValue = boolean | string | number | null | JSONArray | IJSONObject;
-export type JSONArray = JSONValue[];
-
-export type CompositeArray = CompositeValue[];
-export interface ICompositeObject {
-  [key: string]: CompositeValue;
-}
-
-// 复合类型
-export type CompositeValue = JSONValue | IJSExpression | IJSFunction | IJSSlot | CompositeArray | ICompositeObject;
-
-/**
- * 搭建基础协议 - 多语言描述
- *
- * @export
- * @interface II18nMap
- */
-export interface II18nMap {
-  [lang: string]: {
-    [key: string]: string;
-  };
-}
-
-/**
- * 搭建基础协议
- *
- * @export
- * @interface IBasicSchema
- */
-export interface IBasicSchema {
-  version: string; // 当前协议版本号
-  componentsMap: IComponentsMapItem[]; // 组件映射关系
-  componentsTree: Array<IContainerNodeItem | IComponentNodeItem>; // 描述模版/页面/区块/低代码业务组件的组件树 低代码业务组件树描述，固定长度为1，且顶层为低代码业务组件容器描述
-  utils?: IUtilItem[]; // 工具类扩展映射关系 低代码业务组件不包含
-  i18n?: II18nMap; // 国际化语料
-}
-
-export interface IProjectSchema extends IBasicSchema {
-  constants: Record<string, string>; // 应用范围内的全局常量；
-  css: string; // 应用范围内的全局样式；
-  config: IAppConfig; // 当前应用配置信息
-  meta: IAppMeta; // 当前应用元数据信息
-}
-
-/**
- * 搭建基础协议 - 单个组件描述
- *
- * @export
- * @interface IComponentsMapItem
- */
-export interface IComponentsMapItem extends IExternalDependency {
-  componentName: string; // 组件名称
-}
-
-export interface IUtilItem {
-  name: string;
-  type: 'npm' | 'tnpm' | 'function';
-  content: IExternalDependency | IJSExpression;
-}
-
-export type ChildNodeItem = string | IJSExpression | IComponentNodeItem;
-export type ChildNodeType = ChildNodeItem | ChildNodeItem[];
-
-/**
- * 搭建基础协议 - 单个组件树节点描述
- * 转换成一个 .jsx 文件内 React Class 类 render 函数返回的 jsx 代码
- *
- * @export
- * @interface IComponentNodeItem
- */
-export interface IComponentNodeItem {
-  // TODO: 不需要 id 字段，暂时简单兼容
-  id?: string;
-  componentName: string; // 组件名称 必填、首字母大写
-  props: {
-    [propName: string]: CompositeValue; // 业务属性
-  }; // 组件属性对象
-  condition?: CompositeValue; // 渲染条件
-  loop?: CompositeValue; // 循环数据
-  loopArgs?: [string, string]; // 循环迭代对象、索引名称 ["item", "index"]
-  children?: ChildNodeType; // 子节点
-}
-
-/**
- * 搭建基础协议 - 单个容器节点描述
- *
- * @export
- * @interface IContainerNodeItem
- * @extends {IComponentNodeItem}
- */
-export interface IContainerNodeItem extends IComponentNodeItem {
-  componentName: 'Page' | 'Block' | 'Component'; // 'Page' | 'Block' | 'Component'  组件类型 必填、首字母大写
-  fileName: string; // 文件名称 必填、英文
-  state?: {
-    [stateName: string]: CompositeValue; // 容器初始数据
-  };
-  css?: string; // 样式文件 用于描述容器组件内部节点的样式，对应生成一个独立的样式文件，在对应容器组件生成的 .jsx 文件中 import 引入；
-  /**
-   * LifeCycle
-   * • constructor(props, context)
-   * • 说明：初始化渲染时执行，常用于设置state值；
-   * • render()
-   * • 说明：执行于容器组件React Class的render方法最前，常用于计算变量挂载到this对象上，供props上属性绑定。此render()方法不需要设置return返回值。
-   * • componentDidMount()
-   * • componentDidUpdate(prevProps, prevState, snapshot)
-   * • componentWillUnmount()
-   * • componentDidCatch(error, info)
-   */
-  lifeCycles?: Record<string, IJSExpression | IJSFunction>; // 生命周期Hook方法
-  methods?: Record<string, IJSExpression | IJSFunction>; // 自定义方法设置
-  dataSource?: {
-    list: IDataSourceConfig[];
-  }; // 异步数据源配置
-  meta?: IBasicMeta | IPageMeta;
-}
-
-/**
- * 搭建基础协议 - 数据源单个配置
- *
- * @export
- * @interface IDataSourceConfig
- */
-export interface IDataSourceConfig {
-  id: string; // 数据请求ID标识
-  isInit: boolean; // 是否为初始数据 支持表达式 值为true时，将在组件初始化渲染时自动发送当前数据请求
-  type: string; // 数据请求类型 'fetch' | 'mtop' | 'jsonp' | 'custom'
-  requestHandler?: IJSExpression | IJSFunction; // 自定义扩展的外部请求处理器 仅type='custom'时生效
-  options?: IFetchOptions; // 请求参数配置 每种请求类型对应不同参数
-  dataHandler?: IJSExpression | IJSFunction; // 数据结果处理函数，形如：(data, err) => Object
-}
-
-/**
- * 搭建基础协议 - 请求参数配置
- *
- * @export
- * @interface IFetchOptions
- */
-export interface IFetchOptions {
-  url: string; // 请求地址 支持表达式
-  params?: {
-    // 请求参数
-    [key: string]: any;
-  };
-  method: 'GET' | 'POST';
-  isCors?: boolean; // 是否支持跨域，对应credentials = 'include'
-  timeout?: number; // 超时时长
-  headers?: {
-    // 自定义请求头
-    [key: string]: string;
-  };
-  [extConfigName: string]: any;
-}
-
-export interface IBasicMeta {
-  title: string; // 标题描述
-}
-
-export interface IPageMeta extends IBasicMeta {
-  router: string; // 页面路由
-  spmb?: string; // spm
-}
-
-// "theme": {
-//   //for Fusion use dpl defined
-//   "package": "@alife/theme-fusion",
-//   "version": "^0.1.0",
-
-//   //for Antd use variable
-//   "primary": "#ff9966"
-// }
-
-// "layout": {
-//   "componentName": "BasicLayout",
-//   "props": {
-//     "logo": "...",
-//     "name": "测试网站"
-//   },
-// },
-
-export interface IAppConfig {
-  sdkVersion: string; // 渲染模块版本
-  historyMode: 'brower' | 'hash'; // 浏览器路由：brower  哈希路由：hash
-  targetRootID: string; // 渲染根节点 ID
-  layout: IComponentNodeItem;
-  theme: object; // 主题配置，根据接入的主题模块不同
-}
-
-export interface IAppMeta {
-  name: string; // 应用中文名称
-  git_group?: string; // 应用对应git分组名
-  project_name?: string; // 应用对应git的project名称
-  description?: string; // 应用描述
-  spma?: string; // 应用spma A位信息
-  creator?: string; // author
-  [otherAttrName: string]: any;
-}
diff --git a/packages/code-generator/src/utils/OrderedSet.ts b/packages/code-generator/src/utils/OrderedSet.ts
new file mode 100644
index 000000000..3c58ddc73
--- /dev/null
+++ b/packages/code-generator/src/utils/OrderedSet.ts
@@ -0,0 +1,33 @@
+export class OrderedSet<T> {
+  private _set = new Set<T>();
+  private _arr: T[] = [];
+
+  constructor(items?: T[]) {
+    if (items) {
+      this._set = new Set(items);
+      this._arr = items.slice(0);
+    }
+  }
+
+  add(item: T) {
+    if (!this._set.has(item)) {
+      this._set.add(item);
+      this._arr.push(item);
+    }
+  }
+
+  delete(item: T) {
+    if (this._set.has(item)) {
+      this._set.delete(item);
+      this._arr.splice(this._arr.indexOf(item), 1);
+    }
+  }
+
+  has(item: T) {
+    return this._set.has(item);
+  }
+
+  toArray() {
+    return this._arr.slice(0);
+  }
+}
diff --git a/packages/code-generator/src/utils/Scope.ts b/packages/code-generator/src/utils/Scope.ts
new file mode 100644
index 000000000..e8b7bf235
--- /dev/null
+++ b/packages/code-generator/src/utils/Scope.ts
@@ -0,0 +1,27 @@
+import { IScope } from '../types/core';
+import { IScopeBindings, ScopeBindings } from './ScopeBindings';
+
+class Scope implements IScope {
+  static createRootScope(): IScope {
+    return new Scope();
+  }
+
+  bindings?: IScopeBindings;
+
+  constructor() {
+    this.bindings = undefined;
+  }
+
+  createSubScope(ownIndentifiers: string[]): IScope {
+    const originalScopeBindings = this.bindings;
+    const newScopeBindings = new ScopeBindings(originalScopeBindings);
+    ownIndentifiers.forEach((identifier) => {
+      newScopeBindings.addBinding(identifier);
+    });
+    const newScope = new Scope();
+    newScope.bindings = newScopeBindings;
+    return newScope;
+  }
+}
+
+export default Scope;
diff --git a/packages/code-generator/src/utils/ScopeBindings.ts b/packages/code-generator/src/utils/ScopeBindings.ts
new file mode 100644
index 000000000..875f6c82e
--- /dev/null
+++ b/packages/code-generator/src/utils/ScopeBindings.ts
@@ -0,0 +1,56 @@
+import { OrderedSet } from './OrderedSet';
+
+export interface IScopeBindings {
+  readonly parent: IScopeBindings | null;
+
+  hasBinding(varName: string): boolean;
+  hasOwnBinding(varName: string): boolean;
+
+  addBinding(varName: string): void;
+  removeBinding(varName: string): void;
+
+  getAllBindings(): string[];
+  getAllOwnedBindings(): string[];
+}
+
+export class ScopeBindings implements IScopeBindings {
+  readonly parent: IScopeBindings | null;
+
+  private _bindings = new OrderedSet<string>();
+
+  constructor(p: IScopeBindings | null = null) {
+    this.parent = p;
+  }
+
+  hasBinding(varName: string): boolean {
+    return this._bindings.has(varName) || !!this.parent?.hasBinding(varName);
+  }
+
+  hasOwnBinding(varName: string): boolean {
+    return this._bindings.has(varName);
+  }
+
+  addBinding(varName: string): void {
+    this._bindings.add(varName);
+  }
+
+  removeBinding(varName: string): void {
+    this._bindings.delete(varName);
+  }
+
+  getAllBindings(): string[] {
+    const allBindings = new OrderedSet(this._bindings.toArray());
+
+    for (let parent = this.parent; parent; parent = parent?.parent) {
+      parent.getAllOwnedBindings().forEach((varName) => {
+        allBindings.add(varName);
+      });
+    }
+
+    return allBindings.toArray();
+  }
+
+  getAllOwnedBindings(): string[] {
+    return this._bindings.toArray();
+  }
+}
diff --git a/packages/code-generator/src/utils/aopHelper.ts b/packages/code-generator/src/utils/aopHelper.ts
new file mode 100644
index 000000000..2b380c648
--- /dev/null
+++ b/packages/code-generator/src/utils/aopHelper.ts
@@ -0,0 +1,28 @@
+import { BaseGenerator, IScope } from '../types/core';
+
+export function executeFunctionStack<I, T, C>(
+  input: I,
+  scope: IScope,
+  funcs: BaseGenerator<I, T, C> | Array<BaseGenerator<I, T, C>>,
+  baseFunc: BaseGenerator<I, T, C>,
+  config?: C,
+): T {
+  const funcList: Array<BaseGenerator<I, T, C>> = [];
+  if (Array.isArray(funcs)) {
+    funcList.push(...funcs);
+  } else {
+    funcList.push(funcs);
+  }
+
+  let next: BaseGenerator<I, T, C> = baseFunc;
+  while (funcList.length > 0) {
+    const func = funcList.pop();
+    if (func) {
+      const warppedFunc =
+        ((nextFunc) => (i: I, s: IScope, cfg?: C) => func(i, s, cfg, nextFunc))(next);
+      next = warppedFunc;
+    }
+  }
+
+  return next(input, scope, config);
+}
diff --git a/packages/code-generator/src/utils/common.ts b/packages/code-generator/src/utils/common.ts
index 5d4619cdb..fe05ce423 100644
--- a/packages/code-generator/src/utils/common.ts
+++ b/packages/code-generator/src/utils/common.ts
@@ -24,7 +24,9 @@ export function upperCaseFirst(inputValue: string): string {
 
 export function uniqueArray<T>(arr: T[], by: (i: T) => string) {
   const map: Record<string, T> = {};
-  arr.forEach((item) => (map[by(item)] = item));
+  arr.forEach((item) => {
+    map[by(item)] = item;
+  });
   const uniqueKeys = [...new Set<string>(Object.keys(map))];
   const uniqueItems = uniqueKeys.map((key) => map[key]);
   return uniqueItems;
diff --git a/packages/code-generator/src/utils/compositeType.ts b/packages/code-generator/src/utils/compositeType.ts
index edab55873..01b953fc3 100644
--- a/packages/code-generator/src/utils/compositeType.ts
+++ b/packages/code-generator/src/utils/compositeType.ts
@@ -1,45 +1,28 @@
 import {
   CompositeArray,
   CompositeValue,
-  ICompositeObject,
-  CompositeValueGeneratorOptions,
-  CompositeTypeContainerHandlerSet,
-  CodeGeneratorError,
-} from '../types';
-import { generateExpression, generateFunction, isJsExpression, isJsFunction } from './jsExpression';
-import { isJsSlot, generateJsSlot } from './jsSlot';
+  CompositeObject,
+  JSFunction,
+  isJSExpression,
+  isJSFunction,
+  isJSSlot,
+  JSSlot,
+} from '@ali/lowcode-types';
+import _ from 'lodash';
+
+import { IScope, CompositeValueGeneratorOptions, CodeGeneratorError } from '../types';
+import { generateExpression, generateFunction } from './jsExpression';
+import { generateJsSlot } from './jsSlot';
 import { isValidIdentifier } from './validate';
 import { camelize } from './common';
+import { executeFunctionStack } from './aopHelper';
 
-const defaultContainerHandlers: CompositeTypeContainerHandlerSet = {
-  default: (v) => v,
-  string: (v) => `'${v}'`,
-};
-
-function generateArray(value: CompositeArray, options: CompositeValueGeneratorOptions = {}): string {
-  const body = value.map((v) => generateUnknownType(v, options)).join(',');
+function generateArray(value: CompositeArray, scope: IScope, options: CompositeValueGeneratorOptions = {}): string {
+  const body = value.map((v) => generateUnknownType(v, scope, options)).join(',');
   return `[${body}]`;
 }
 
-function generateObject(value: ICompositeObject, options: CompositeValueGeneratorOptions = {}): string {
-  if (isJsExpression(value)) {
-    if (options.handlers && options.handlers.expression) {
-      return options.handlers.expression(value);
-    }
-    return generateExpression(value);
-  }
-
-  if (isJsFunction(value)) {
-    return generateFunction(value, { isArrow: true });
-  }
-
-  if (isJsSlot(value)) {
-    if (options.nodeGenerator) {
-      return generateJsSlot(value, options.nodeGenerator);
-    }
-    throw new CodeGeneratorError("Can't find Node Generator");
-  }
-
+function generateObject(value: CompositeObject, scope: IScope, options: CompositeValueGeneratorOptions = {}): string {
   const body = Object.keys(value)
     .map((key) => {
       let propName = key;
@@ -59,7 +42,7 @@ function generateObject(value: ICompositeObject, options: CompositeValueGenerato
           throw new CodeGeneratorError(`Propname: ${key} is not a valid identifier.`);
         }
       }
-      const v = generateUnknownType(value[key], options);
+      const v = generateUnknownType(value[key], scope, options);
       return `${propName}: ${v}`;
     })
     .join(',\n');
@@ -67,40 +50,108 @@ function generateObject(value: ICompositeObject, options: CompositeValueGenerato
   return `{${body}}`;
 }
 
-export function generateUnknownType(value: CompositeValue, options: CompositeValueGeneratorOptions = {}): string {
-  if (Array.isArray(value)) {
-    if (options.handlers && options.handlers.array) {
-      return options.handlers.array(value);
-    }
-    return generateArray(value as CompositeArray, options);
-  } else if (typeof value === 'object') {
-    if (options.handlers && options.handlers.object) {
-      return options.handlers.object(value);
-    }
-    return generateObject(value as ICompositeObject, options);
-  } else if (typeof value === 'string') {
-    if (options.handlers && options.handlers.string) {
-      return options.handlers.string(value);
-    }
-    return `'${value}'`;
-  } else if (typeof value === 'number' && options.handlers && options.handlers.number) {
-    return options.handlers.number(value);
-  } else if (typeof value === 'boolean' && options.handlers && options.handlers.boolean) {
-    return options.handlers.boolean(value);
-  }
-  return `${value}`;
+function generateString(value: string): string {
+  return `'${value}'`;
 }
 
-export function generateCompositeType(value: CompositeValue, options: CompositeValueGeneratorOptions = {}): string {
-  const result = generateUnknownType(value, options);
-  const containerHandlers = {
-    ...defaultContainerHandlers,
-    ...(options.containerHandlers || {}),
-  };
-
-  const isStringType = result.substr(0, 1) === "'" && result.substr(-1, 1) === "'";
-  if (isStringType) {
-    return (containerHandlers.string && containerHandlers.string(result.substring(1, result.length - 1))) || '';
-  }
-  return (containerHandlers.default && containerHandlers.default(result)) || '';
+function generateNumber(value: number): string {
+  return String(value);
+}
+
+function generateBool(value: boolean): string {
+  return value ? 'true' : 'false';
+}
+
+function genFunction(value: JSFunction): string {
+  return generateFunction(value, { isArrow: true });
+}
+
+function genJsSlot(value: JSSlot, scope: IScope, options: CompositeValueGeneratorOptions = {}) {
+  if (options.nodeGenerator) {
+    return generateJsSlot(value, scope, options.nodeGenerator);
+  }
+  return '';
+}
+
+function generateUnknownType(
+  value: CompositeValue,
+  scope: IScope,
+  options: CompositeValueGeneratorOptions = {},
+): string {
+  if (_.isUndefined(value)) {
+    return 'undefined';
+  }
+
+  if (_.isNull(value)) {
+    return 'null';
+  }
+
+  if (_.isArray(value)) {
+    if (options.handlers?.array) {
+      return executeFunctionStack(value, scope, options.handlers.array, generateArray, options);
+    }
+    return generateArray(value, scope, options);
+  }
+
+  if (isJSExpression(value)) {
+    if (options.handlers?.expression) {
+      return executeFunctionStack(value, scope, options.handlers.expression, generateExpression, options);
+    }
+    return generateExpression(value);
+  }
+
+  if (isJSFunction(value)) {
+    if (options.handlers?.function) {
+      return executeFunctionStack(value, scope, options.handlers.function, genFunction, options);
+    }
+    return genFunction(value);
+  }
+
+  if (isJSSlot(value)) {
+    if (options.handlers?.slot) {
+      return executeFunctionStack(value, scope, options.handlers.slot, genJsSlot, options);
+    }
+    return genJsSlot(value, scope, options);
+  }
+
+  if (_.isObject(value)) {
+    if (options.handlers?.object) {
+      return executeFunctionStack(value, scope, options.handlers.object, generateObject, options);
+    }
+    return generateObject(value as CompositeObject, scope, options);
+  }
+
+  if (_.isString(value)) {
+    if (options.handlers?.string) {
+      return executeFunctionStack(value, scope, options.handlers.string, generateString, options);
+    }
+    return generateString(value);
+  }
+
+  if (_.isNumber(value)) {
+    if (options.handlers?.number) {
+      return executeFunctionStack(value, scope, options.handlers.number, generateNumber, options);
+    }
+    return generateNumber(value);
+  }
+
+  if (_.isBoolean(value)) {
+    if (options.handlers?.boolean) {
+      return executeFunctionStack(value, scope, options.handlers.boolean, generateBool, options);
+    }
+    return generateBool(value);
+  }
+
+  throw new CodeGeneratorError('Meet unknown composite value type');
+}
+
+// 这一层曾经是对产出做最外层包装的，但其实包装逻辑不应该属于这一层
+// 这一层先不去掉，做冗余，方便后续重构
+export function generateCompositeType(
+  value: CompositeValue,
+  scope: IScope,
+  options: CompositeValueGeneratorOptions = {},
+): string {
+  const result = generateUnknownType(value, scope, options);
+  return result;
 }
diff --git a/packages/code-generator/src/utils/expressionParser.ts b/packages/code-generator/src/utils/expressionParser.ts
new file mode 100644
index 000000000..cc952060b
--- /dev/null
+++ b/packages/code-generator/src/utils/expressionParser.ts
@@ -0,0 +1,243 @@
+import * as parser from '@babel/parser';
+import generate from '@babel/generator';
+import traverse, { NodePath } from '@babel/traverse';
+import * as t from '@babel/types';
+import { isIdentifier, Node } from '@babel/types';
+
+import { OrderedSet } from './OrderedSet';
+
+export class ParseError extends Error {
+  constructor(expr: string | t.Expression) {
+    super(`Failed to parse expression "${typeof expr === 'string' ? expr : generate(expr)}"`);
+    Object.setPrototypeOf(this, new.target.prototype);
+  }
+}
+
+const MAYBE_EXPRESSIONS: {
+  [k in Node['type']]?: {
+    // fields: Array<keyof (Node & { type: k })>
+    fields: string[] | ((node: Node) => string[]);
+  };
+} = {
+  ArrayExpression: { fields: ['elements'] },
+  AssignmentExpression: { fields: ['left', 'right'] },
+  BinaryExpression: { fields: ['left', 'right'] },
+  CallExpression: { fields: ['arguments', 'callee'] },
+  ConditionalExpression: { fields: ['test', 'consequent', 'alternate'] },
+  DoWhileStatement: { fields: ['test'] },
+  ExpressionStatement: { fields: ['expression'] },
+  ForInStatement: { fields: ['right'] },
+  ForStatement: { fields: ['init', 'test', 'update'] },
+  IfStatement: { fields: ['test'] },
+  LogicalExpression: { fields: ['left', 'right'] },
+  MemberExpression: {
+    fields: (node) => { return (node.type === 'MemberExpression' && node.computed) ? ['object', 'property'] : ['object']; },
+  },
+  NewExpression: { fields: ['callee', 'arguments'] },
+  ObjectMethod: {
+    fields: (node) => { return (node.type === 'ObjectMethod' && node.computed) ? ['key'] : []; },
+  },
+  ObjectProperty: {
+    fields: (node) => { return (node.type === 'ObjectProperty' && node.computed) ? ['key', 'value'] : ['value']; },
+  },
+  ReturnStatement: { fields: ['argument'] },
+  SequenceExpression: { fields: ['expressions'] },
+  ParenthesizedExpression: { fields: ['expression'] },
+  SwitchCase: { fields: ['test'] },
+  SwitchStatement: { fields: ['discriminant'] },
+  ThrowStatement: { fields: ['argument'] },
+  UnaryExpression: { fields: ['argument'] },
+  UpdateExpression: { fields: ['argument'] },
+  VariableDeclarator: { fields: ['init'] },
+  WhileStatement: { fields: ['test'] },
+  WithStatement: { fields: ['object'] },
+  AssignmentPattern: { fields: ['right'] },
+  ArrowFunctionExpression: { fields: ['body'] },
+  ClassExpression: { fields: ['superClass'] },
+  ClassDeclaration: { fields: ['superClass'] },
+  ExportDefaultDeclaration: { fields: ['declaration'] },
+  ForOfStatement: { fields: ['right'] },
+  ClassMethod: { fields: (node) => { return (node.type === 'ClassMethod' && node.computed) ? ['key'] : []; } },
+  SpreadElement: { fields: ['argument'] },
+  TaggedTemplateExpression: { fields: ['tag'] },
+  TemplateLiteral: { fields: ['expressions'] },
+  YieldExpression: { fields: ['argument'] },
+  AwaitExpression: { fields: ['argument'] },
+  OptionalMemberExpression: {
+    fields: (node) => { return (node.type === 'OptionalMemberExpression' && node.computed) ? ['object', 'property'] : ['object']; },
+  },
+  OptionalCallExpression: { fields: ['callee', 'arguments'] },
+  JSXSpreadAttribute: { fields: ['argument'] },
+  BindExpression: { fields: ['object', 'callee'] },
+  ClassProperty: { fields: (node) => { return (node.type === 'ClassProperty' && node.computed) ? ['key', 'value'] : ['value']; } },
+  PipelineTopicExpression: { fields: ['expression'] },
+  PipelineBareFunction: { fields: ['callee'] },
+  ClassPrivateProperty: { fields: ['value'] },
+  Decorator: { fields: ['expression'] },
+  TupleExpression: { fields: ['elements'] },
+  TSDeclareMethod: { fields: (node) => { return (node.type === 'TSDeclareMethod' && node.computed) ? ['key'] : []; } },
+  TSPropertySignature: {
+    fields: (node) => { return (node.type === 'TSPropertySignature' && node.computed) ? ['key', 'initializer'] : ['initializer']; },
+  },
+
+  TSMethodSignature: {
+    fields: (node) => { return (node.type === 'TSMethodSignature' && node.computed) ? ['key'] : []; },
+  },
+  TSAsExpression: { fields: ['expression'] },
+  TSTypeAssertion: { fields: ['expression'] },
+  TSEnumDeclaration: { fields: ['initializer'] },
+  TSEnumMember: { fields: ['initializer'] },
+  TSNonNullExpression: { fields: ['expression'] },
+  TSExportAssignment: { fields: ['expression'] },
+};
+
+export type ParseExpressionGetGlobalVariablesOptions = { filter?: (varName: string) => boolean };
+
+const CROSS_THIS_SCOPE_TYPE_NODE: {
+  [k in Node['type']]?: boolean;
+} = {
+  ArrowFunctionExpression: false, // 箭头函数不跨越 this 的 scope
+  FunctionExpression: true,
+  FunctionDeclaration: true,
+  // FunctionTypeAnnotation: false, // 这是 TS 定义
+  // FunctionTypeParam: false, // 这是 TS 定义
+  ClassDeclaration: true,
+  ClassExpression: true,
+  ClassBody: true,
+  ClassImplements: true,
+  ClassMethod: true,
+  ClassPrivateMethod: true,
+  ClassProperty: true,
+  ClassPrivateProperty: true,
+  DeclareClass: true,
+};
+
+export function parseExpressionGetGlobalVariables(
+  expr: string | null | undefined,
+  { filter = () => true }: ParseExpressionGetGlobalVariablesOptions = {},
+): string[] {
+  if (!expr) {
+    return [];
+  }
+
+  try {
+    const undeclaredVars = new OrderedSet<string>();
+
+    const ast = parser.parse(`!(${expr});`);
+
+    const addUndeclaredIdentifierIfNeeded =
+      (x: Record<string, unknown> | null | undefined, path: NodePath<Node>) => {
+        if (isIdentifier(x) && !path.scope.hasBinding(x.name)) {
+          undeclaredVars.add(x.name);
+        }
+      };
+
+    traverse(ast, {
+      enter(path) {
+        const node = path.node;
+        const expressionFields = MAYBE_EXPRESSIONS[node.type]?.fields;
+        if (expressionFields) {
+          (typeof expressionFields === 'function' ? expressionFields(node) : expressionFields).forEach((fieldName) => {
+            const fieldValue = node[fieldName as keyof typeof node];
+            if (typeof fieldValue === 'object') {
+              if (Array.isArray(fieldValue)) {
+                fieldValue.forEach((item) => {
+                  addUndeclaredIdentifierIfNeeded(item, path);
+                });
+              } else {
+                addUndeclaredIdentifierIfNeeded(fieldValue, path);
+              }
+            }
+          });
+        }
+      },
+    });
+
+    return undeclaredVars.toArray().filter(filter);
+  } catch (e) {
+    throw new ParseError(expr);
+  }
+}
+
+export function parseExpressionConvertThis2Context(
+  expr: string | t.Expression,
+  contextName = '__$$context',
+  localVariables: string[] = [],
+): string {
+  if (!expr) {
+    return expr;
+  }
+
+  try {
+    const exprAst = typeof expr === 'string' ? parser.parseExpression(expr) : expr;
+    const exprWrapAst = t.expressionStatement(exprAst);
+    const fileAst = t.file(t.program([exprWrapAst]));
+
+    const localVariablesSet = new Set(localVariables);
+
+    let thisScopeLevel = CROSS_THIS_SCOPE_TYPE_NODE[exprAst.type] ? -1 : 0;
+    traverse(fileAst, {
+      enter(path) {
+        if (CROSS_THIS_SCOPE_TYPE_NODE[path.node.type]) {
+          thisScopeLevel++;
+        }
+      },
+      exit(path) {
+        if (CROSS_THIS_SCOPE_TYPE_NODE[path.node.type]) {
+          thisScopeLevel--;
+        }
+      },
+      MemberExpression(path) {
+        if (!path.isMemberExpression()) {
+          return;
+        }
+
+        const obj = path.get('object');
+        if (!obj.isThisExpression()) {
+          return;
+        }
+
+        // 处理局部变量
+        if (!path.node.computed) {
+          const prop = path.get('property');
+          if (prop.isIdentifier() && localVariablesSet.has(prop.node.name)) {
+            path.replaceWith(t.identifier(prop.node.name));
+            return;
+          }
+        }
+
+        // 替换 this (只在顶层替换)
+        if (thisScopeLevel <= 0) {
+          obj.replaceWith(t.identifier(contextName));
+        }
+      },
+      ThisExpression(path) {
+        if (!path.isThisExpression()) {
+          return;
+        }
+
+        // MemberExpression 中的 this.xxx 已经处理过了
+        if (path.parent.type === 'MemberExpression') {
+          return;
+        }
+
+        if (thisScopeLevel <= 0) {
+          path.replaceWith(t.identifier(contextName));
+        }
+      },
+    });
+
+    const { code } = generate(exprWrapAst.expression, { sourceMaps: false });
+    return code;
+  } catch (e) {
+    throw new ParseError(expr);
+  }
+}
+
+export function parseExpression(expr: string) {
+  try {
+    return parser.parseExpression(expr);
+  } catch (e) {
+    throw new ParseError(expr);
+  }
+}
diff --git a/packages/code-generator/src/utils/jsExpression.ts b/packages/code-generator/src/utils/jsExpression.ts
index d975228ee..d30e27141 100644
--- a/packages/code-generator/src/utils/jsExpression.ts
+++ b/packages/code-generator/src/utils/jsExpression.ts
@@ -1,4 +1,5 @@
-import { CodeGeneratorError, IJSExpression, IJSFunction } from '../types';
+import { JSExpression, JSFunction, isJSExpression, isJSFunction } from '@ali/lowcode-types';
+import { CodeGeneratorError } from '../types';
 
 export function transformFuncExpr2MethodMember(methodName: string, functionBody: string): string {
   const args = getFuncExprArguments(functionBody);
@@ -23,8 +24,6 @@ export function getFuncExprBody(functionBody: string) {
   const start = functionBody.indexOf('{');
   const end = functionBody.lastIndexOf('}');
 
-  // test(functionBody);
-
   if (start < 0 || end < 0 || end < start) {
     throw new CodeGeneratorError('JSExpression has no valid body.');
   }
@@ -40,21 +39,13 @@ export function getArrowFunction(functionBody: string) {
   return `(${args}) => { ${body} }`;
 }
 
-export function isJsExpression(value: unknown): boolean {
-  return value && typeof value === 'object' && (value as IJSExpression).type === 'JSExpression';
-}
-
-export function isJsFunction(value: unknown): boolean {
-  return value && typeof value === 'object' && (value as IJSFunction).type === 'JSFunction';
-}
-
 export function isJsCode(value: unknown): boolean {
-  return isJsExpression(value) || isJsFunction(value);
+  return isJSExpression(value) || isJSFunction(value);
 }
 
 export function generateExpression(value: any): string {
-  if (isJsExpression(value)) {
-    return (value as IJSExpression).value || 'null';
+  if (isJSExpression(value)) {
+    return (value as JSExpression).value || 'null';
   }
 
   throw new CodeGeneratorError('Not a JSExpression');
@@ -75,7 +66,7 @@ export function generateFunction(
   },
 ) {
   if (isJsCode(value)) {
-    const functionCfg = value as IJSFunction;
+    const functionCfg = value as JSFunction;
     if (config.isMember) {
       return transformFuncExpr2MethodMember(config.name || '', functionCfg.value);
     }
diff --git a/packages/code-generator/src/utils/jsSlot.ts b/packages/code-generator/src/utils/jsSlot.ts
index 13f40eef6..e47136ed2 100644
--- a/packages/code-generator/src/utils/jsSlot.ts
+++ b/packages/code-generator/src/utils/jsSlot.ts
@@ -1,20 +1,34 @@
-import { CodeGeneratorError, NodeGenerator, IJSSlot } from '../types';
+import { JSSlot, isJSSlot } from '@ali/lowcode-types';
+import { CodeGeneratorError, NodeGenerator, IScope } from '../types';
 
-export function isJsSlot(value: unknown): boolean {
-  return value && typeof value === 'object' && (value as IJSSlot).type === 'JSSlot';
+function generateSingleLineComment(commentText: string): string {
+  return (
+    `/* ${
+      commentText
+        .split('\n')
+        .join(' ')
+        .replace(/\*\//g, '*-/')
+    }*/`
+  );
 }
 
-export function generateJsSlot(value: any, generator: NodeGenerator): string {
-  if (isJsSlot(value)) {
-    const slotCfg = value as IJSSlot;
-    if (!slotCfg.value) {
-      return 'null';
+export function generateJsSlot(slot: any, scope: IScope, generator: NodeGenerator<string>): string {
+  if (isJSSlot(slot)) {
+    const { title, params, value } = slot as JSSlot;
+    if (params) {
+      return [
+        title && generateSingleLineComment(title),
+        '(',
+        ...(params || []),
+        ') => (',
+        !value ? 'null' : generator(value, scope),
+        ')',
+      ]
+        .filter(Boolean)
+        .join('');
     }
-    const results = slotCfg.value.map((n) => generator(n));
-    if (results.length === 1) {
-      return results[0];
-    }
-    return `[${results.join(',')}]`;
+
+    return !value ? 'null' : generator(value, scope);
   }
 
   throw new CodeGeneratorError('Not a JSSlot');
diff --git a/packages/code-generator/src/utils/nodeToJSX.ts b/packages/code-generator/src/utils/nodeToJSX.ts
index 237221346..6f91b8d81 100644
--- a/packages/code-generator/src/utils/nodeToJSX.ts
+++ b/packages/code-generator/src/utils/nodeToJSX.ts
@@ -1,220 +1,154 @@
+import _ from 'lodash';
+import { NodeSchema, isNodeSchema, NodeDataType, CompositeValue } from '@ali/lowcode-types';
+
 import {
-  ChildNodeType,
-  IComponentNodeItem,
-  IJSExpression,
-  ChildNodeItem,
+  IScope,
   CodeGeneratorError,
   PIECE_TYPE,
   CodePiece,
-  HandlerSet,
-  ExtGeneratorPlugin,
-  IJSSlot,
-  INodeGeneratorConfig,
-  INodeGeneratorContext,
   NodeGenerator,
+  NodeGeneratorConfig,
+  NodePlugin,
+  AttrData,
 } from '../types';
+
 import { generateCompositeType } from './compositeType';
-import { generateExpression, isJsExpression } from './jsExpression';
-import { isJsSlot } from './jsSlot';
+import { executeFunctionStack } from './aopHelper';
 
-// tslint:disable-next-line: no-empty
-const noop = () => [];
-
-const handleChildrenDefaultOptions = {
-  rerun: false,
-};
-
-export function handleSubNodes<T>(
-  children: ChildNodeType,
-  handlers: HandlerSet<T>,
-  options?: {
-    rerun?: boolean;
-  },
-): T[] {
-  const opt = {
-    ...handleChildrenDefaultOptions,
-    ...(options || {}),
-  };
-
-  if (Array.isArray(children)) {
-    const list: ChildNodeItem[] = children as ChildNodeItem[];
-    return list.map((child) => handleSubNodes(child, handlers, opt)).reduce((p, c) => p.concat(c), []);
-  } else if (typeof children === 'string') {
-    const handler = handlers.string || handlers.common || noop;
-    return handler(children as string);
-  } else if (isJsExpression(children)) {
-    const handler = handlers.expression || handlers.common || noop;
-    return handler(children as IJSExpression);
-  } else {
-    const handler = handlers.node || handlers.common || noop;
-    let curRes = handler(children as IComponentNodeItem);
-    if (opt.rerun && children.children) {
-      const childRes = handleSubNodes(children.children, handlers, opt);
-      curRes = curRes.concat(childRes || []);
-    }
-    if (children.props) {
-      Object.keys(children.props)
-        .filter((propName) => isJsSlot(children.props[propName]))
-        .forEach((propName) => {
-          const soltVals = (children.props[propName] as IJSSlot).value;
-          (soltVals || []).forEach((soltVal) => {
-            const childRes = handleSubNodes(soltVal, handlers, opt);
-            curRes = curRes.concat(childRes || []);
-          });
-        });
-    }
-    return curRes;
+function mergeNodeGeneratorConfig(cfg1: NodeGeneratorConfig, cfg2: NodeGeneratorConfig = {}): NodeGeneratorConfig {
+  const resCfg: NodeGeneratorConfig = {};
+  if (cfg1.handlers || cfg2.handlers) {
+    resCfg.handlers = {
+      ...(cfg1.handlers || {}),
+      ...(cfg2.handlers || {}),
+    };
   }
+
+  if (cfg1.tagMapping || cfg2.tagMapping) {
+    resCfg.tagMapping = cfg2.tagMapping || cfg1.tagMapping;
+  }
+
+  if (cfg1.attrPlugins || cfg2.attrPlugins) {
+    resCfg.attrPlugins = [];
+    resCfg.attrPlugins.push(...(cfg2.attrPlugins || []));
+    resCfg.attrPlugins.push(...(cfg1.attrPlugins || []));
+  }
+
+  if (cfg1.nodePlugins || cfg2.nodePlugins) {
+    resCfg.nodePlugins = [];
+    resCfg.nodePlugins.push(...(cfg2.nodePlugins || []));
+    resCfg.nodePlugins.push(...(cfg1.nodePlugins || []));
+  }
+
+  return resCfg;
 }
 
-export function handleChildren<T>(
-  ctx: INodeGeneratorContext,
-  children: ChildNodeType,
-  handlers: HandlerSet<T>,
-  options?: {
-    rerun?: boolean;
-  },
-): T[] {
-  const opt = {
-    ...handleChildrenDefaultOptions,
-    ...(options || {}),
-  };
-
-  if (Array.isArray(children)) {
-    const list: ChildNodeItem[] = children as ChildNodeItem[];
-    return list.map((child) => handleChildren(ctx, child, handlers, opt)).reduce((p, c) => p.concat(c), []);
-  } else if (typeof children === 'string') {
-    const handler = handlers.string || handlers.common || noop;
-    return handler(children as string);
-  } else if (isJsExpression(children)) {
-    const handler = handlers.expression || handlers.common || noop;
-    return handler(children as IJSExpression);
-  } else {
-    const handler = handlers.node || handlers.common || noop;
-    let curRes = handler(children as IComponentNodeItem);
-    if (opt.rerun && children.children) {
-      const childRes = handleChildren(ctx, children.children, handlers, opt);
-      curRes = curRes.concat(childRes || []);
-    }
-    return curRes;
-  }
-}
-
-export function generateAttr(ctx: INodeGeneratorContext, attrName: string, attrValue: any): CodePiece[] {
-  if (attrName === 'initValue') {
-    return [];
-  }
-  const valueStr = generateCompositeType(attrValue, {
-    containerHandlers: {
-      default: (v) => `{${v}}`,
-      string: (v) => `"${v}"`,
-    },
-    nodeGenerator: ctx.generator,
+function generateAttrValue(
+  attrData: { attrName: string; attrValue: CompositeValue },
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+): CodePiece[] {
+  const valueStr = generateCompositeType(attrData.attrValue, scope, {
+    handlers: config?.handlers,
+    nodeGenerator: config?.self,
   });
   return [
     {
-      value: `${attrName}=${valueStr}`,
       type: PIECE_TYPE.ATTR,
+      name: attrData.attrName,
+      value: valueStr,
     },
   ];
 }
 
-export function generateAttrs(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] {
-  const { props } = nodeItem;
-  let pieces: CodePiece[] = [];
+function generateAttr(
+  attrName: string,
+  attrValue: CompositeValue,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+): CodePiece[] {
+  let pieces: CodePiece[];
+  if (config?.attrPlugins) {
+    pieces = executeFunctionStack<AttrData, CodePiece[], NodeGeneratorConfig>(
+      { attrName, attrValue },
+      scope,
+      config.attrPlugins,
+      generateAttrValue,
+      config,
+    );
+  } else {
+    pieces = generateAttrValue({ attrName, attrValue }, scope, config);
+  }
 
-  Object.keys(props).forEach(
-    (propName: string) => (pieces = pieces.concat(generateAttr(ctx, propName, props[propName]))),
-  );
+  pieces = pieces.map((p) => {
+    // FIXME: 在经过 generateCompositeType 处理过之后，其实已经无法通过传入值的类型判断传出值是否为纯字面值字符串了（可能包裹了加工函数之类的）
+    //        因此这个处理最好的方式是对传出值做语法分析，判断以哪种模版产出 Attr 值
+    let newValue: string;
+    if (p.value && p.value[0] === "'" && p.value[p.value.length - 1] === "'") {
+      newValue = `"${p.value.substring(1, p.value.length - 1)}"`;
+    } else {
+      newValue = `{${p.value}}`;
+    }
+
+    return {
+      value: `${p.name}=${newValue}`,
+      type: PIECE_TYPE.ATTR,
+    };
+  });
 
   return pieces;
 }
 
-function mapNodeName(src: string, mapping: Record<string, string>): string {
-  if (mapping[src]) {
-    return mapping[src];
+function generateAttrs(nodeItem: NodeSchema, scope: IScope, config?: NodeGeneratorConfig): CodePiece[] {
+  const { props } = nodeItem;
+
+  let pieces: CodePiece[] = [];
+
+  if (props) {
+    if (!Array.isArray(props)) {
+      Object.keys(props).forEach((propName: string) => {
+        pieces = pieces.concat(generateAttr(propName, props[propName], scope, config));
+      });
+    } else {
+      props.forEach((prop) => {
+        if (prop.name && !prop.spread) {
+          pieces = pieces.concat(generateAttr(prop.name, prop.value, scope, config));
+        }
+
+        // TODO: 处理 spread 场景（<Xxx {...(something)}/>)
+        // 这种在 schema 里面怎么描述
+      });
+    }
   }
-  return src;
+
+  return pieces;
 }
 
-export function generateBasicNode(
-  ctx: INodeGeneratorContext,
-  nodeItem: IComponentNodeItem,
-  mapping: Record<string, string>,
-): CodePiece[] {
+function generateBasicNode(nodeItem: NodeSchema, scope: IScope, config?: NodeGeneratorConfig): CodePiece[] {
   const pieces: CodePiece[] = [];
+  const tagName = (config?.tagMapping || _.identity)(nodeItem.componentName);
+
   pieces.push({
-    value: mapNodeName(nodeItem.componentName, mapping),
+    value: tagName || '', // FIXME: type detection error
     type: PIECE_TYPE.TAG,
   });
 
   return pieces;
 }
 
-// TODO: 生成文档
-// 为包裹的代码片段生成子上下文，集成父级上下文，并传入子级上下文新增内容。（如果存在多级上下文怎么处理？）
-// 创建新的上下文，并从作用域中取对应同名变量塞到作用域里面？
-// export function createSubContext() {}
+function generateSimpleNode(nodeItem: NodeSchema, scope: IScope, config?: NodeGeneratorConfig): CodePiece[] {
+  const basicParts = generateBasicNode(nodeItem, scope, config) || [];
+  const attrParts = generateAttrs(nodeItem, scope, config) || [];
 
-/**
- * JSX 生成逻辑插件。在 React 代码模式下生成 loop 与 condition 相关的逻辑代码
- *
- * @export
- * @param {IComponentNodeItem} nodeItem 当前 UI 节点
- * @returns {CodePiece[]} 实现功能的相关代码片段
- */
-export function generateReactCtrlLine(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] {
-  const pieces: CodePiece[] = [];
-
-  if (nodeItem.loop) {
-    const args: [string, string] = nodeItem.loopArgs || ['item', 'index'];
-    const loopData = generateCompositeType(nodeItem.loop, {
-      nodeGenerator: ctx.generator,
-    });
-    pieces.unshift({
-      value: `(${loopData}).map((${args[0]}, ${args[1]}) => (`,
-      type: PIECE_TYPE.BEFORE,
-    });
-    pieces.push({
-      value: '))',
-      type: PIECE_TYPE.AFTER,
-    });
-  }
-
-  if (nodeItem.condition) {
-    const value = generateCompositeType(nodeItem.condition, {
-      nodeGenerator: ctx.generator,
-    });
-
-    pieces.unshift({
-      value: `(${value}) && (`,
-      type: PIECE_TYPE.BEFORE,
-    });
-    pieces.push({
-      value: ')',
-      type: PIECE_TYPE.AFTER,
-    });
-  }
-
-  if (nodeItem.condition || nodeItem.loop) {
-    pieces.unshift({
-      value: '{',
-      type: PIECE_TYPE.BEFORE,
-    });
-    pieces.push({
-      value: '}',
-      type: PIECE_TYPE.AFTER,
-    });
-  }
-
-  return pieces;
+  return [...basicParts, ...attrParts];
 }
 
-export function linkPieces(pieces: CodePiece[]): string {
-  if (pieces.filter((p) => p.type === PIECE_TYPE.TAG).length !== 1) {
+function linkPieces(pieces: CodePiece[]): string {
+  const tagsPieces = pieces.filter((p) => p.type === PIECE_TYPE.TAG);
+  if (tagsPieces.length !== 1) {
     throw new CodeGeneratorError('One node only need one tag define');
   }
-  const tagName = pieces.filter((p) => p.type === PIECE_TYPE.TAG)[0].value;
+  const tagName = tagsPieces[0].value;
 
   const beforeParts = pieces
     .filter((p) => p.type === PIECE_TYPE.BEFORE)
@@ -245,53 +179,173 @@ export function linkPieces(pieces: CodePiece[]): string {
   return `${beforeParts}<${tagName}${attrsParts} />${afterParts}`;
 }
 
-export function createNodeGenerator(
-  handlers: HandlerSet<string>,
-  plugins: ExtGeneratorPlugin[],
-  cfg?: INodeGeneratorConfig,
-): NodeGenerator {
-  let nodeTypeMapping: Record<string, string> = {};
-  if (cfg && cfg.nodeTypeMapping) {
-    nodeTypeMapping = cfg.nodeTypeMapping;
+function generateNodeSchema(nodeItem: NodeSchema, scope: IScope, config?: NodeGeneratorConfig): string {
+  const pieces: CodePiece[] = [];
+  if (config?.nodePlugins) {
+    const res = executeFunctionStack<NodeSchema, CodePiece[], NodeGeneratorConfig>(
+      nodeItem,
+      scope,
+      config.nodePlugins,
+      generateSimpleNode,
+      config,
+    );
+    pieces.push(...res);
+  } else {
+    pieces.push(...generateSimpleNode(nodeItem, scope, config));
   }
 
-  const generateNode = (nodeItem: IComponentNodeItem): string => {
-    let pieces: CodePiece[] = [];
-    const ctx: INodeGeneratorContext = {
-      generator: generateNode,
-    };
+  if (nodeItem.children && config?.self) {
+    const childrenStr = config.self(nodeItem.children, scope);
 
-    plugins.forEach((p) => {
-      pieces = pieces.concat(p(ctx, nodeItem));
+    pieces.push({
+      type: PIECE_TYPE.CHILDREN,
+      value: childrenStr,
     });
-    pieces = pieces.concat(generateBasicNode(ctx, nodeItem, nodeTypeMapping));
-    pieces = pieces.concat(generateAttrs(ctx, nodeItem));
-    if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) {
-      pieces = pieces.concat(
-        handleChildren<string>(ctx, nodeItem.children, handlers).map((l) => ({
-          type: PIECE_TYPE.CHILDREN,
-          value: l,
-        })),
-      );
+  }
+
+  return linkPieces(pieces);
+}
+
+// TODO: 生成文档
+// 为包裹的代码片段生成子上下文，集成父级上下文，并传入子级上下文新增内容。（如果存在多级上下文怎么处理？）
+// 创建新的上下文，并从作用域中取对应同名变量塞到作用域里面？
+// export function createSubContext() {}
+
+/**
+ * JSX 生成逻辑插件。在 React 代码模式下生成 loop 相关的逻辑代码
+ * @type NodePlugin Extended
+ *
+ * @export
+ * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @returns {CodePiece[]} 实现功能的相关代码片段
+ */
+export function generateReactLoopCtrl(
+  nodeItem: NodeSchema,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+  next?: NodePlugin,
+): CodePiece[] {
+  const pieces: CodePiece[] = next ? next(nodeItem, scope, config) : [];
+
+  if (nodeItem.loop) {
+    const loopItemName = nodeItem.loopArgs?.[0] || 'item';
+    const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
+
+    const loopDataExpr = generateCompositeType(nodeItem.loop, scope, {
+      handlers: config?.handlers,
+    });
+
+    pieces.unshift({
+      value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => (`,
+      type: PIECE_TYPE.BEFORE,
+    });
+
+    pieces.push({
+      value: '))',
+      type: PIECE_TYPE.AFTER,
+    });
+  }
+
+  return pieces;
+}
+
+/**
+ * JSX 生成逻辑插件。在 React 代码模式下生成 condition 相关的逻辑代码
+ * @type NodePlugin
+ *
+ * @export
+ * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @returns {CodePiece[]} 实现功能的相关代码片段
+ */
+export function generateConditionReactCtrl(
+  nodeItem: NodeSchema,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+  next?: NodePlugin,
+): CodePiece[] {
+  const pieces: CodePiece[] = next ? next(nodeItem, scope, config) : [];
+
+  if (nodeItem.condition) {
+    const value = generateCompositeType(nodeItem.condition, scope, {
+      handlers: config?.handlers,
+    });
+
+    pieces.unshift({
+      value: `(${value}) && (`,
+      type: PIECE_TYPE.BEFORE,
+    });
+
+    pieces.push({
+      value: ')',
+      type: PIECE_TYPE.AFTER,
+    });
+  }
+
+  return pieces;
+}
+
+/**
+ * JSX 生成逻辑插件。在 React 代码模式下，如果 Node 生成结果是一个表达式，则对其进行 { Expression } 包装
+ * @type NodePlugin
+ *
+ * @export
+ * @param {NodeSchema} nodeItem 当前 UI 节点
+ * @returns {CodePiece[]} 实现功能的相关代码片段
+ */
+export function generateReactExprInJS(
+  nodeItem: NodeSchema,
+  scope: IScope,
+  config?: NodeGeneratorConfig,
+  next?: NodePlugin,
+): CodePiece[] {
+  const pieces: CodePiece[] = next ? next(nodeItem, scope, config) : [];
+
+  if (nodeItem.condition || nodeItem.loop) {
+    pieces.unshift({
+      value: '{',
+      type: PIECE_TYPE.BEFORE,
+    });
+
+    pieces.push({
+      value: '}',
+      type: PIECE_TYPE.AFTER,
+    });
+  }
+
+  return pieces;
+}
+
+const handleChildren = (v: string[]) => v.join('');
+
+export function createNodeGenerator(cfg: NodeGeneratorConfig = {}): NodeGenerator<string> {
+  const generateNode = (nodeItem: NodeDataType, scope: IScope): string => {
+    if (_.isArray(nodeItem)) {
+      const resList = nodeItem.map((n) => generateNode(n, scope));
+      return handleChildren(resList);
     }
 
-    return linkPieces(pieces);
-  };
+    if (isNodeSchema(nodeItem)) {
+      return generateNodeSchema(nodeItem, scope, {
+        ...cfg,
+        self: generateNode,
+      });
+    }
 
-  handlers.node = (input: IComponentNodeItem) => [generateNode(input)];
+    return generateCompositeType(nodeItem, scope, {
+      handlers: cfg.handlers,
+      nodeGenerator: generateNode,
+    });
+  };
 
   return generateNode;
 }
 
-export const generateString = (input: string) => [input];
+const defaultReactGeneratorConfig: NodeGeneratorConfig = {
+  nodePlugins: [generateReactExprInJS, generateConditionReactCtrl, generateReactLoopCtrl],
+};
 
-export function createReactNodeGenerator(cfg?: INodeGeneratorConfig): NodeGenerator {
-  return createNodeGenerator(
-    {
-      string: generateString,
-      expression: (input) => [generateExpression(input)],
-    },
-    [generateReactCtrlLine],
-    cfg,
-  );
+export function createReactNodeGenerator(cfg?: NodeGeneratorConfig): NodeGenerator<string> {
+  const newCfg = mergeNodeGeneratorConfig(defaultReactGeneratorConfig, cfg);
+
+  return createNodeGenerator(newCfg);
 }
diff --git a/packages/code-generator/src/utils/resultHelper.ts b/packages/code-generator/src/utils/resultHelper.ts
new file mode 100644
index 000000000..35b9fe7b0
--- /dev/null
+++ b/packages/code-generator/src/utils/resultHelper.ts
@@ -0,0 +1,35 @@
+import { ResultFile, ResultDir } from '@ali/lowcode-types';
+
+import { CodeGeneratorError } from '../types/error';
+
+export function createResultFile(name: string, ext = 'jsx', content = ''): ResultFile {
+  return {
+    name,
+    ext,
+    content,
+  };
+}
+
+export function createResultDir(name: string): ResultDir {
+  return {
+    name,
+    dirs: [],
+    files: [],
+  };
+}
+
+export function addDirectory(target: ResultDir, dir: ResultDir): void {
+  if (target.dirs.findIndex((d) => d.name === dir.name) < 0) {
+    target.dirs.push(dir);
+  } else {
+    throw new CodeGeneratorError(`Adding same directory to one directory: ${dir.name} -> ${target.name}`);
+  }
+}
+
+export function addFile(target: ResultDir, file: ResultFile): void {
+  if (target.files.findIndex((f) => f.name === file.name && f.ext === file.ext) < 0) {
+    target.files.push(file);
+  } else {
+    throw new CodeGeneratorError(`Adding same file to one directory: ${file.name} -> ${target.name}`);
+  }
+}
diff --git a/packages/code-generator/src/utils/schema.ts b/packages/code-generator/src/utils/schema.ts
new file mode 100644
index 000000000..527b22f60
--- /dev/null
+++ b/packages/code-generator/src/utils/schema.ts
@@ -0,0 +1,87 @@
+import {
+  JSSlot,
+  JSExpression,
+  NodeData,
+  NodeSchema,
+  PropsMap,
+  isJSExpression,
+  isJSSlot,
+  isDOMText,
+  ContainerSchema,
+  NpmInfo,
+} from '@ali/lowcode-types';
+
+export function isContainerSchema(x: any): x is ContainerSchema {
+  return typeof x === 'object' && x && typeof x.componentName === 'string' && typeof x.fileName === 'string';
+}
+
+export function isNpmInfo(x: any): x is NpmInfo {
+  return typeof x === 'object' && x && typeof x.package === 'string';
+}
+
+// tslint:disable-next-line: no-empty
+const noop = () => undefined;
+
+const handleChildrenDefaultOptions = {
+  rerun: false,
+};
+
+export function handleSubNodes<T>(
+  children: unknown,
+  handlers: {
+    string?: (i: string) => T;
+    expression?: (i: JSExpression) => T;
+    node?: (i: NodeSchema) => T;
+  },
+  options?: {
+    rerun?: boolean;
+  },
+): T[] {
+  const opt = {
+    ...handleChildrenDefaultOptions,
+    ...(options || {}),
+  };
+
+  if (Array.isArray(children)) {
+    const list: NodeData[] = children as NodeData[];
+    return list.map(
+      (child) => handleSubNodes(child, handlers, opt)
+    ).reduce((p, c) => p.concat(c), []);
+  }
+
+  let result: T | undefined;
+  const childrenRes: T[] = [];
+  if (isDOMText(children)) {
+    const handler = handlers.string || noop;
+    result = handler(children as string);
+  } else if (isJSExpression(children)) {
+    const handler = handlers.expression || noop;
+    result = handler(children as JSExpression);
+  } else {
+    const handler = handlers.node || noop;
+    const child = children as NodeSchema;
+    result = handler(child);
+
+    if (opt.rerun && child.children) {
+      const childRes = handleSubNodes(child.children, handlers, opt);
+      childrenRes.push(...childRes);
+    }
+    if (child.props) {
+      // FIXME: currently only support PropsMap
+      const childProps = child.props as PropsMap;
+      Object.keys(childProps)
+        .filter((propName) => isJSSlot(childProps[propName]))
+        .forEach((propName) => {
+          const soltVals = (childProps[propName] as JSSlot).value;
+          const childRes = handleSubNodes(soltVals, handlers, opt);
+          childrenRes.push(...childRes);
+        });
+    }
+  }
+
+  if (result !== undefined) {
+    childrenRes.unshift(result);
+  }
+
+  return childrenRes;
+}
diff --git a/packages/code-generator/src/utils/templateHelper.ts b/packages/code-generator/src/utils/templateHelper.ts
index f1692ad67..90b66c50f 100644
--- a/packages/code-generator/src/utils/templateHelper.ts
+++ b/packages/code-generator/src/utils/templateHelper.ts
@@ -1,25 +1,25 @@
-import { IResultFile, IResultDir } from '../types';
-import ResultDir from '../model/ResultDir';
+import { ResultDir, ResultFile } from '@ali/lowcode-types';
+import { createResultDir, addDirectory, addFile } from '../utils/resultHelper';
 
-type FuncFileGenerator = () => [string[], IResultFile];
+type FuncFileGenerator = () => [string[], ResultFile];
 
-export function insertFile(root: IResultDir, path: string[], file: IResultFile) {
-  let current: IResultDir = root;
-  path.forEach(pathNode => {
-    const dir = current.dirs.find(d => d.name === pathNode);
+export function insertFile(root: ResultDir, path: string[], file: ResultFile) {
+  let current: ResultDir = root;
+  path.forEach((pathNode) => {
+    const dir = current.dirs.find((d) => d.name === pathNode);
     if (dir) {
       current = dir;
     } else {
-      const newDir = new ResultDir(pathNode);
-      current.addDirectory(newDir);
+      const newDir = createResultDir(pathNode);
+      addDirectory(current, newDir);
       current = newDir;
     }
   });
 
-  current.addFile(file);
+  addFile(current, file);
 }
 
-export function runFileGenerator(root: IResultDir, fun: FuncFileGenerator) {
+export function runFileGenerator(root: ResultDir, fun: FuncFileGenerator) {
   const [path, file] = fun();
   insertFile(root, path, file);
 }
diff --git a/packages/code-generator/src/utils/version.ts b/packages/code-generator/src/utils/version.ts
new file mode 100644
index 000000000..4f5e607e8
--- /dev/null
+++ b/packages/code-generator/src/utils/version.ts
@@ -0,0 +1,29 @@
+import semver from 'semver';
+
+export function calcCompatibleVersion(v1: string | undefined | null, v2: string | undefined | null): string {
+  if (!v1 && !v2) {
+    return '*';
+  }
+
+  if (!v1 || v1 === '*') {
+    return v2 || '*';
+  }
+
+  if (!v2 || v2 === '*') {
+    return v1;
+  }
+
+  if (v1 === v2) {
+    return v1;
+  }
+
+  if (!semver.intersects(v1, v2, { loose: true })) {
+    throw new Error(`no compatible versions for "${v1}" and "${v2}"`);
+  }
+
+  if (semver.subset(v1, v2, { loose: true })) {
+    return v1;
+  }
+
+  return v2;
+}
diff --git a/packages/code-generator/test-cases/.gitignore b/packages/code-generator/test-cases/.gitignore
new file mode 100644
index 000000000..b36969646
--- /dev/null
+++ b/packages/code-generator/test-cases/.gitignore
@@ -0,0 +1 @@
+actual/
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.editorconfig b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.editorconfig
new file mode 100644
index 000000000..5760be583
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintignore b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintignore
new file mode 100644
index 000000000..3b437e614
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintignore
@@ -0,0 +1,11 @@
+# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintrc.js b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintrc.js
new file mode 100644
index 000000000..e2a7c5b54
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ['rax'],
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.gitignore b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.gitignore
new file mode 100644
index 000000000..50a53dace
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/.gitignore
@@ -0,0 +1,17 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/README.md b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/README.md
new file mode 100644
index 000000000..6eff85d41
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/README.md
@@ -0,0 +1,15 @@
+# @ali/rax-component-demo
+
+## Getting Started
+
+### `npm run start`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/abc.json b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/abc.json
new file mode 100644
index 000000000..f9ee40f71
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/abc.json
@@ -0,0 +1,7 @@
+{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/build.json b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/build.json
new file mode 100644
index 000000000..f3e9b9323
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/build.json
@@ -0,0 +1,12 @@
+{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"]
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/package.json b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/package.json
new file mode 100644
index 000000000..33a086c66
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/package.json
@@ -0,0 +1,37 @@
+{
+  "name": "@ali/rax-app-demo",
+  "private": true,
+  "version": "1.0.0",
+  "scripts": {
+    "build": "build-scripts build",
+    "start": "build-scripts start",
+    "lint": "eslint --ext .js --ext .jsx ./"
+  },
+  "dependencies": {
+    "@ali/lowcode-datasource-engine": "*",
+    "@ali/lowcode-datasource-url-params-handler": "*",
+    "@ali/lowcode-datasource-fetch-handler": "*",
+    "@ali/lowcode-datasource-mtop-handler": "*",
+    "@ali/lowcode-datasource-mopen-handler": "*",
+    "universal-env": "^3.2.0",
+    "intl-messageformat": "^9.3.6",
+    "rax": "^1.1.0",
+    "rax-app": "^2.0.0",
+    "rax-document": "^0.1.0",
+    "rax-view": "^1.0.0",
+    "rax-text": "^1.0.0"
+  },
+  "devDependencies": {
+    "build-plugin-rax-app": "^5.0.0",
+    "@alib/build-scripts": "^0.1.0",
+    "@typescript-eslint/eslint-plugin": "^2.11.0",
+    "@typescript-eslint/parser": "^2.11.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.8.0",
+    "eslint-config-rax": "^0.1.0",
+    "eslint-plugin-import": "^2.20.0",
+    "eslint-plugin-module": "^0.1.0",
+    "eslint-plugin-react": "^7.18.0",
+    "@ali/build-plugin-rax-app-def": "^1.0.0"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.js b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.js
new file mode 100644
index 000000000..bc474c6e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.js
@@ -0,0 +1,6 @@
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+
+runApp(appConfig);
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.json b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.json
new file mode 100644
index 000000000..63dec4d7d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/app.json
@@ -0,0 +1,11 @@
+{
+  "routes": [
+    {
+      "path": "/",
+      "source": "pages/Home/index"
+    }
+  ],
+  "window": {
+    "title": "Rax App Demo"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/constants.js b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/constants.js
new file mode 100644
index 000000000..ea766c9da
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/constants.js
@@ -0,0 +1,3 @@
+const __$$constants = {};
+
+export default __$$constants;
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/document/index.jsx b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/document/index.jsx
new file mode 100644
index 000000000..50569a9b6
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/document/index.jsx
@@ -0,0 +1,25 @@
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>Rax App Demo</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/global.scss b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/global.scss
new file mode 100644
index 000000000..0d203c62a
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/global.scss
@@ -0,0 +1,3 @@
+body {
+  -webkit-font-smoothing: antialiased;
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/i18n.js b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/i18n.js
new file mode 100644
index 000000000..8f0de31e0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/i18n.js
@@ -0,0 +1,31 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+const i18nConfig = {};
+
+let locale = 'en-US';
+
+const getLocale = () => locale;
+
+const setLocale = (target) => {
+  locale = target;
+};
+
+const i18nFormat = ({ id, defaultMessage }, variables) => {
+  const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
+  if (msg == null) {
+    console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+    return `${id}`;
+  }
+
+  if (!variables || !variables.length) {
+    return msg;
+  }
+
+  return new IntlMessageFormat(msg, locale).format(variables);
+};
+
+const i18n = (id) => {
+  return i18nFormat({ id });
+};
+
+export { getLocale, setLocale, i18n, i18nFormat };
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.css b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx
new file mode 100644
index 000000000..cb5a4ddbe
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/pages/Home/index.jsx
@@ -0,0 +1,157 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import Page from 'rax-view';
+
+import Text from 'rax-text';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Home$$Page extends Component {
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <Page>
+        <Text>Hello world!</Text>
+      </Page>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Home$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/utils.js b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/utils.js
new file mode 100644
index 000000000..ff8b4c563
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/expected/demo-project/src/utils.js
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/code-generator/test-cases/rax-app/demo1/schema.json5 b/packages/code-generator/test-cases/rax-app/demo1/schema.json5
new file mode 100644
index 000000000..282f979e8
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo1/schema.json5
@@ -0,0 +1,55 @@
+{
+  // 本例是一个非常简单的 Hello world 页面
+  // Schema 参见：https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr
+  version: '1.0.0',
+  componentsMap: [
+    {
+      componentName: 'Page',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Page',
+    },
+    {
+      componentName: 'Text',
+      package: 'rax-text',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Text',
+    },
+  ],
+  componentsTree: [
+    {
+      componentName: 'Page',
+      props: {},
+      lifeCycles: {},
+      fileName: 'home',
+      meta: {
+        router: '/',
+      },
+      dataSource: {
+        list: [],
+      },
+      children: [
+        {
+          componentName: 'Text',
+          props: {},
+          children: 'Hello world!',
+        },
+      ],
+    },
+  ],
+  config: {
+    sdkVersion: '1.0.3',
+    historyMode: 'hash',
+    targetRootID: 'root',
+  },
+  meta: {
+    name: 'Rax App Demo',
+    git_group: 'demo-group',
+    project_name: 'demo-project',
+    description: '这是一个示例应用',
+    spma: 'spmademo',
+    creator: '张三',
+  },
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.editorconfig b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.editorconfig
new file mode 100644
index 000000000..5760be583
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintignore b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintignore
new file mode 100644
index 000000000..3b437e614
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintignore
@@ -0,0 +1,11 @@
+# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintrc.js b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintrc.js
new file mode 100644
index 000000000..e2a7c5b54
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ['rax'],
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.gitignore b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.gitignore
new file mode 100644
index 000000000..50a53dace
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/.gitignore
@@ -0,0 +1,17 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/README.md b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/README.md
new file mode 100644
index 000000000..6eff85d41
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/README.md
@@ -0,0 +1,15 @@
+# @ali/rax-component-demo
+
+## Getting Started
+
+### `npm run start`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/abc.json b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/abc.json
new file mode 100644
index 000000000..f9ee40f71
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/abc.json
@@ -0,0 +1,7 @@
+{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/build.json b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/build.json
new file mode 100644
index 000000000..f3e9b9323
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/build.json
@@ -0,0 +1,12 @@
+{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"]
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/package.json b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/package.json
new file mode 100644
index 000000000..aa61cda9c
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/package.json
@@ -0,0 +1,41 @@
+{
+  "name": "@ali/rax-app-demo",
+  "private": true,
+  "version": "1.0.0",
+  "scripts": {
+    "build": "build-scripts build",
+    "start": "build-scripts start",
+    "lint": "eslint --ext .js --ext .jsx ./"
+  },
+  "dependencies": {
+    "@ali/lowcode-datasource-engine": "*",
+    "@ali/lowcode-datasource-url-params-handler": "*",
+    "@ali/lowcode-datasource-fetch-handler": "*",
+    "@ali/lowcode-datasource-mtop-handler": "*",
+    "@ali/lowcode-datasource-mopen-handler": "*",
+    "universal-env": "^3.2.0",
+    "intl-messageformat": "^9.3.6",
+    "rax": "^1.1.0",
+    "rax-app": "^2.0.0",
+    "rax-document": "^0.1.0",
+    "rax-view": "^1.0.0",
+    "rax-text": "^1.0.0",
+    "rax-image": "^1.0.0",
+    "moment": "*",
+    "lodash": "*",
+    "universal-toast": "^1.2.0"
+  },
+  "devDependencies": {
+    "build-plugin-rax-app": "^5.0.0",
+    "@alib/build-scripts": "^0.1.0",
+    "@typescript-eslint/eslint-plugin": "^2.11.0",
+    "@typescript-eslint/parser": "^2.11.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.8.0",
+    "eslint-config-rax": "^0.1.0",
+    "eslint-plugin-import": "^2.20.0",
+    "eslint-plugin-module": "^0.1.0",
+    "eslint-plugin-react": "^7.18.0",
+    "@ali/build-plugin-rax-app-def": "^1.0.0"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.js b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.js
new file mode 100644
index 000000000..bc474c6e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.js
@@ -0,0 +1,6 @@
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+
+runApp(appConfig);
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.json b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.json
new file mode 100644
index 000000000..63dec4d7d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/app.json
@@ -0,0 +1,11 @@
+{
+  "routes": [
+    {
+      "path": "/",
+      "source": "pages/Home/index"
+    }
+  ],
+  "window": {
+    "title": "Rax App Demo"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/constants.js b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/constants.js
new file mode 100644
index 000000000..ea766c9da
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/constants.js
@@ -0,0 +1,3 @@
+const __$$constants = {};
+
+export default __$$constants;
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/document/index.jsx b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/document/index.jsx
new file mode 100644
index 000000000..50569a9b6
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/document/index.jsx
@@ -0,0 +1,25 @@
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>Rax App Demo</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/global.scss b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/global.scss
new file mode 100644
index 000000000..2b98f3726
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/global.scss
@@ -0,0 +1,9 @@
+body {
+  -webkit-font-smoothing: antialiased;
+}
+
+page,
+body {
+  width: 750rpx;
+  overflow-x: hidden;
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/i18n.js b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/i18n.js
new file mode 100644
index 000000000..8f0de31e0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/i18n.js
@@ -0,0 +1,31 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+const i18nConfig = {};
+
+let locale = 'en-US';
+
+const getLocale = () => locale;
+
+const setLocale = (target) => {
+  locale = target;
+};
+
+const i18nFormat = ({ id, defaultMessage }, variables) => {
+  const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
+  if (msg == null) {
+    console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+    return `${id}`;
+  }
+
+  if (!variables || !variables.length) {
+    return msg;
+  }
+
+  return new IntlMessageFormat(msg, locale).format(variables);
+};
+
+const i18n = (id) => {
+  return i18nFormat({ id });
+};
+
+export { getLocale, setLocale, i18n, i18nFormat };
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.css b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.jsx
new file mode 100644
index 000000000..5b78b28a0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/pages/Home/index.jsx
@@ -0,0 +1,340 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import View from 'rax-view';
+
+import Text from 'rax-text';
+
+import Image from 'rax-image';
+
+import { createUrlParamsHandler as __$$createUrlParamsRequestHandler } from '@ali/lowcode-datasource-url-params-handler';
+
+import { createFetchHandler as __$$createFetchRequestHandler } from '@ali/lowcode-datasource-fetch-handler';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Home$$Page extends Component {
+  state = {
+    clickCount: 0,
+    user: { name: '张三', age: 18, avatar: 'https://gw.alicdn.com/tfs/TB1Ui9BMkY2gK0jSZFgXXc5OFXa-50-50.png' },
+    orders: [
+      {
+        title: '【小米智能生活】米家扫地机器人家用全自动扫拖一体机拖地吸尘器',
+        price: 1799,
+        coverUrl: 'https://gw.alicdn.com/tfs/TB1dGVlRfb2gK0jSZK9XXaEgFXa-258-130.png',
+      },
+      {
+        title: '【限时下单立减】Apple/苹果 iPhone 11 4G全网通智能手机正品苏宁易购官方旗舰店苹果11',
+        price: 4999,
+        coverUrl: 'https://gw.alicdn.com/tfs/TB18gdJddTfau8jSZFwXXX1mVXa-1298-1202.png',
+      },
+    ],
+  };
+
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, {
+    runtimeConfig: true,
+    requestHandlersMap: {
+      urlParams: __$$createUrlParamsRequestHandler(this.props.location.search),
+      fetch: __$$createFetchRequestHandler(),
+    },
+  });
+
+  _utils = this._defineUtils();
+
+  _lifeCycles = this._defineLifeCycles();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+
+    this._lifeCycles.didMount();
+  }
+
+  componentWillUnmount() {
+    this._lifeCycles.willUnmount();
+  }
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <View>
+        <View>
+          <Text>Demo data source logic</Text>
+        </View>
+        <View>
+          <Text>=== User Info: ===</Text>
+        </View>
+        {__$$eval(() => __$$context.state.user) && (
+          <View style={{ flexDirection: 'row' }}>
+            <Image
+              source={{ uri: __$$eval(() => __$$context.state.user.avatar) }}
+              style={{ width: '32px', height: '32px' }}
+            />
+            <View onClick={__$$context.hello}>
+              <Text>{__$$eval(() => __$$context.state.user.name)}</Text>
+              <Text>{__$$eval(() => __$$context.state.user.age)}岁</Text>
+            </View>
+          </View>
+        )}
+        <View>
+          <Text>=== Orders: ===</Text>
+        </View>
+        {__$$evalArray(() => __$$context.state.orders).map((order, index) => (
+          <View
+            style={{ flexDirection: 'row' }}
+            data-order={order}
+            onClick={(...__$$args) => {
+              if (__$$isMiniApp) {
+                const __$$event = __$$args[0];
+                const order = __$$event.target.dataset.order;
+                return function () {
+                  __$$context.utils.recordEvent(`CLICK_ORDER`, order.title);
+                }.apply(this, __$$args);
+              } else {
+                return function () {
+                  __$$context.utils.recordEvent(`CLICK_ORDER`, order.title);
+                }.apply(this, __$$args);
+              }
+            }}
+          >
+            <View>
+              <Image source={{ uri: __$$eval(() => order.coverUrl) }} style={{ width: '80px', height: '60px' }} />
+            </View>
+            <View>
+              <Text>{__$$eval(() => order.title)}</Text>
+              <Text>{__$$eval(() => __$$context.utils.formatPrice(order.price, '元'))}</Text>
+            </View>
+          </View>
+        ))}
+        <View
+          onClick={function () {
+            __$$context.setState({
+              clickCount: __$$context.state.clickCount + 1,
+            });
+          }}
+        >
+          <Text>点击次数：{__$$eval(() => __$$context.state.clickCount)}(点击加 1)</Text>
+        </View>
+        <View>
+          <Text>操作提示：</Text>
+          <Text>1. 点击会员名，可以弹出 Toast "Hello xxx!"</Text>
+          <Text>2. 点击订单，会记录点击的订单信息，并弹出 Toast 提示</Text>
+          <Text>3. 最下面的【点击次数】，点一次应该加 1</Text>
+        </View>
+      </View>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return {
+      list: [
+        {
+          id: 'urlParams',
+          type: 'urlParams',
+          isInit: function () {
+            return undefined;
+          },
+          options: function () {
+            return undefined;
+          },
+        },
+        {
+          id: 'user',
+          type: 'fetch',
+          options: function () {
+            return {
+              method: 'GET',
+              uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
+              isSync: true,
+            };
+          },
+          dataHandler: function (response) {
+            if (!response.success) {
+              throw new Error(response.message);
+            }
+
+            return response.data;
+          },
+          isInit: function () {
+            return undefined;
+          },
+        },
+        {
+          id: 'orders',
+          type: 'fetch',
+          options: function () {
+            return {
+              method: 'GET',
+              uri: __$$context.state.user.ordersApiUri,
+              isSync: true,
+            };
+          },
+          dataHandler: function (response) {
+            if (!response.success) {
+              throw new Error(response.message);
+            }
+
+            return response.data.result;
+          },
+          isInit: function () {
+            return undefined;
+          },
+        },
+      ],
+      dataHandler: function (dataMap) {
+        console.info('All datasources loaded:', dataMap);
+      },
+    };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineLifeCycles() {
+    const __$$lifeCycles = {
+      didMount: function didMount() {
+        this.utils.Toast.show(`Hello ${this.state.user.name}!`);
+      },
+
+      willUnmount: function didMount() {
+        this.utils.Toast.show(`Bye, ${this.state.user.name}!`);
+      },
+    };
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$lifeCycles).forEach(([lifeCycleName, lifeCycleMethod]) => {
+      if (typeof lifeCycleMethod === 'function') {
+        __$$lifeCycles[lifeCycleName] = (...args) => {
+          return lifeCycleMethod.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$lifeCycles;
+  }
+
+  _defineMethods() {
+    const __$$methods = {
+      hello: function hello() {
+        this.utils.Toast.show(`Hello ${this.state.user.name}!`);
+        console.log(`Hello ${this.state.user.name}!`);
+      },
+    };
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Home$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/utils.js b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/utils.js
new file mode 100644
index 000000000..a9612b3d2
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/expected/demo-project/src/utils.js
@@ -0,0 +1,26 @@
+import moment from 'moment';
+
+import clone from 'lodash/clone';
+
+import Toast from 'universal-toast';
+
+const formatPrice = function formatPrice(price, unit) {
+  return Number(price).toFixed(2) + unit;
+};
+
+const recordEvent = function recordEvent(eventName, eventDetail) {
+  this.utils.Toast.show(`[EVENT]: ${eventName} ${eventDetail}`);
+  console.log(`[EVENT]: ${eventName} (detail: %o) (user: %o)`, eventDetail, this.state.user);
+};
+
+export default {
+  formatPrice,
+
+  recordEvent,
+
+  moment,
+
+  clone,
+
+  Toast,
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo2/schema.json5 b/packages/code-generator/test-cases/rax-app/demo2/schema.json5
new file mode 100644
index 000000000..a9f5813cd
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo2/schema.json5
@@ -0,0 +1,375 @@
+{
+  // 本例是一个比较复杂的，带有循环和条件渲染的，以及有各种事件处理函数的页面
+  // Schema 参见：https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr
+  version: '1.0.0',
+  componentsMap: [
+    {
+      componentName: 'View',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'View',
+    },
+    {
+      componentName: 'Text',
+      package: 'rax-text',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Text',
+    },
+    {
+      componentName: 'Image',
+      package: 'rax-image',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Image',
+    },
+    {
+      componentName: 'Page',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Page',
+    },
+  ],
+  componentsTree: [
+    {
+      componentName: 'Page',
+      fileName: 'home',
+      meta: {
+        router: '/',
+      },
+      state: {
+        clickCount: 0,
+        user: { name: '张三', age: 18, avatar: 'https://gw.alicdn.com/tfs/TB1Ui9BMkY2gK0jSZFgXXc5OFXa-50-50.png' },
+        orders: [
+          {
+            title: '【小米智能生活】米家扫地机器人家用全自动扫拖一体机拖地吸尘器',
+            price: 1799,
+            coverUrl: 'https://gw.alicdn.com/tfs/TB1dGVlRfb2gK0jSZK9XXaEgFXa-258-130.png',
+          },
+          {
+            title: '【限时下单立减】Apple/苹果 iPhone 11 4G全网通智能手机正品苏宁易购官方旗舰店苹果11',
+            price: 4999,
+            coverUrl: 'https://gw.alicdn.com/tfs/TB18gdJddTfau8jSZFwXXX1mVXa-1298-1202.png',
+          },
+        ],
+      },
+      props: {},
+      lifeCycles: {
+        didMount: {
+          type: 'JSExpression',
+          value: 'function didMount(){\n  this.utils.Toast.show(`Hello ${this.state.user.name}!`);\n}',
+        },
+        willUnmount: {
+          type: 'JSExpression',
+          value: 'function didMount(){\n  this.utils.Toast.show(`Bye, ${this.state.user.name}!`);\n}',
+        },
+      },
+      methods: {
+        hello: {
+          type: 'JSExpression',
+          value: 'function hello(){\n  this.utils.Toast.show(`Hello ${this.state.user.name}!`);\n  console.log(`Hello ${this.state.user.name}!`); }',
+        },
+      },
+      dataSource: {
+        list: [
+          {
+            id: 'urlParams',
+            type: 'urlParams',
+          },
+          // 示例数据源：https://shs.alibaba-inc.com/mock/1458/demo/user
+          {
+            id: 'user',
+            type: 'fetch',
+            options: {
+              method: 'GET',
+              uri: 'https://shs.alibaba-inc.com/mock/1458/demo/user',
+              isSync: true,
+            },
+            dataHandler: {
+              type: 'JSExpression',
+              value: 'function (response) {\nif (!response.success){\n    throw new Error(response.message);\n  }\n  return response.data;\n}',
+            },
+          },
+          // 示例数据源：https://shs.alibaba-inc.com/mock/1458/demo/orders
+          {
+            id: 'orders',
+            type: 'fetch',
+            options: {
+              method: 'GET',
+              uri: {
+                type: 'JSExpression',
+                value: 'this.state.user.ordersApiUri',
+              },
+              isSync: true,
+            },
+            dataHandler: {
+              type: 'JSExpression',
+              value: 'function (response) {\nif (!response.success){\n    throw new Error(response.message);\n  }\n  return response.data.result;\n}',
+            },
+          },
+        ],
+        dataHandler: {
+          type: 'JSExpression',
+          value: 'function (dataMap) {\n  console.info("All datasources loaded:", dataMap);\n}',
+        },
+      },
+      children: [
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              props: {},
+              children: 'Demo data source logic',
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              props: {},
+              children: '=== User Info: ===',
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          condition: {
+            type: 'JSExpression',
+            value: 'this.state.user',
+          },
+          props: {
+            style: { flexDirection: 'row' },
+          },
+          children: [
+            {
+              componentName: 'Image',
+              props: {
+                source: {
+                  uri: {
+                    type: 'JSExpression',
+                    value: 'this.state.user.avatar',
+                  },
+                },
+                style: {
+                  width: '32px',
+                  height: '32px',
+                },
+              },
+            },
+            {
+              componentName: 'View',
+              props: {
+                onClick: {
+                  type: 'JSExpression',
+                  value: 'this.hello',
+                },
+              },
+              children: [
+                {
+                  componentName: 'Text',
+                  children: {
+                    type: 'JSExpression',
+                    value: 'this.state.user.name',
+                  },
+                },
+                {
+                  componentName: 'Text',
+                  children: [
+                    {
+                      type: 'JSExpression',
+                      value: 'this.state.user.age',
+                    },
+                    '岁',
+                  ],
+                },
+              ],
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              props: {},
+              children: '=== Orders: ===',
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          loop: {
+            type: 'JSExpression',
+            value: 'this.state.orders',
+          },
+          loopArgs: ['order', 'index'],
+          props: {
+            style: { flexDirection: 'row' },
+            onClick: {
+              type: 'JSExpression',
+              value: 'function(){ this.utils.recordEvent(`CLICK_ORDER`, this.order.title) }',
+            },
+          },
+          children: [
+            {
+              componentName: 'View',
+              children: [
+                {
+                  componentName: 'Image',
+                  props: {
+                    source: {
+                      uri: {
+                        type: 'JSExpression',
+                        value: 'this.order.coverUrl',
+                      },
+                    },
+                    style: {
+                      width: '80px',
+                      height: '60px',
+                    },
+                  },
+                },
+              ],
+            },
+            {
+              componentName: 'View',
+              children: [
+                {
+                  componentName: 'Text',
+                  children: {
+                    type: 'JSExpression',
+                    value: 'this.order.title',
+                  },
+                },
+                {
+                  componentName: 'Text',
+                  children: {
+                    type: 'JSExpression',
+                    value: 'this.utils.formatPrice(this.order.price, "元")',
+                  },
+                },
+              ],
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          props: {
+            onClick: {
+              type: 'JSExpression',
+              value: 'function (){ this.setState({ clickCount: this.state.clickCount + 1 }) }',
+            },
+          },
+          children: [
+            {
+              componentName: 'Text',
+              children: [
+                '点击次数：',
+                {
+                  type: 'JSExpression',
+                  value: 'this.state.clickCount',
+                },
+                '(点击加 1)',
+              ],
+            },
+          ],
+        },
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              props: {},
+              children: '操作提示：',
+            },
+            {
+              componentName: 'Text',
+              props: {},
+              children: '1. 点击会员名，可以弹出 Toast "Hello xxx!"',
+            },
+            {
+              componentName: 'Text',
+              props: {},
+              children: '2. 点击订单，会记录点击的订单信息，并弹出 Toast 提示',
+            },
+            {
+              componentName: 'Text',
+              props: {},
+              children: '3. 最下面的【点击次数】，点一次应该加 1',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  utils: [
+    // 可以直接定义一个函数
+    {
+      name: 'formatPrice',
+      type: 'function',
+      content: {
+        type: 'JSExpression',
+        value: 'function formatPrice(price, unit) { return Number(price).toFixed(2) + unit; }',
+      },
+    },
+    // 在 utils 里面也可以用 this 访问当前上下文:
+    {
+      name: 'recordEvent',
+      type: 'function',
+      content: {
+        type: 'JSExpression',
+        value: 'function recordEvent(eventName, eventDetail) { \n  this.utils.Toast.show(`[EVENT]: ${eventName} ${eventDetail}`);\n  console.log(`[EVENT]: ${eventName} (detail: %o) (user: %o)`, eventDetail, this.state.user); }',
+      },
+    },
+    // 也可以直接从 npm 包引入 (下例等价于 `import moment from 'moment';`)
+    {
+      name: 'moment',
+      type: 'npm',
+      content: {
+        package: 'moment',
+        version: '*',
+        exportName: 'moment',
+      },
+    },
+    // 可以引入子目录（下例等价于 `import clone from 'lodash/clone';`)
+    {
+      name: 'clone',
+      type: 'npm',
+      content: {
+        package: 'lodash',
+        version: '*',
+        exportName: 'clone',
+        destructuring: false,
+        main: '/clone',
+      },
+    },
+    {
+      name: 'Toast',
+      type: 'npm',
+      content: {
+        package: 'universal-toast',
+        version: '^1.2.0',
+        exportName: 'Toast', // TODO: 这个 exportName 是否可以省略？省略后默认是上一层的 name？
+      },
+    },
+  ],
+  css: 'page,body{\n  width: 750rpx;\n  overflow-x: hidden;\n}',
+  config: {
+    sdkVersion: '1.0.3',
+    historyMode: 'hash',
+    targetRootID: 'root',
+  },
+  meta: {
+    name: 'Rax App Demo',
+    git_group: 'demo-group',
+    project_name: 'demo-project',
+    description: '这是一个示例应用',
+    spma: 'spmademo',
+    creator: '张三',
+  },
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.editorconfig b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.editorconfig
new file mode 100644
index 000000000..5760be583
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintignore b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintignore
new file mode 100644
index 000000000..3b437e614
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintignore
@@ -0,0 +1,11 @@
+# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintrc.js b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintrc.js
new file mode 100644
index 000000000..e2a7c5b54
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ['rax'],
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.gitignore b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.gitignore
new file mode 100644
index 000000000..50a53dace
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/.gitignore
@@ -0,0 +1,17 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/README.md b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/README.md
new file mode 100644
index 000000000..6eff85d41
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/README.md
@@ -0,0 +1,15 @@
+# @ali/rax-component-demo
+
+## Getting Started
+
+### `npm run start`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/abc.json b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/abc.json
new file mode 100644
index 000000000..f9ee40f71
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/abc.json
@@ -0,0 +1,7 @@
+{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/build.json b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/build.json
new file mode 100644
index 000000000..f3e9b9323
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/build.json
@@ -0,0 +1,12 @@
+{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"]
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/package.json b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/package.json
new file mode 100644
index 000000000..f9451df10
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "@ali/rax-app-demo",
+  "private": true,
+  "version": "1.0.0",
+  "scripts": {
+    "build": "build-scripts build",
+    "start": "build-scripts start",
+    "lint": "eslint --ext .js --ext .jsx ./"
+  },
+  "dependencies": {
+    "@ali/lowcode-datasource-engine": "*",
+    "@ali/lowcode-datasource-url-params-handler": "*",
+    "@ali/lowcode-datasource-fetch-handler": "*",
+    "@ali/lowcode-datasource-mtop-handler": "*",
+    "@ali/lowcode-datasource-mopen-handler": "*",
+    "universal-env": "^3.2.0",
+    "intl-messageformat": "^9.3.6",
+    "rax": "^1.1.0",
+    "rax-app": "^2.0.0",
+    "rax-document": "^0.1.0",
+    "rax-view": "^1.0.0",
+    "rax-text": "^1.0.0",
+    "rax-link": "^1.0.0",
+    "rax-image": "^1.0.0"
+  },
+  "devDependencies": {
+    "build-plugin-rax-app": "^5.0.0",
+    "@alib/build-scripts": "^0.1.0",
+    "@typescript-eslint/eslint-plugin": "^2.11.0",
+    "@typescript-eslint/parser": "^2.11.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.8.0",
+    "eslint-config-rax": "^0.1.0",
+    "eslint-plugin-import": "^2.20.0",
+    "eslint-plugin-module": "^0.1.0",
+    "eslint-plugin-react": "^7.18.0",
+    "@ali/build-plugin-rax-app-def": "^1.0.0"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.js b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.js
new file mode 100644
index 000000000..bc474c6e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.js
@@ -0,0 +1,6 @@
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+
+runApp(appConfig);
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.json b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.json
new file mode 100644
index 000000000..5082c4f9d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/app.json
@@ -0,0 +1,19 @@
+{
+  "routes": [
+    {
+      "path": "/",
+      "source": "pages/Home/index"
+    },
+    {
+      "path": "/list",
+      "source": "pages/List/index"
+    },
+    {
+      "path": "/detail",
+      "source": "pages/Detail/index"
+    }
+  ],
+  "window": {
+    "title": "Rax App Demo"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/constants.js b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/constants.js
new file mode 100644
index 000000000..ea766c9da
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/constants.js
@@ -0,0 +1,3 @@
+const __$$constants = {};
+
+export default __$$constants;
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/document/index.jsx b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/document/index.jsx
new file mode 100644
index 000000000..50569a9b6
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/document/index.jsx
@@ -0,0 +1,25 @@
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>Rax App Demo</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/global.scss b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/global.scss
new file mode 100644
index 000000000..2b98f3726
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/global.scss
@@ -0,0 +1,9 @@
+body {
+  -webkit-font-smoothing: antialiased;
+}
+
+page,
+body {
+  width: 750rpx;
+  overflow-x: hidden;
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/i18n.js b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/i18n.js
new file mode 100644
index 000000000..8f0de31e0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/i18n.js
@@ -0,0 +1,31 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+const i18nConfig = {};
+
+let locale = 'en-US';
+
+const getLocale = () => locale;
+
+const setLocale = (target) => {
+  locale = target;
+};
+
+const i18nFormat = ({ id, defaultMessage }, variables) => {
+  const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
+  if (msg == null) {
+    console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+    return `${id}`;
+  }
+
+  if (!variables || !variables.length) {
+    return msg;
+  }
+
+  return new IntlMessageFormat(msg, locale).format(variables);
+};
+
+const i18n = (id) => {
+  return i18nFormat({ id });
+};
+
+export { getLocale, setLocale, i18n, i18nFormat };
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.css b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.jsx b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.jsx
new file mode 100644
index 000000000..91dbd2d75
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Detail/index.jsx
@@ -0,0 +1,168 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import View from 'rax-view';
+
+import Text from 'rax-text';
+
+import Link from 'rax-link';
+
+import Image from 'rax-image';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Detail$$Page extends Component {
+  state = {};
+
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <View>
+        <View>
+          <Text>This is the Detail Page</Text>
+        </View>
+        <Link href="javascript:history.back();" miniappHref="navigateBack:">
+          <Text>Go back</Text>
+        </Link>
+      </View>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Detail$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.css b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.jsx
new file mode 100644
index 000000000..d1d93e306
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/Home/index.jsx
@@ -0,0 +1,168 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import View from 'rax-view';
+
+import Text from 'rax-text';
+
+import Link from 'rax-link';
+
+import Image from 'rax-image';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Home$$Page extends Component {
+  state = {};
+
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <View>
+        <View>
+          <Text>This is the Home Page</Text>
+        </View>
+        <Link href="#/list" miniappHref="navigate:/pages/List/index">
+          <Text>Go To The List Page</Text>
+        </Link>
+      </View>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Home$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.css b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.jsx b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.jsx
new file mode 100644
index 000000000..9c14cc6e5
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/pages/List/index.jsx
@@ -0,0 +1,171 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import View from 'rax-view';
+
+import Text from 'rax-text';
+
+import Link from 'rax-link';
+
+import Image from 'rax-image';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class List$$Page extends Component {
+  state = {};
+
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <View>
+        <View>
+          <Text>This is the List Page</Text>
+        </View>
+        <Link href="#/detail" miniappHref="navigate:/pages/Detail/index">
+          <Text>Go To The Detail Page</Text>
+        </Link>
+        <Link href="javascript:history.back();" miniappHref="navigateBack:">
+          <Text>Go back</Text>
+        </Link>
+      </View>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(List$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/utils.js b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/utils.js
new file mode 100644
index 000000000..ff8b4c563
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/expected/demo-project/src/utils.js
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/code-generator/test-cases/rax-app/demo3/schema.json5 b/packages/code-generator/test-cases/rax-app/demo3/schema.json5
new file mode 100644
index 000000000..5652b1db1
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo3/schema.json5
@@ -0,0 +1,176 @@
+{
+  // 本例是一个路由测试页面，里面有几个页面，相互之间有跳转关系的
+  // Schema 参见：https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr
+  version: '1.0.0',
+  componentsMap: [
+    {
+      componentName: 'View',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'View',
+    },
+    {
+      componentName: 'Text',
+      package: 'rax-text',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Text',
+    },
+    {
+      componentName: 'Link',
+      package: 'rax-link',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Link',
+    },
+    {
+      componentName: 'Image',
+      package: 'rax-image',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Image',
+    },
+    {
+      componentName: 'Page',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Page',
+    },
+  ],
+  componentsTree: [
+    {
+      componentName: 'Page',
+      fileName: 'home',
+      state: {},
+      dataSource: {
+        list: [],
+      },
+      meta: {
+        router: '/',
+      },
+      children: [
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              children: 'This is the Home Page',
+            },
+          ],
+        },
+        {
+          componentName: 'Link',
+          props: {
+            href: '#/list',
+            miniappHref: 'navigate:/pages/List/index',
+          },
+          children: [
+            {
+              componentName: 'Text',
+              children: 'Go To The List Page',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      componentName: 'Page',
+      fileName: 'list',
+      state: {},
+      dataSource: {
+        list: [],
+      },
+      meta: {
+        router: '/list',
+      },
+      children: [
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              children: 'This is the List Page',
+            },
+          ],
+        },
+        {
+          componentName: 'Link',
+          props: {
+            href: '#/detail',
+            miniappHref: 'navigate:/pages/Detail/index',
+          },
+          children: [
+            {
+              componentName: 'Text',
+              children: 'Go To The Detail Page',
+            },
+          ],
+        },
+        {
+          componentName: 'Link',
+          props: {
+            href: 'javascript:history.back();',
+            miniappHref: 'navigateBack:',
+          },
+          children: [
+            {
+              componentName: 'Text',
+              children: 'Go back',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      componentName: 'Page',
+      fileName: 'detail',
+      state: {},
+      dataSource: {
+        list: [],
+      },
+      meta: {
+        router: '/detail',
+      },
+      children: [
+        {
+          componentName: 'View',
+          children: [
+            {
+              componentName: 'Text',
+              children: 'This is the Detail Page',
+            },
+          ],
+        },
+        {
+          componentName: 'Link',
+          props: {
+            href: 'javascript:history.back();',
+            miniappHref: 'navigateBack:',
+          },
+          children: [
+            {
+              componentName: 'Text',
+              children: 'Go back',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  css: 'page,body{\n  width: 750rpx;\n  overflow-x: hidden;\n}',
+  config: {
+    sdkVersion: '1.0.3',
+    historyMode: 'hash',
+    targetRootID: 'root',
+  },
+  meta: {
+    name: 'Rax App Demo',
+    git_group: 'demo-group',
+    project_name: 'demo-project',
+    description: '这是一个示例应用',
+    spma: 'spmademo',
+    creator: '张三',
+  },
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/README.md b/packages/code-generator/test-cases/rax-app/demo4/README.md
new file mode 100644
index 000000000..b6613c4d3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/README.md
@@ -0,0 +1 @@
+# 这个 demo 是用来演示运行时的方案的。
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.editorconfig b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.editorconfig
new file mode 100644
index 000000000..5760be583
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintignore b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintignore
new file mode 100644
index 000000000..3b437e614
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintignore
@@ -0,0 +1,11 @@
+# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintrc.js b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintrc.js
new file mode 100644
index 000000000..e2a7c5b54
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ['rax'],
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore
new file mode 100644
index 000000000..50a53dace
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/.gitignore
@@ -0,0 +1,17 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/README.md b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/README.md
new file mode 100644
index 000000000..6eff85d41
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/README.md
@@ -0,0 +1,15 @@
+# @ali/rax-component-demo
+
+## Getting Started
+
+### `npm run start`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/abc.json b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/abc.json
new file mode 100644
index 000000000..f9ee40f71
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/abc.json
@@ -0,0 +1,7 @@
+{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/build.json b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/build.json
new file mode 100644
index 000000000..69a413ad0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/build.json
@@ -0,0 +1,15 @@
+{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"],
+        "miniapp": {
+          "buildType": "runtime"
+        }
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/package.json b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/package.json
new file mode 100644
index 000000000..c7a658230
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "@ali/rax-app-demo",
+  "private": true,
+  "version": "1.0.0",
+  "scripts": {
+    "build": "build-scripts build",
+    "start": "build-scripts start",
+    "lint": "eslint --ext .js --ext .jsx ./"
+  },
+  "dependencies": {
+    "@ali/lowcode-datasource-engine": "*",
+    "@ali/lowcode-datasource-url-params-handler": "*",
+    "@ali/lowcode-datasource-fetch-handler": "*",
+    "@ali/lowcode-datasource-mtop-handler": "*",
+    "@ali/lowcode-datasource-mopen-handler": "*",
+    "universal-env": "^3.2.0",
+    "intl-messageformat": "^9.3.6",
+    "rax": "^1.1.0",
+    "rax-app": "^2.0.0",
+    "rax-document": "^0.1.0",
+    "@alife/right-design-card": "*",
+    "rax-view": "^1.0.0",
+    "rax-text": "^1.0.0",
+    "rax-image": "^1.0.0"
+  },
+  "devDependencies": {
+    "build-plugin-rax-app": "^5.0.0",
+    "@alib/build-scripts": "^0.1.0",
+    "@typescript-eslint/eslint-plugin": "^2.11.0",
+    "@typescript-eslint/parser": "^2.11.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.8.0",
+    "eslint-config-rax": "^0.1.0",
+    "eslint-plugin-import": "^2.20.0",
+    "eslint-plugin-module": "^0.1.0",
+    "eslint-plugin-react": "^7.18.0",
+    "@ali/build-plugin-rax-app-def": "^1.0.0"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.js b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.js
new file mode 100644
index 000000000..bc474c6e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.js
@@ -0,0 +1,6 @@
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+
+runApp(appConfig);
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.json b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.json
new file mode 100644
index 000000000..63dec4d7d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/app.json
@@ -0,0 +1,11 @@
+{
+  "routes": [
+    {
+      "path": "/",
+      "source": "pages/Home/index"
+    }
+  ],
+  "window": {
+    "title": "Rax App Demo"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/constants.js b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/constants.js
new file mode 100644
index 000000000..ea766c9da
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/constants.js
@@ -0,0 +1,3 @@
+const __$$constants = {};
+
+export default __$$constants;
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/document/index.jsx b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/document/index.jsx
new file mode 100644
index 000000000..50569a9b6
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/document/index.jsx
@@ -0,0 +1,25 @@
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>Rax App Demo</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/global.scss b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/global.scss
new file mode 100644
index 000000000..2b98f3726
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/global.scss
@@ -0,0 +1,9 @@
+body {
+  -webkit-font-smoothing: antialiased;
+}
+
+page,
+body {
+  width: 750rpx;
+  overflow-x: hidden;
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/i18n.js b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/i18n.js
new file mode 100644
index 000000000..8f0de31e0
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/i18n.js
@@ -0,0 +1,31 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+const i18nConfig = {};
+
+let locale = 'en-US';
+
+const getLocale = () => locale;
+
+const setLocale = (target) => {
+  locale = target;
+};
+
+const i18nFormat = ({ id, defaultMessage }, variables) => {
+  const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
+  if (msg == null) {
+    console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+    return `${id}`;
+  }
+
+  if (!variables || !variables.length) {
+    return msg;
+  }
+
+  return new IntlMessageFormat(msg, locale).format(variables);
+};
+
+const i18n = (id) => {
+  return i18nFormat({ id });
+};
+
+export { getLocale, setLocale, i18n, i18nFormat };
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.css b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.jsx
new file mode 100644
index 000000000..6b550a1e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/pages/Home/index.jsx
@@ -0,0 +1,165 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import Card from '@alife/right-design-card';
+
+import View from 'rax-view';
+
+import Text from 'rax-text';
+
+import Image from 'rax-image';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Home$$Page extends Component {
+  state = {};
+
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <View>
+        <Card>
+          <Text>This is a demo card.</Text>
+        </Card>
+      </View>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Home$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/utils.js b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/utils.js
new file mode 100644
index 000000000..ff8b4c563
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/expected/demo-project/src/utils.js
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/code-generator/test-cases/rax-app/demo4/schema.json5 b/packages/code-generator/test-cases/rax-app/demo4/schema.json5
new file mode 100644
index 000000000..efa43c840
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo4/schema.json5
@@ -0,0 +1,85 @@
+{
+  // 本例是为了测试一下小程序的 runtime 模式
+  version: '1.0.0',
+  componentsMap: [
+    {
+      componentName: 'Card',
+      package: '@alife/right-design-card',
+      version: '*',
+      destructuring: false,
+      exportName: 'Card',
+    },
+    {
+      componentName: 'View',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'View',
+    },
+    {
+      componentName: 'Text',
+      package: 'rax-text',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Text',
+    },
+    {
+      componentName: 'Image',
+      package: 'rax-image',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Image',
+    },
+    {
+      componentName: 'Page',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Page',
+    },
+  ],
+  componentsTree: [
+    {
+      componentName: 'Page',
+      fileName: 'home',
+      meta: {
+        router: '/',
+      },
+      state: {},
+      props: {},
+      lifeCycles: {},
+      methods: {},
+      dataSource: {
+        list: [],
+      },
+      children: [
+        {
+          componentName: 'Card',
+          children: [
+            {
+              componentName: 'Text',
+              props: {},
+              children: 'This is a demo card.',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  utils: [],
+  css: 'page,body{\n  width: 750rpx;\n  overflow-x: hidden;\n}',
+  config: {
+    sdkVersion: '1.0.3',
+    historyMode: 'hash',
+    targetRootID: 'root',
+    miniAppBuildType: 'runtime',
+  },
+  meta: {
+    name: 'Rax App Demo',
+    git_group: 'demo-group',
+    project_name: 'demo-project',
+    description: '这是一个示例应用',
+    spma: 'spmademo',
+    creator: '张三',
+  },
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.editorconfig b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.editorconfig
new file mode 100644
index 000000000..5760be583
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintignore b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintignore
new file mode 100644
index 000000000..3b437e614
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintignore
@@ -0,0 +1,11 @@
+# 忽略目录
+build/
+tests/
+demo/
+
+# node 覆盖率文件
+coverage/
+
+# 忽略文件
+**/*-min.js
+**/*.min.js
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintrc.js b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintrc.js
new file mode 100644
index 000000000..e2a7c5b54
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ['rax'],
+};
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.gitignore b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.gitignore
new file mode 100644
index 000000000..50a53dace
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/.gitignore
@@ -0,0 +1,17 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+*~
+*.swp
+*.log
+
+.DS_Store
+.idea/
+.temp/
+
+build/
+dist/
+lib/
+coverage/
+node_modules/
+
+template.yml
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/README.md b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/README.md
new file mode 100644
index 000000000..6eff85d41
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/README.md
@@ -0,0 +1,15 @@
+# @ali/rax-component-demo
+
+## Getting Started
+
+### `npm run start`
+
+Runs the app in development mode.
+
+Open [http://localhost:9999](http://localhost:9999) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/abc.json b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/abc.json
new file mode 100644
index 000000000..f9ee40f71
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/abc.json
@@ -0,0 +1,7 @@
+{
+  "type": "rax",
+  "builder": "@ali/builder-rax-v1",
+  "info": {
+    "raxVersion": "1.x"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/build.json b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/build.json
new file mode 100644
index 000000000..f3e9b9323
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/build.json
@@ -0,0 +1,12 @@
+{
+  "inlineStyle": false,
+  "plugins": [
+    [
+      "build-plugin-rax-app",
+      {
+        "targets": ["web", "miniapp"]
+      }
+    ],
+    "@ali/build-plugin-rax-app-def"
+  ]
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/package.json b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/package.json
new file mode 100644
index 000000000..33a086c66
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/package.json
@@ -0,0 +1,37 @@
+{
+  "name": "@ali/rax-app-demo",
+  "private": true,
+  "version": "1.0.0",
+  "scripts": {
+    "build": "build-scripts build",
+    "start": "build-scripts start",
+    "lint": "eslint --ext .js --ext .jsx ./"
+  },
+  "dependencies": {
+    "@ali/lowcode-datasource-engine": "*",
+    "@ali/lowcode-datasource-url-params-handler": "*",
+    "@ali/lowcode-datasource-fetch-handler": "*",
+    "@ali/lowcode-datasource-mtop-handler": "*",
+    "@ali/lowcode-datasource-mopen-handler": "*",
+    "universal-env": "^3.2.0",
+    "intl-messageformat": "^9.3.6",
+    "rax": "^1.1.0",
+    "rax-app": "^2.0.0",
+    "rax-document": "^0.1.0",
+    "rax-view": "^1.0.0",
+    "rax-text": "^1.0.0"
+  },
+  "devDependencies": {
+    "build-plugin-rax-app": "^5.0.0",
+    "@alib/build-scripts": "^0.1.0",
+    "@typescript-eslint/eslint-plugin": "^2.11.0",
+    "@typescript-eslint/parser": "^2.11.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.8.0",
+    "eslint-config-rax": "^0.1.0",
+    "eslint-plugin-import": "^2.20.0",
+    "eslint-plugin-module": "^0.1.0",
+    "eslint-plugin-react": "^7.18.0",
+    "@ali/build-plugin-rax-app-def": "^1.0.0"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.js b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.js
new file mode 100644
index 000000000..bc474c6e3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.js
@@ -0,0 +1,6 @@
+import { runApp } from 'rax-app';
+import appConfig from './app.json';
+
+import './global.scss';
+
+runApp(appConfig);
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.json b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.json
new file mode 100644
index 000000000..63dec4d7d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/app.json
@@ -0,0 +1,11 @@
+{
+  "routes": [
+    {
+      "path": "/",
+      "source": "pages/Home/index"
+    }
+  ],
+  "window": {
+    "title": "Rax App Demo"
+  }
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/constants.js b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/constants.js
new file mode 100644
index 000000000..ea766c9da
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/constants.js
@@ -0,0 +1,3 @@
+const __$$constants = {};
+
+export default __$$constants;
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/document/index.jsx b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/document/index.jsx
new file mode 100644
index 000000000..50569a9b6
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/document/index.jsx
@@ -0,0 +1,25 @@
+import { createElement } from 'rax';
+import { Root, Style, Script } from 'rax-document';
+
+function Document() {
+  return (
+    <html>
+      <head>
+        <meta charset="utf-8" />
+        <meta
+          name="viewport"
+          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
+        />
+        <title>Rax App Demo</title>
+        <Style />
+      </head>
+      <body>
+        {/* root container */}
+        <Root />
+        <Script />
+      </body>
+    </html>
+  );
+}
+
+export default Document;
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/global.scss b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/global.scss
new file mode 100644
index 000000000..0d203c62a
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/global.scss
@@ -0,0 +1,3 @@
+body {
+  -webkit-font-smoothing: antialiased;
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/i18n.js b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/i18n.js
new file mode 100644
index 000000000..c3e7c955d
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/i18n.js
@@ -0,0 +1,38 @@
+import IntlMessageFormat from 'intl-messageformat';
+
+const i18nConfig = {
+  'zh-CN': {
+    'hello-world': '你好，世界！',
+  },
+  'en-US': {
+    'hello-world': 'Hello world!',
+  },
+};
+
+let locale = 'en-US';
+
+const getLocale = () => locale;
+
+const setLocale = (target) => {
+  locale = target;
+};
+
+const i18nFormat = ({ id, defaultMessage }, variables) => {
+  const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
+  if (msg == null) {
+    console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
+    return `${id}`;
+  }
+
+  if (!variables || !variables.length) {
+    return msg;
+  }
+
+  return new IntlMessageFormat(msg, locale).format(variables);
+};
+
+const i18n = (id) => {
+  return i18nFormat({ id });
+};
+
+export { getLocale, setLocale, i18n, i18nFormat };
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.css b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.jsx b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.jsx
new file mode 100644
index 000000000..d7885feb3
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/pages/Home/index.jsx
@@ -0,0 +1,163 @@
+// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头，禁止在搭建的代码中直接访问。
+// 例外：rax 框架的导出名和各种组件名除外。
+import { createElement, Component } from 'rax';
+import { withRouter as __$$withRouter } from 'rax-app';
+
+import Page from 'rax-view';
+
+import Text from 'rax-text';
+
+import { create as __$$createDataSourceEngine } from '@ali/lowcode-datasource-engine/runtime';
+
+import { isMiniApp as __$$isMiniApp } from 'universal-env';
+
+import __$$constants from '../../constants';
+
+import * as __$$i18n from '../../i18n';
+
+import __$$projectUtils from '../../utils';
+
+import './index.css';
+
+class Home$$Page extends Component {
+  _methods = this._defineMethods();
+
+  _context = this._createContext();
+
+  _dataSourceConfig = this._defineDataSourceConfig();
+  _dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this._context, { runtimeConfig: true });
+
+  _utils = this._defineUtils();
+
+  componentDidMount() {
+    this._dataSourceEngine.reloadDataSource();
+  }
+
+  componentWillUnmount() {}
+
+  render() {
+    const __$$context = this._context;
+    const {
+      state,
+      setState,
+      dataSourceMap,
+      reloadDataSource,
+      utils,
+      constants,
+      i18n,
+      i18nFormat,
+      getLocale,
+      setLocale,
+    } = __$$context;
+
+    return (
+      <Page>
+        <Text
+          onClick={function () {
+            __$$context.setLocale(__$$context.getLocale() === 'en-US' ? 'zh-CN' : 'en-US');
+          }}
+        >
+          {__$$eval(() => __$$context.i18n['hello-world'])}
+        </Text>
+      </Page>
+    );
+  }
+
+  _createContext() {
+    const self = this;
+
+    // 保存下最新的状态，这样 setState 可以搞成同步一样的了
+    self._latestState = self.state;
+
+    const context = {
+      get state() {
+        // 这里直接获取最新的 state，从而能避免一些 React/Rax 这样的框架因为异步 setState 而导致的一些问题
+        return self._latestState;
+      },
+      setState(newState) {
+        self._latestState = { ...self._latestState, ...newState };
+        self.setState(newState);
+      },
+      get dataSourceMap() {
+        return self._dataSourceEngine.dataSourceMap || {};
+      },
+      async reloadDataSource() {
+        await self._dataSourceEngine.reloadDataSource();
+      },
+      get utils() {
+        return self._utils;
+      },
+      get page() {
+        return context;
+      },
+      get component() {
+        return context;
+      },
+      get props() {
+        return self.props;
+      },
+      get constants() {
+        return __$$constants;
+      },
+      i18n: __$$i18n.i18n,
+      i18nFormat: __$$i18n.i18nFormat,
+      getLocale: __$$i18n.getLocale,
+      setLocale(locale) {
+        __$$i18n.setLocale(locale);
+        self.forceUpdate();
+      },
+      ...this._methods,
+    };
+
+    return context;
+  }
+
+  _defineDataSourceConfig() {
+    const __$$context = this._context;
+    return { list: [] };
+  }
+
+  _defineUtils() {
+    const utils = {
+      ...__$$projectUtils,
+    };
+
+    Object.entries(utils).forEach(([name, util]) => {
+      if (typeof util === 'function') {
+        utils[name] = util.bind(this._context);
+      }
+    });
+
+    return utils;
+  }
+
+  _defineMethods() {
+    const __$$methods = {};
+
+    // 为所有的方法绑定上下文
+    Object.entries(__$$methods).forEach(([methodName, method]) => {
+      if (typeof method === 'function') {
+        __$$methods[methodName] = (...args) => {
+          return method.apply(this._context, args);
+        };
+      }
+    });
+
+    return __$$methods;
+  }
+}
+
+export default __$$withRouter(Home$$Page);
+
+function __$$eval(expr) {
+  try {
+    return expr();
+  } catch (err) {
+    console.warn('Failed to evaluate: ', expr, err);
+  }
+}
+
+function __$$evalArray(expr) {
+  const res = __$$eval(expr);
+  return Array.isArray(res) ? res : [];
+}
diff --git a/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/utils.js b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/utils.js
new file mode 100644
index 000000000..ff8b4c563
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/expected/demo-project/src/utils.js
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/code-generator/test-cases/rax-app/demo5/schema.json5 b/packages/code-generator/test-cases/rax-app/demo5/schema.json5
new file mode 100644
index 000000000..3c767dfd9
--- /dev/null
+++ b/packages/code-generator/test-cases/rax-app/demo5/schema.json5
@@ -0,0 +1,73 @@
+{
+  // 这是一个关于国际化的 schema 示例
+  // Schema 参见：https://yuque.antfin-inc.com/mo/spec/spec-materials#eNCJr
+  version: '1.0.0',
+  componentsMap: [
+    {
+      componentName: 'Page',
+      package: 'rax-view',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Page',
+    },
+    {
+      componentName: 'Text',
+      package: 'rax-text',
+      version: '^1.0.0',
+      destructuring: false,
+      exportName: 'Text',
+    },
+  ],
+  componentsTree: [
+    {
+      componentName: 'Page',
+      props: {},
+      lifeCycles: {},
+      fileName: 'home',
+      meta: {
+        router: '/',
+      },
+      dataSource: {
+        list: [],
+      },
+      children: [
+        {
+          componentName: 'Text',
+          props: {
+            onClick: {
+              type: 'JSFunction',
+              value: "function () {\n  this.setLocale(this.getLocale() === 'en-US' ? 'zh-CN' : 'en-US');\n}",
+            },
+          },
+          children: [
+            {
+              type: 'JSExpression',
+              value: 'this.i18n["hello-world"]',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  i18n: {
+    'zh-CN': {
+      'hello-world': '你好，世界！',
+    },
+    'en-US': {
+      'hello-world': 'Hello world!',
+    },
+  },
+  config: {
+    sdkVersion: '1.0.3',
+    historyMode: 'hash',
+    targetRootID: 'root',
+  },
+  meta: {
+    name: 'Rax App Demo',
+    git_group: 'demo-group',
+    project_name: 'demo-project',
+    description: '这是一个示例应用',
+    spma: 'spmademo',
+    creator: '张三',
+  },
+}
diff --git a/packages/code-generator/test/rax-app.test.ts b/packages/code-generator/test/rax-app.test.ts
new file mode 100644
index 000000000..c7ce4c5c8
--- /dev/null
+++ b/packages/code-generator/test/rax-app.test.ts
@@ -0,0 +1,118 @@
+import test from 'ava';
+import { spawnSync } from 'child_process';
+import fs from 'fs';
+import glob from 'glob';
+import JSON from 'json5';
+import path from 'path';
+import chalk from 'chalk';
+import type { ProjectSchema } from '@ali/lowcode-types';
+
+import CodeGenerator from '../src';
+
+const TEST_CASES_DIR = path.join(__dirname, '../test-cases/rax-app');
+
+getSubDirectoriesSync(TEST_CASES_DIR).forEach(defineTest);
+
+function defineTest(caseDirName: string) {
+  test(`rax-app ${caseDirName} should works`, async (t) => {
+    const caseFullDir = path.join(TEST_CASES_DIR, caseDirName);
+    const schema = JSON.parse(fs.readFileSync(path.join(caseFullDir, 'schema.json5'), 'utf-8'));
+    const actualDir = path.join(caseFullDir, 'actual');
+
+    removeActualDirRecursiveSync(actualDir, caseFullDir);
+
+    await exportProject(schema, actualDir, 'demo-project');
+
+    const actualFiles = glob.sync('**/*.{js,jsx,json,ts,tsx,less,css,scss,sass}', { cwd: actualDir });
+
+    t.true(actualFiles.length > 0);
+
+    runPrettierSync(actualFiles, actualDir);
+
+    const differences = diffActualAndExpectedSync(caseFullDir);
+    if (differences) {
+      t.fail(differences);
+    }
+  });
+}
+
+async function exportProject(schemaJson: ProjectSchema, targetPath: string, projectName: string) {
+  const raxAppBuilder = CodeGenerator.solutions.rax();
+  const result = await raxAppBuilder.generateProject(schemaJson);
+  const publisher = CodeGenerator.publishers.disk();
+  await publisher.publish({
+    project: result,
+    outputPath: targetPath,
+    projectSlug: projectName,
+    createProjectFolder: true,
+  });
+}
+
+function removeActualDirRecursiveSync(actualDir: string, caseFullDir: string) {
+  ensureShellExec('rm', ['-rf', actualDir], { cwd: caseFullDir });
+}
+
+function runPrettierSync(files: string[], cwd: string) {
+  ensureShellExec('npx', ['prettier', '--write', ...files], { cwd });
+}
+
+function diffActualAndExpectedSync(caseFullDir: string): string {
+  const res = spawnSync('diff', ['-wBur', 'expected', 'actual'], {
+    cwd: caseFullDir,
+    stdio: 'pipe',
+    shell: true,
+    encoding: 'utf-8',
+  });
+
+  return colorizeDiffOutput(res.stdout);
+}
+
+function ensureShellExec(
+  shellCmd: string,
+  args: string[],
+  { cwd = process.cwd() }: { cwd?: string } = {},
+): { stdout: string; stderr: string } {
+  const res = spawnSync(shellCmd, args, {
+    stdio: 'pipe',
+    shell: true,
+    cwd,
+    encoding: 'utf-8',
+  });
+
+  if (res.status !== 0) {
+    throw new Error(
+      `Shell command "${shellCmd} ${args.slice(0, 2).join(' ')}..." failed with status: ${
+        res.status
+      } (Full command: "${shellCmd} ${args.join(' ')}" )`,
+    );
+  }
+
+  return res;
+}
+
+function colorizeDiffOutput(output: string): string {
+  if (!output) {
+    return output;
+  }
+
+  return output
+    .split('\n')
+    .map((line) => {
+      if (/^Only/i.test(line)) {
+        return chalk.red(line);
+      } else if (line[0] === '+') {
+        return chalk.yellow(line);
+      } else if (line[0] === '-') {
+        return chalk.red(line);
+      } else {
+        return line;
+      }
+    })
+    .join('\n');
+}
+
+function getSubDirectoriesSync(baseDir: string) {
+  return fs
+    .readdirSync(baseDir)
+    .filter((dirOrFileName: string) => fs.statSync(path.join(baseDir, dirOrFileName)).isDirectory());
+}
diff --git a/packages/code-generator/test/utils/expressionParser/parseExpressionConvertThis2Context.test.ts b/packages/code-generator/test/utils/expressionParser/parseExpressionConvertThis2Context.test.ts
new file mode 100644
index 000000000..19c2b9621
--- /dev/null
+++ b/packages/code-generator/test/utils/expressionParser/parseExpressionConvertThis2Context.test.ts
@@ -0,0 +1,79 @@
+import test from 'ava';
+import type { ExecutionContext, Macro } from 'ava';
+import { parseExpressionConvertThis2Context } from '../../../src/utils/expressionParser';
+
+const macro: Macro<any[]> = (
+  t: ExecutionContext<Record<string, unknown>>,
+  input: [string, string, string[]],
+  expected: string,
+  error?: { message: RegExp },
+) => {
+  if (!error) {
+    t.deepEqual(parseExpressionConvertThis2Context(input[0], input[1], input[2]), expected);
+  } else {
+    t.throws(() => {
+      t.deepEqual(parseExpressionConvertThis2Context(input[0], input[1], input[2]), expected);
+    }, error.message);
+  }
+};
+
+macro.title = (providedTitle: string | undefined, ...args: any[]): string => {
+  const [input, expected] = args;
+  return providedTitle || `after convert this to context "${input[0]}" should be "${expected}"`.replace(/\n|\s+/g, ' ');
+};
+
+test(macro, ['this.hello', '__$$context', []], '__$$context.hello');
+test(macro, ['this.utils.recordEvent', '__$$context', []], '__$$context.utils.recordEvent');
+
+test(
+  macro,
+  ['this.utils.recordEvent.bind(this)', '__$$context', []],
+  '__$$context.utils.recordEvent.bind(__$$context)',
+);
+
+test(macro, ['this.item', '__$$context', ['item']], 'item');
+
+test(macro, ['this.user.name', '__$$context', ['user']], 'user.name');
+
+test(macro, ['function (){}', '__$$context', []], 'function () {}');
+
+test(
+  macro,
+  ['function (){ this.utils.Toast.show("Hello world!") }', '__$$context'],
+  'function () {\n  __$$context.utils.Toast.show("Hello world!");\n}',
+);
+
+// 变量能被替换掉
+test(
+  macro,
+  ['function (){ this.utils.recordEvent("click", this.item) }', '__$$context', ['item']],
+  'function () {\n  __$$context.utils.recordEvent("click", item);\n}',
+);
+
+// 只替换顶层的，不替换内层
+test(
+  macro,
+  ['function (){ return function (){ this.utils.recordEvent("click", this.item) } }', '__$$context', ['item']],
+  'function () {\n  return function () {\n    this.utils.recordEvent("click", item);\n  };\n}',
+);
+
+// 只替换顶层的，不替换内层
+test(
+  macro,
+  ['function onClick(){ return function (){ this.utils.recordEvent("click", this.item) } }', '__$$context', ['item']],
+  'function onClick() {\n  return function () {\n    this.utils.recordEvent("click", item);\n  };\n}',
+);
+
+// 只替换顶层的，不替换内层
+test(
+  macro,
+  ['() => { return function (){ this.utils.recordEvent("click", this.item) } }', '__$$context', ['item']],
+  '() => {\n  return function () {\n    this.utils.recordEvent("click", item);\n  };\n}',
+);
+
+// 但是若内层有用箭头函数定义的则还是要替换下
+test(
+  macro,
+  ['() => { return () => { this.utils.recordEvent("click", this.item) } }', '__$$context', ['item']],
+  '() => {\n  return () => {\n    __$$context.utils.recordEvent("click", item);\n  };\n}',
+);
diff --git a/packages/code-generator/test/utils/expressionParser/parseExpressionGetGlobalVariables.test.ts b/packages/code-generator/test/utils/expressionParser/parseExpressionGetGlobalVariables.test.ts
new file mode 100644
index 000000000..e7c6f3cae
--- /dev/null
+++ b/packages/code-generator/test/utils/expressionParser/parseExpressionGetGlobalVariables.test.ts
@@ -0,0 +1,114 @@
+import test from 'ava';
+import type { ExecutionContext, Macro } from 'ava';
+import {
+  parseExpressionGetGlobalVariables,
+  ParseExpressionGetGlobalVariablesOptions,
+} from '../../../src/utils/expressionParser';
+
+const macro: Macro<any[]> = (
+  t: ExecutionContext<Record<string, unknown>>,
+  input: [string | null | undefined, ParseExpressionGetGlobalVariablesOptions],
+  expected: string[],
+  error?: { message: RegExp },
+) => {
+  if (!error) {
+    t.deepEqual(parseExpressionGetGlobalVariables(input[0], input[1]), expected);
+  } else {
+    t.throws(() => {
+      t.deepEqual(parseExpressionGetGlobalVariables(input[0], input[1]), expected);
+    }, error.message);
+  }
+};
+
+macro.title = (providedTitle: string | undefined, ...args: any[]): string => {
+  const [input, expected] = args;
+  return providedTitle || `global variables of "${input[0]}" should be "${expected.join(', ')}"`;
+};
+
+test(macro, ['function (){ }', {}], []);
+test(macro, ['function (){ __$$context.utils.Toast.show("Hello world!") }', {}], ['__$$context']);
+
+test(macro, ['function (){ __$$context.utils.formatPrice(item.price1, "元") }', {}], ['__$$context', 'item']);
+
+test(
+  macro,
+  [
+    'function (){ __$$context.utils.formatPrice(item2, "元"); }',
+    { filter: (varName: string) => !/^__\$\$/.test(varName) },
+  ],
+  ['item2'],
+);
+
+test(
+  macro,
+  [
+    'function (){ __$$context.utils.log(item3, [item4, item5]); }',
+    { filter: (varName: string) => !/^__\$\$/.test(varName) },
+  ],
+  ['item3', 'item4', 'item5'],
+);
+
+test(
+  macro,
+  ['function (){ item3[item4]("Hello"); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3', 'item4'],
+);
+
+test(macro, ['function (){ item3("Hello"); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }], ['item3']);
+
+test(
+  macro,
+  ['function foo(){ foo[item3]("Hello"); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3'],
+);
+
+// isAssignmentExpression/right
+test(
+  macro,
+  ['function (){ let foo; foo = item3; foo(); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3'],
+);
+
+// isAssignmentExpression/left
+test(
+  macro,
+  ['function (){ foo = item3; foo(); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['foo', 'item3'],
+);
+
+// isVariableDeclarator
+test(
+  macro,
+  ['function (){ const foo = item3; foo(); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3'],
+);
+
+// isVariableDeclarator
+test(
+  macro,
+  ['function (){ let foo = item3; foo(); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3'],
+);
+
+// isVariableDeclarator
+test(
+  macro,
+  ['function (){ var foo = item3; foo(); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['item3'],
+);
+
+// isTemplateLiteral
+test(
+  macro,
+  ['function (){ console.log(`Hello ${item3};`); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['console', 'item3'],
+);
+
+// isBinaryExpression
+test(
+  macro,
+  ['function (){ console.log(item2 | item3); }', { filter: (varName: string) => !/^__\$\$/.test(varName) }],
+  ['console', 'item2', 'item3'],
+);
+
+// TODO: 补充更多类型的测试用例
diff --git a/packages/code-generator/test/utils/version.test.ts b/packages/code-generator/test/utils/version.test.ts
new file mode 100644
index 000000000..f3a3fba74
--- /dev/null
+++ b/packages/code-generator/test/utils/version.test.ts
@@ -0,0 +1,50 @@
+import test from 'ava';
+import type { ExecutionContext, Macro } from 'ava';
+import { calcCompatibleVersion } from '../../src/utils/version';
+
+const NO_COMPATIBLE_VERSIONS = /no compatible versions/;
+
+const testCalcCompatibleVersion: Macro<any[]> = (
+  t: ExecutionContext<Record<string, unknown>>,
+  input: [string | null | undefined, string | null | undefined],
+  expected: string,
+  error?: { message: RegExp },
+) => {
+  if (!error) {
+    t.is(calcCompatibleVersion(input[0], input[1]), expected);
+    t.is(calcCompatibleVersion(input[1], input[0]), expected); // 应该满足交换律
+  } else {
+    t.throws(() => {
+      calcCompatibleVersion(input[0], input[1]);
+    }, error.message);
+    t.throws(() => {
+      calcCompatibleVersion(input[1], input[0]); // 应该满足交换律
+    }, error.message);
+  }
+};
+
+testCalcCompatibleVersion.title = (providedTitle: string | undefined, ...args: any[]): string => {
+  const [input, expected] = args;
+  return `calc compatible versions "${input[0]}" & "${input[1]}" should be "${expected}"`;
+};
+
+test(testCalcCompatibleVersion, ['*', '*'], '*');
+test(testCalcCompatibleVersion, ['1.0.0', '1.0.0'], '1.0.0');
+test(testCalcCompatibleVersion, ['^1.0.0', '^1.0.0'], '^1.0.0');
+
+test(testCalcCompatibleVersion, ['*', undefined], '*');
+
+test(testCalcCompatibleVersion, [undefined, undefined], '*');
+
+test(testCalcCompatibleVersion, ['^1.0.0', undefined], '^1.0.0');
+
+test(testCalcCompatibleVersion, ['*', '^1.0.0'], '^1.0.0');
+test(testCalcCompatibleVersion, ['^1.0.0', '^1.0.2'], '^1.0.2');
+test(testCalcCompatibleVersion, ['^1.2.0', '^1.1.2'], '^1.2.0');
+test(testCalcCompatibleVersion, ['^1.0.0', '1.0.2'], '1.0.2');
+
+test(testCalcCompatibleVersion, ['^0.2.0', '^0.1.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });
+
+test(testCalcCompatibleVersion, ['>0.2.0', '^0.1.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });
+
+test(testCalcCompatibleVersion, ['1.0.1', '1.0.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });
diff --git a/packages/code-generator/tools/createTemplate.js b/packages/code-generator/tools/createTemplate.js
index 8b4a47215..3a10b1599 100644
--- a/packages/code-generator/tools/createTemplate.js
+++ b/packages/code-generator/tools/createTemplate.js
@@ -2,13 +2,13 @@ const fs = require('fs');
 const path = require('path');
 
 console.log(process.argv);
-let root = '';
+let rootPath = '';
 const pathArgIndex = process.argv.indexOf('--path');
 if (pathArgIndex >= 0) {
-  root = process.argv[pathArgIndex + 1];
+  rootPath = process.argv[pathArgIndex + 1];
 }
 
-if (!root) {
+if (!rootPath) {
   throw new Error('Can\'t find path argument');
 }
 
@@ -35,7 +35,7 @@ function createTemplateFile(root, internalPath, fileName) {
     encoding: 'utf8',
   });
   const pathList = (internalPath.split(path.sep) || []).filter(p => !!p);
-  const modulePathStr = JSON.stringify(pathList).replace(/\"/g, '\'');
+  const modulePathStr = JSON.stringify(pathList).replace(/"/g, '\'');
 
   const templateContent = `
 import ResultFile from '${depPrefix}model/ResultFile';
@@ -80,6 +80,6 @@ function fileDisplay(root, internalPath) {
 
 // 调用函数遍历根目录，同时传递 文件夹路径和对应的数组
 // 请使用同步读取
-fileDisplay(root, '');
+fileDisplay(rootPath, '');
 // 读取完毕则写入到txt文件中
 // fs.writeFileSync('./data.txt', JSON.stringify(arr));
diff --git a/packages/code-generator/tsconfig.json b/packages/code-generator/tsconfig.json
index 7a6244f14..dc63d9496 100644
--- a/packages/code-generator/tsconfig.json
+++ b/packages/code-generator/tsconfig.json
@@ -2,14 +2,11 @@
   "extends": "../../tsconfig.json",
   "compilerOptions": {
     "outDir": "./lib",
-    "lib": [
-      "es6"
-    ],
+    "target": "ES2018",
+    "lib": ["ES6", "ES2016", "ES2017", "ES2018", "ES2019", "ES2020"],
     "module": "commonjs",
     "types": ["node"],
-    "baseUrl": ".",            /* Base directory to resolve non-absolute module names. */
+    "baseUrl": "." /* Base directory to resolve non-absolute module names. */
   },
-  "include": [
-    "src/**/*"
-  ]
+  "include": ["src/**/*"]
 }
diff --git a/packages/datasource-engine/.gitignore b/packages/datasource-engine/.gitignore
new file mode 100644
index 000000000..28b6557db
--- /dev/null
+++ b/packages/datasource-engine/.gitignore
@@ -0,0 +1,5 @@
+/node_modules/
+*.log
+.DS_Store
+/es/
+/lib/
diff --git a/packages/datasource-engine/handlers/fetch/index.d.ts b/packages/datasource-engine/handlers/fetch/index.d.ts
new file mode 100644
index 000000000..86829236a
--- /dev/null
+++ b/packages/datasource-engine/handlers/fetch/index.d.ts
@@ -0,0 +1 @@
+export type * from '../../es/handlers/fetch';
diff --git a/packages/datasource-engine/handlers/fetch/index.js b/packages/datasource-engine/handlers/fetch/index.js
new file mode 100644
index 000000000..5abed6279
--- /dev/null
+++ b/packages/datasource-engine/handlers/fetch/index.js
@@ -0,0 +1 @@
+module.exports = require('../../lib/handlers/fetch').default;
diff --git a/packages/datasource-engine/handlers/mtop/index.d.ts b/packages/datasource-engine/handlers/mtop/index.d.ts
new file mode 100644
index 000000000..1d11c303b
--- /dev/null
+++ b/packages/datasource-engine/handlers/mtop/index.d.ts
@@ -0,0 +1 @@
+export type * from '../../es/handlers/mtop';
diff --git a/packages/datasource-engine/handlers/mtop/index.js b/packages/datasource-engine/handlers/mtop/index.js
new file mode 100644
index 000000000..89f131c78
--- /dev/null
+++ b/packages/datasource-engine/handlers/mtop/index.js
@@ -0,0 +1 @@
+module.exports = require('../../lib/handlers/mtop').default;
diff --git a/packages/datasource-engine/handlers/url-params/index.d.ts b/packages/datasource-engine/handlers/url-params/index.d.ts
new file mode 100644
index 000000000..58e059ec8
--- /dev/null
+++ b/packages/datasource-engine/handlers/url-params/index.d.ts
@@ -0,0 +1 @@
+export type * from '../../es/handlers/url-params';
diff --git a/packages/datasource-engine/handlers/url-params/index.js b/packages/datasource-engine/handlers/url-params/index.js
new file mode 100644
index 000000000..f9b01c61e
--- /dev/null
+++ b/packages/datasource-engine/handlers/url-params/index.js
@@ -0,0 +1 @@
+module.exports = require('../../lib/handlers/url-params').default;
diff --git a/packages/datasource-engine/package.json b/packages/datasource-engine/package.json
new file mode 100644
index 000000000..321e39a55
--- /dev/null
+++ b/packages/datasource-engine/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ali/lowcode-datasource-engine",
+  "version": "0.1.11",
+  "description": "DataSource Engine for lowcode",
+  "main": "lib/index.js",
+  "module": "es/index.js",
+  "typings": "es/index.d.ts",
+  "files": [
+    "handlers",
+    "src",
+    "lib",
+    "es"
+  ],
+  "scripts": {
+    "start": "tsc --watch",
+    "clean": "rm -rf es lib",
+    "build": "rm -rf es lib && tsc --module esnext --target es6 && mv lib es && tsc",
+    "prepublishOnly": "npm run build"
+  },
+  "author": "",
+  "license": "ISC",
+  "publishConfig": {
+    "registry": "https://registry.npm.alibaba-inc.com"
+  },
+  "devDependencies": {
+    "typescript": "^3.9.7"
+  },
+  "dependencies": {
+    "@ali/universal-mtop": "^5.1.9",
+    "query-string": "^6.13.1",
+    "tslib": "^2.0.1",
+    "universal-request": "^2.2.0"
+  }
+}
diff --git a/packages/datasource-engine/src/core/DataSourceEngine.ts b/packages/datasource-engine/src/core/DataSourceEngine.ts
new file mode 100644
index 000000000..1d15aeee1
--- /dev/null
+++ b/packages/datasource-engine/src/core/DataSourceEngine.ts
@@ -0,0 +1,121 @@
+import {
+  DataSourceConfig,
+  DataSourceEngineOptions,
+  IDataSourceEngine,
+  IDataSourceEngineFactory,
+  IRuntimeContext,
+} from '../types';
+import { RuntimeDataSource } from './RuntimeDataSource';
+
+export class DataSourceEngine implements IDataSourceEngine {
+  private _dataSourceMap: Record<string, RuntimeDataSource> = {};
+
+  constructor(
+    private _dataSourceConfig: DataSourceConfig,
+    private _runtimeContext: IRuntimeContext,
+    private _options?: DataSourceEngineOptions,
+  ) {
+    _dataSourceConfig.list?.forEach((ds) => {
+      // 确保数据源都有处理器
+      const requestHandler = ds.requestHandler || _options?.requestHandlersMap?.[ds.type];
+      if (!requestHandler) {
+        throw new Error(`No request handler for "${ds.type}" data source`);
+      }
+
+      this._dataSourceMap[ds.id] = new RuntimeDataSource(
+        ds.id,
+        ds.type,
+        getValue(ds.options) || {},
+        requestHandler.bind(_runtimeContext),
+        ds.dataHandler ? ds.dataHandler.bind(_runtimeContext) : undefined,
+        (data) => {
+          _runtimeContext.setState({ [ds.id]: data });
+        },
+      );
+    });
+  }
+
+  public get dataSourceMap() {
+    return this._dataSourceMap;
+  }
+
+  public async reloadDataSource() {
+    try {
+      const allDataSourceConfigList = this._dataSourceConfig.list || [];
+
+      // urlParams 类型的优先加载
+      for (const ds of allDataSourceConfigList) {
+        if (ds.type === 'urlParams' && (getValue(ds.isInit) ?? true)) {
+          await this._dataSourceMap[ds.id].load();
+        }
+      }
+
+      // 然后是所有其他的
+      const remainDataSourceConfigList = allDataSourceConfigList.filter((x) => x.type !== 'urlParams');
+
+      // 先发起异步的
+      const asyncLoadings: Array<Promise<unknown>> = [];
+      for (const ds of remainDataSourceConfigList) {
+        if (getValue(ds.isInit) ?? true) {
+          const options = getValue(ds.options);
+          if (options && !options.isSync) {
+            this._dataSourceMap[ds.id].setOptions(options);
+            asyncLoadings.push(this._dataSourceMap[ds.id].load(options?.params).catch(() => {}));
+          }
+        }
+      }
+
+      try {
+        // 再按先后顺序发起同步请求
+        for (const ds of remainDataSourceConfigList) {
+          if (getValue(ds.isInit) ?? true) {
+            const options = getValue(ds.options);
+            if (options && options.isSync) {
+              this._dataSourceMap[ds.id].setOptions(options);
+              await this._dataSourceMap[ds.id].load(options?.params);
+              await sleep(0); // TODO: 如何优雅地解决 setState 的异步问题？
+            }
+          }
+        }
+      } catch (e) {}
+
+      await Promise.all(asyncLoadings);
+    } finally {
+      const allDataHandler = this._dataSourceConfig.dataHandler;
+      if (allDataHandler) {
+        await allDataHandler(this._getDataMapOfAll());
+      }
+    }
+  }
+
+  private _getDataMapOfAll(): Record<string, unknown> {
+    const dataMap: Record<string, unknown> = {};
+
+    Object.entries(this._dataSourceMap).forEach(([dsId, ds]) => {
+      dataMap[dsId] = ds.data;
+    });
+
+    return dataMap;
+  }
+}
+
+export const create: IDataSourceEngineFactory['create'] = (dataSourceConfig, runtimeContext, options) => {
+  return new DataSourceEngine(dataSourceConfig, runtimeContext, options);
+};
+
+function getValue<T>(valueOrValueGetter: T | (() => T)): T;
+function getValue<T extends boolean>(valueOrValueGetter: T | (() => T)): T | undefined {
+  if (typeof valueOrValueGetter === 'function') {
+    try {
+      return valueOrValueGetter();
+    } catch (e) {
+      return undefined;
+    }
+  } else {
+    return valueOrValueGetter;
+  }
+}
+
+function sleep(ms: number = 0) {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
diff --git a/packages/datasource-engine/src/core/RuntimeDataSource.ts b/packages/datasource-engine/src/core/RuntimeDataSource.ts
new file mode 100644
index 000000000..8f53b45f7
--- /dev/null
+++ b/packages/datasource-engine/src/core/RuntimeDataSource.ts
@@ -0,0 +1,91 @@
+import { DataSourceOptions, IRuntimeDataSource, RequestHandler, RuntimeDataSourceStatus } from '../types';
+import { DataSourceResponse } from '../types/DataSourceResponse';
+
+export class RuntimeDataSource<
+  TParams extends Record<string, unknown> = Record<string, unknown>,
+  TRequestResult = unknown,
+  TResultData = unknown
+> implements IRuntimeDataSource<TParams, TResultData> {
+  private _status: RuntimeDataSourceStatus = RuntimeDataSourceStatus.Initial;
+  private _data?: TResultData;
+  private _error?: Error;
+  private _latestOptions: DataSourceOptions<TParams>;
+
+  constructor(
+    private _id: string,
+    private _type: string,
+    private _initialOptions: DataSourceOptions<TParams>,
+    private _requestHandler: RequestHandler<DataSourceOptions<TParams>, DataSourceResponse<TRequestResult>>,
+    private _dataHandler:
+      | ((
+          data: DataSourceResponse<TRequestResult> | undefined,
+          error: unknown | undefined,
+        ) => TResultData | Promise<TResultData>)
+      | undefined,
+    private _onLoaded: (data: TResultData) => void,
+  ) {
+    this._latestOptions = _initialOptions;
+  }
+
+  public get status() {
+    return this._status;
+  }
+
+  public get data() {
+    return this._data;
+  }
+
+  public get error() {
+    return this._error;
+  }
+
+  public async load(params?: TParams): Promise<TResultData> {
+    try {
+      this._latestOptions = {
+        ...this._latestOptions,
+        params: {
+          ...this._latestOptions.params,
+          ...params,
+        } as TParams,
+      };
+
+      this._status = RuntimeDataSourceStatus.Loading;
+
+      const data = await this._request(this._latestOptions);
+
+      this._status = RuntimeDataSourceStatus.Loaded;
+
+      this._onLoaded(data);
+
+      this._data = data;
+      return data;
+    } catch (err) {
+      this._error = err;
+      this._status = RuntimeDataSourceStatus.Error;
+      throw err;
+    }
+  }
+
+  public setOptions(options: DataSourceOptions<TParams>) {
+    this._latestOptions = options;
+  }
+
+  private async _request(options: DataSourceOptions<TParams>) {
+    try {
+      const response = await this._requestHandler(options);
+
+      const data = this._dataHandler
+        ? await this._dataHandler(response, undefined)
+        : ((response.data as unknown) as TResultData);
+
+      return data;
+    } catch (err) {
+      if (this._dataHandler) {
+        const data = await this._dataHandler(undefined, err);
+        return data;
+      }
+
+      throw err;
+    }
+  }
+}
diff --git a/packages/datasource-engine/src/core/index.ts b/packages/datasource-engine/src/core/index.ts
new file mode 100644
index 000000000..fb9854290
--- /dev/null
+++ b/packages/datasource-engine/src/core/index.ts
@@ -0,0 +1 @@
+export { create } from './DataSourceEngine';
diff --git a/packages/datasource-engine/src/handlers/fetch.ts b/packages/datasource-engine/src/handlers/fetch.ts
new file mode 100644
index 000000000..d0f6d344b
--- /dev/null
+++ b/packages/datasource-engine/src/handlers/fetch.ts
@@ -0,0 +1,24 @@
+import request from 'universal-request';
+import type { AsObject, RequestOptions } from 'universal-request/lib/types';
+
+import { DataSourceOptions, RequestHandler } from '../types';
+
+const fetchHandler: RequestHandler = async ({
+  url,
+  uri,
+  data,
+  params,
+  ...otherOptions
+}: DataSourceOptions) => {
+  const reqOptions = {
+    url: ((url || uri) as unknown) as string,
+    data: ((data || params) as unknown) as AsObject,
+    ...otherOptions,
+  };
+
+  const res = await request(reqOptions as RequestOptions);
+
+  return res;
+};
+
+export default fetchHandler;
diff --git a/packages/datasource-engine/src/handlers/mtop.ts b/packages/datasource-engine/src/handlers/mtop.ts
new file mode 100644
index 000000000..4894b9ad9
--- /dev/null
+++ b/packages/datasource-engine/src/handlers/mtop.ts
@@ -0,0 +1,18 @@
+import mtop from '@ali/universal-mtop';
+import { RequestHandler } from '../types';
+
+const mtopHandler: RequestHandler = async (options) => {
+  const { api, uri, data, params, type, method, ...otherOptions } = options;
+  const reqOptions = {
+    ...otherOptions,
+    api: api || uri,
+    data: data || params,
+    type: type || method,
+  };
+
+  const res = await mtop(reqOptions);
+
+  return res;
+};
+
+export default mtopHandler;
diff --git a/packages/datasource-engine/src/handlers/url-params.ts b/packages/datasource-engine/src/handlers/url-params.ts
new file mode 100644
index 000000000..67540c9f2
--- /dev/null
+++ b/packages/datasource-engine/src/handlers/url-params.ts
@@ -0,0 +1,12 @@
+import qs from 'query-string';
+import { RequestHandler } from '../types';
+
+export default function urlParamsHandler(search: string | Record<string, unknown>): RequestHandler {
+  const urlParams = typeof search === 'string' ? qs.parse(search) : search;
+
+  return async () => {
+    return {
+      data: urlParams,
+    };
+  };
+}
diff --git a/packages/datasource-engine/src/index.ts b/packages/datasource-engine/src/index.ts
new file mode 100644
index 000000000..a5a9e0535
--- /dev/null
+++ b/packages/datasource-engine/src/index.ts
@@ -0,0 +1,2 @@
+export * from './core';
+export * from './types';
diff --git a/packages/datasource-engine/src/types/DataSourceConfig.ts b/packages/datasource-engine/src/types/DataSourceConfig.ts
new file mode 100644
index 000000000..8a3687834
--- /dev/null
+++ b/packages/datasource-engine/src/types/DataSourceConfig.ts
@@ -0,0 +1,6 @@
+import { DataSourceConfigItem } from './DataSourceConfigItem';
+
+export type DataSourceConfig = {
+  list?: DataSourceConfigItem[];
+  dataHandler?: (dataMap: Record<string, unknown>) => void | Promise<void>;
+};
diff --git a/packages/datasource-engine/src/types/DataSourceConfigItem.ts b/packages/datasource-engine/src/types/DataSourceConfigItem.ts
new file mode 100644
index 000000000..a8aa46965
--- /dev/null
+++ b/packages/datasource-engine/src/types/DataSourceConfigItem.ts
@@ -0,0 +1,17 @@
+import { DataSourceOptions } from './DataSourceOptions';
+import { RequestHandler } from './RequestHandler';
+
+export type DataSourceConfigItem = {
+  id: string;
+  type: string;
+  isInit?: boolean | (() => boolean | undefined);
+
+  options?: DataSourceOptions | (() => DataSourceOptions | undefined);
+
+  requestHandler?: RequestHandler;
+
+  dataHandler?: (
+    data: unknown | undefined,
+    error: unknown | undefined,
+  ) => unknown;
+};
diff --git a/packages/datasource-engine/src/types/DataSourceEngineOptions.ts b/packages/datasource-engine/src/types/DataSourceEngineOptions.ts
new file mode 100644
index 000000000..f2fd84b1a
--- /dev/null
+++ b/packages/datasource-engine/src/types/DataSourceEngineOptions.ts
@@ -0,0 +1,7 @@
+import { RequestHandler } from './RequestHandler';
+
+export type DataSourceEngineOptions = {
+  requestHandlersMap?: {
+    [dataSourceType: string]: RequestHandler;
+  };
+};
diff --git a/packages/datasource-engine/src/types/DataSourceOptions.ts b/packages/datasource-engine/src/types/DataSourceOptions.ts
new file mode 100644
index 000000000..55a317496
--- /dev/null
+++ b/packages/datasource-engine/src/types/DataSourceOptions.ts
@@ -0,0 +1,10 @@
+export type DataSourceOptions<TParams = Record<string, unknown>> = {
+  uri?: string;
+  params?: TParams;
+  method?: string;
+  isCors?: boolean;
+  timeout?: number;
+  headers?: Record<string, string>;
+  isSync?: boolean;
+  [key: string]: unknown;
+};
diff --git a/packages/datasource-engine/src/types/DataSourceResponse.ts b/packages/datasource-engine/src/types/DataSourceResponse.ts
new file mode 100644
index 000000000..36bd45fff
--- /dev/null
+++ b/packages/datasource-engine/src/types/DataSourceResponse.ts
@@ -0,0 +1,3 @@
+export type DataSourceResponse<TData = unknown> = {
+  data: TData;
+};
diff --git a/packages/datasource-engine/src/types/IDataSourceEngine.ts b/packages/datasource-engine/src/types/IDataSourceEngine.ts
new file mode 100644
index 000000000..4d19be842
--- /dev/null
+++ b/packages/datasource-engine/src/types/IDataSourceEngine.ts
@@ -0,0 +1,9 @@
+import { IRuntimeDataSource } from './IRuntimeDataSource';
+
+export interface IDataSourceEngine {
+  /** 数据源, key 是数据源的 ID */
+  readonly dataSourceMap: Record<string, IRuntimeDataSource>;
+
+  /** 重新加载所有的数据源 */
+  reloadDataSource(): Promise<void>;
+}
diff --git a/packages/datasource-engine/src/types/IDataSourceEngineFactory.ts b/packages/datasource-engine/src/types/IDataSourceEngineFactory.ts
new file mode 100644
index 000000000..4215049ea
--- /dev/null
+++ b/packages/datasource-engine/src/types/IDataSourceEngineFactory.ts
@@ -0,0 +1,12 @@
+import { DataSourceConfig } from './DataSourceConfig';
+import { DataSourceEngineOptions } from './DataSourceEngineOptions';
+import { IDataSourceEngine } from './IDataSourceEngine';
+import { IRuntimeContext } from './IRuntimeContext';
+
+export interface IDataSourceEngineFactory {
+  create(
+    dataSourceConfig: DataSourceConfig,
+    runtimeContext: IRuntimeContext,
+    options?: DataSourceEngineOptions,
+  ): IDataSourceEngine;
+}
diff --git a/packages/datasource-engine/src/types/IRuntimeContext.ts b/packages/datasource-engine/src/types/IRuntimeContext.ts
new file mode 100644
index 000000000..4fed73205
--- /dev/null
+++ b/packages/datasource-engine/src/types/IRuntimeContext.ts
@@ -0,0 +1,24 @@
+import { IRuntimeDataSource } from './IRuntimeDataSource';
+
+/** 运行时上下文 */
+export interface IRuntimeContext<
+  TState extends object = Record<string, unknown>
+> {
+  /** 当前容器的状态 */
+  readonly state: TState;
+
+  /** 设置状态(浅合并) */
+  setState(state: Partial<TState>): void;
+
+  /** 数据源, key 是数据源的 ID */
+  dataSourceMap: Record<string, IRuntimeDataSource>;
+
+  /** 重新加载所有的数据源 */
+  reloadDataSource(): Promise<void>;
+
+  /** 页面容器 */
+  readonly page: IRuntimeContext & { props: Record<string, unknown> };
+
+  /** 低代码业务组件容器 */
+  readonly component: IRuntimeContext & { props: Record<string, unknown> };
+}
diff --git a/packages/datasource-engine/src/types/IRuntimeDataSource.ts b/packages/datasource-engine/src/types/IRuntimeDataSource.ts
new file mode 100644
index 000000000..ccf133716
--- /dev/null
+++ b/packages/datasource-engine/src/types/IRuntimeDataSource.ts
@@ -0,0 +1,22 @@
+import { RuntimeDataSourceStatus } from './RuntimeDataSourceStatus';
+
+/**
+ * 运行时的数据源（对外暴露的接口）
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#Jwgj5
+ */
+export interface IRuntimeDataSource<TParams = unknown, TResultData = unknown> {
+  /** 当前状态(initial/loading/loaded/error) */
+  readonly status: RuntimeDataSourceStatus;
+
+  /** 加载成功时的数据 */
+  readonly data?: TResultData;
+
+  /** 加载出错的时候的错误信息 */
+  readonly error?: Error;
+
+  /**
+   * 加载数据 (无论是否曾经加载过)
+   * 注意：若提供 params，则会和默认配置的参数做浅合并；否则会使用默认配置的参数。
+   */
+  load(params?: TParams): Promise<TResultData>;
+}
diff --git a/packages/datasource-engine/src/types/RequestHandler.ts b/packages/datasource-engine/src/types/RequestHandler.ts
new file mode 100644
index 000000000..c8a96f099
--- /dev/null
+++ b/packages/datasource-engine/src/types/RequestHandler.ts
@@ -0,0 +1,7 @@
+import { DataSourceOptions } from './DataSourceOptions';
+import { DataSourceResponse } from './DataSourceResponse';
+
+export type RequestHandler<
+  TOptions extends DataSourceOptions = DataSourceOptions,
+  TResult extends DataSourceResponse = DataSourceResponse
+> = (options: TOptions) => Promise<TResult>;
diff --git a/packages/datasource-engine/src/types/RuntimeDataSourceStatus.ts b/packages/datasource-engine/src/types/RuntimeDataSourceStatus.ts
new file mode 100644
index 000000000..e089860ab
--- /dev/null
+++ b/packages/datasource-engine/src/types/RuntimeDataSourceStatus.ts
@@ -0,0 +1,14 @@
+/** 数据源的状态 */
+export enum RuntimeDataSourceStatus {
+  /** 初始状态，尚未加载 */
+  Initial = 'init',
+
+  /** 正在加载 */
+  Loading = 'loading',
+
+  /** 已加载(无错误) */
+  Loaded = 'loaded',
+
+  /** 加载出错了 */
+  Error = 'error',
+}
diff --git a/packages/datasource-engine/src/types/index.ts b/packages/datasource-engine/src/types/index.ts
new file mode 100644
index 000000000..31f0f3947
--- /dev/null
+++ b/packages/datasource-engine/src/types/index.ts
@@ -0,0 +1 @@
+export * from './DataSourceConfig';
export * from './DataSourceConfigItem';
export * from './DataSourceEngineOptions';
export * from './DataSourceOptions';
export * from './IDataSourceEngine';
export * from './IDataSourceEngineFactory';
export * from './IRuntimeContext';
export * from './IRuntimeDataSource';
export * from './RequestHandler';
export * from './RuntimeDataSourceStatus';
\ No newline at end of file
diff --git a/packages/datasource-engine/src/typing.d.ts b/packages/datasource-engine/src/typing.d.ts
new file mode 100644
index 000000000..2a2deec30
--- /dev/null
+++ b/packages/datasource-engine/src/typing.d.ts
@@ -0,0 +1 @@
+declare module '@ali/universal-mtop';
diff --git a/packages/datasource-engine/tsconfig.json b/packages/datasource-engine/tsconfig.json
new file mode 100644
index 000000000..e06677d2b
--- /dev/null
+++ b/packages/datasource-engine/tsconfig.json
@@ -0,0 +1,80 @@
+{
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig.json to read more about this file */
+
+    /* Basic Options */
+    // "incremental": true,                   /* Enable incremental compilation */
+    "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
+    "lib": [
+      "DOM",
+      "ES2015",
+      "ES2016",
+      "ES2017",
+      "ES2018",
+      "ES2019"
+    ] /* Specify library files to be included in the compilation. */,
+    // "allowJs": true,                       /* Allow javascript files to be compiled. */
+    // "checkJs": true,                       /* Report errors in .js files. */
+    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+    "declaration": true /* Generates corresponding '.d.ts' file. */,
+    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
+    "sourceMap": true /* Generates corresponding '.map' file. */,
+    // "outFile": "./",                       /* Concatenate and emit output to single file. */
+    "outDir": "./lib" /* Redirect output structure to the directory. */,
+    "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
+    // "composite": true,                     /* Enable project compilation */
+    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
+    "removeComments": false /* Do not emit comments to output. */,
+    // "noEmit": true,                        /* Do not emit outputs. */
+    "importHelpers": true /* Import emit helpers from 'tslib'. */,
+    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+    /* Strict Type-Checking Options */
+    "strict": true /* Enable all strict type-checking options. */,
+    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,              /* Enable strict null checks. */
+    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
+    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
+    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
+
+    /* Additional Checks */
+    // "noUnusedLocals": true,                /* Report errors on unused locals. */
+    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
+    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
+
+    /* Module Resolution Options */
+    "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
+    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
+    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+    "rootDirs": [
+      "src"
+    ] /* List of root folders whose combined content represents the structure of the project at runtime. */,
+    "typeRoots": [
+      "./node_modules/@types"
+    ] /* List of folders to include type definitions from. */,
+    // "types": [],                           /* Type declaration files to be included in compilation. */
+    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
+    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
+
+    /* Source Map Options */
+    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
+    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+    /* Experimental Options */
+    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
+    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
+
+    /* Advanced Options */
+    "skipLibCheck": true /* Skip type checking of declaration files. */,
+    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
+  }
+}
diff --git a/packages/types/src/code-intermediate.ts b/packages/types/src/code-intermediate.ts
new file mode 100644
index 000000000..656df2e1e
--- /dev/null
+++ b/packages/types/src/code-intermediate.ts
@@ -0,0 +1,14 @@
+export interface PackageJSON {
+  name: string;
+  version: string;
+  description?: string;
+  dependencies: Record<string, string>;
+  devDependencies: Record<string, string>;
+  scripts?: Record<string, string>;
+  engines?: Record<string, string>;
+  repository?: {
+    type: string;
+    url: string;
+  };
+  private?: boolean;
+}
diff --git a/packages/types/src/code-result.ts b/packages/types/src/code-result.ts
new file mode 100644
index 000000000..07e9c0795
--- /dev/null
+++ b/packages/types/src/code-result.ts
@@ -0,0 +1,59 @@
+/**
+ * 导出内容结构，文件夹
+ *
+ * @export
+ * @interface ResultDir
+ */
+export interface ResultDir {
+  /**
+   * 文件夹名称，Root 名称默认为 .
+   *
+   * @type {string}
+   * @memberof ResultDir
+   */
+  name: string;
+  /**
+   * 子目录
+   *
+   * @type {ResultDir[]}
+   * @memberof ResultDir
+   */
+  dirs: ResultDir[];
+  /**
+   * 文件夹内文件
+   *
+   * @type {ResultFile[]}
+   * @memberof ResultDir
+   */
+  files: ResultFile[];
+}
+
+/**
+ * 导出内容，对文件的描述
+ *
+ * @export
+ * @interface ResultFile
+ */
+export interface ResultFile {
+  /**
+   * 文件名
+   *
+   * @type {string}
+   * @memberof ResultFile
+   */
+  name: string;
+  /**
+   * 文件类型扩展名，例如 .js .less
+   *
+   * @type {string}
+   * @memberof ResultFile
+   */
+  ext: string;
+  /**
+   * 文件内容
+   *
+   * @type {string}
+   * @memberof ResultFile
+   */
+  content: string;
+}
diff --git a/packages/types/src/data-source.ts b/packages/types/src/data-source.ts
index 742a4f9d4..157e65648 100644
--- a/packages/types/src/data-source.ts
+++ b/packages/types/src/data-source.ts
@@ -1,16 +1,32 @@
-import { CompositeValue } from './value-type';
+import { CompositeValue, JSExpression, JSFunction, JSONObject } from './value-type';
 
+/**
+ * 数据源对象
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
+ */
 export interface DataSourceConfig {
   id: string;
-  isInit: boolean;
-  type: string;
-  options: {
-    uri: string;
+  isInit?: boolean | JSExpression;
+  type?: string;
+  requestHandler?: JSFunction;
+  dataHandler?: JSFunction;
+  options?: {
+    uri: string | JSExpression;
+    params?: JSONObject | JSExpression;
+    method?: string | JSExpression;
+    isCors?: boolean | JSExpression;
+    timeout?: number | JSExpression;
+    headers?: JSONObject | JSExpression;
     [option: string]: CompositeValue;
   };
   [otherKey: string]: CompositeValue;
 }
 
+/**
+ * 数据源对象
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
+ */
 export interface DataSource {
   list: DataSourceConfig[];
+  dataHandler?: JSFunction;
 }
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index d8f66a46c..56ff2826b 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -15,3 +15,5 @@ export * from './setter-config';
 export * from './setting-target';
 export * from './node';
 export * from './transform-stage';
+export * from './code-intermediate';
+export * from './code-result';
diff --git a/packages/types/src/schema.ts b/packages/types/src/schema.ts
index 9002d6594..590618a31 100644
--- a/packages/types/src/schema.ts
+++ b/packages/types/src/schema.ts
@@ -1,18 +1,20 @@
 import { ComponentsMap } from './npm';
-import { CompositeValue, JSExpression, CompositeObject, JSONObject } from './value-type';
+import { CompositeValue, JSExpression, JSFunction, CompositeObject, JSONObject } from './value-type';
 import { DataSource } from './data-source';
 import { I18nMap } from './i18n';
 import { UtilsMap } from './utils';
 
+// 搭建基础协议 - 单个组件树节点描述
+// 转换成一个 .jsx 文件内 React Class 类 render 函数返回的 jsx 代码
 export interface NodeSchema {
   id?: string;
-  componentName: string;
-  props?: PropsMap | PropsList;
+  componentName: string; // 组件名称 必填、首字母大写
+  props?: PropsMap | PropsList; // 组件属性对象
   leadingComponents?: string;
-  condition?: CompositeValue;
-  loop?: CompositeValue;
-  loopArgs?: [string, string];
-  children?: NodeData | NodeData[];
+  condition?: CompositeValue; // 渲染条件
+  loop?: CompositeValue; // 循环数据
+  loopArgs?: [string, string]; // 循环迭代对象、索引名称 ["item", "index"]
+  children?: NodeData | NodeData[]; // 子节点
 
   // ------- future support -----
   conditionGroup?: string;
@@ -30,6 +32,7 @@ export type PropsList = Array<{
 }>;
 
 export type NodeData = NodeSchema | JSExpression | DOMText;
+export type NodeDataType = NodeData | NodeData[];
 
 export function isDOMText(data: any): data is DOMText {
   return typeof data === 'string';
@@ -45,31 +48,43 @@ export interface ContainerSchema extends NodeSchema {
     [key: string]: CompositeValue;
   };
   methods?: {
-    [key: string]: JSExpression;
+    [key: string]: JSExpression | JSFunction;
   };
   lifeCycles?: {
-    [key: string]: JSExpression;
+    [key: string]: JSExpression | JSFunction;
   };
   css?: string;
   dataSource?: DataSource;
   defaultProps?: CompositeObject;
 }
 
+/**
+ * 页面容器
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
+ */
 export interface PageSchema extends ContainerSchema {
   componentName: 'Page';
 }
 
+/**
+ * 低代码业务组件容器
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
+ */
 export interface ComponentSchema extends ContainerSchema {
   componentName: 'Component';
 }
 
-export type RootSchema = PageSchema | ComponentSchema;
-
-export interface BlockSchema extends NodeSchema {
+/**
+ * 区块容器
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#XMeF5
+ */
+export interface BlockSchema extends ContainerSchema {
   componentName: 'Block';
 }
+
+export type RootSchema = PageSchema | ComponentSchema | BlockSchema;
+
 export interface SlotSchema extends NodeSchema {
-  name?: string;
   componentName: 'Slot';
   params?: string[];
 }
diff --git a/packages/types/src/utils.ts b/packages/types/src/utils.ts
index 751317f84..b8ac406ef 100644
--- a/packages/types/src/utils.ts
+++ b/packages/types/src/utils.ts
@@ -1,13 +1,17 @@
 import { NpmInfo } from './npm';
+import { JSExpression, JSFunction } from './value-type';
 
-export type UtilsMap = Array<
-| {
+export type InternalUtils = {
   name: string;
-  type: 'npm';
+  type: 'function';
+  content: JSFunction | JSExpression;
+};
+
+export type ExternalUtils = {
+  name: string;
+  type: 'npm' | 'tnpm';
   content: NpmInfo;
-}
-| {
-  name: string;
-  type: '';
-}
->;
+};
+
+export type UtilItem = InternalUtils | ExternalUtils;
+export type UtilsMap = UtilItem[];
diff --git a/packages/types/src/value-type.ts b/packages/types/src/value-type.ts
index 14eea7ad4..7aa964620 100644
--- a/packages/types/src/value-type.ts
+++ b/packages/types/src/value-type.ts
@@ -11,10 +11,31 @@ export interface JSExpression {
    * 模拟值
    */
   mock?: any;
+}
+
+// 函数
+export interface JSFunction {
+  type: 'JSFunction';
   /**
-   * 额外扩展属性，如 extType、events
+   * 表达式字符串
    */
-  [key: string]: any;
+  value: string;
+}
+
+/**
+ * 事件函数类型
+ * @see https://yuque.antfin-inc.com/mo/spec/spec-low-code-building-schema#feHTW
+ */
+export interface JSFunction {
+  type: 'JSFunction';
+
+  /**
+   * 函数定义，或直接函数表达式
+   */
+  value: string;
+
+  /** 源码 */
+  compiled?: string;
 }
 
 // 函数
@@ -35,7 +56,6 @@ export interface JSFunction{
 }
 
 export interface JSSlot {
-  name?: string;
   type: 'JSSlot';
   title?: string;
   // 函数的入参
@@ -56,23 +76,20 @@ export interface JSONObject {
 }
 
 // 复合类型
-export type CompositeValue = JSONValue | JSExpression | JSSlot | CompositeArray | CompositeObject | JSFunction;
+export type CompositeValue = JSONValue | JSExpression | JSFunction | JSSlot | CompositeArray | CompositeObject;
 export type CompositeArray = CompositeValue[];
 export interface CompositeObject {
   [key: string]: CompositeValue;
 }
 
-
 export function isJSExpression(data: any): data is JSExpression {
   return data && data.type === 'JSExpression';
 }
 
-
-export function isJSFunction(data: any): data is JSFunction {
-  return data && data.type === 'JSFunction';
+export function isJSFunction(x: any): x is JSFunction {
+  return typeof x === 'object' && x && x.type === 'JSFunction';
 }
 
-
 export function isJSSlot(data: any): data is JSSlot {
   return data && data.type === 'JSSlot';
 }
