feat: 🎸 通过 config.miniAppBuildType 来支持 Rax 的 runtime 模式

This commit is contained in:
牧毅 2020-08-18 17:05:15 +08:00
parent c743afd9ee
commit 35fcdd955b
23 changed files with 457 additions and 2 deletions

View File

@ -128,6 +128,16 @@ export class ProjectBuilder implements IProjectBuilder {
});
}
// 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);
@ -188,6 +198,8 @@ export class ProjectBuilder implements IProjectBuilder {
});
}
// TODO: 更多 slots 的处理??是不是可以考虑把 template 中所有的 slots 都处理下?
// Post Process
// Combine Modules

View File

@ -1,6 +1,7 @@
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';
@ -9,6 +10,7 @@ export default {
template,
plugins: {
appConfig,
buildConfig,
entry,
entryDocument,
globalStyle,

View File

@ -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;

View File

@ -9,7 +9,6 @@ import file2 from './files/eslintrc.js';
import file3 from './files/gitignore';
import file4 from './files/README.md';
import file5 from './files/abc.json';
import file6 from './files/build.json';
const raxAppTemplate: IProjectTemplate = {
slots: {
@ -31,6 +30,10 @@ const raxAppTemplate: IProjectTemplate = {
path: ['src'],
fileName: 'app',
},
buildConfig: {
path: [],
fileName: 'build',
},
constants: {
path: ['src'],
fileName: 'constants',
@ -66,7 +69,6 @@ const raxAppTemplate: IProjectTemplate = {
runFileGenerator(root, file3);
runFileGenerator(root, file4);
runFileGenerator(root, file5);
runFileGenerator(root, file6);
return root;
},

View File

@ -52,6 +52,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
css(),
],
appConfig: [raxApp.plugins.appConfig()],
buildConfig: [raxApp.plugins.buildConfig()],
entry: [raxApp.plugins.entry()],
constants: [constants()],
utils: [esModule(), utils()],

View File

@ -56,6 +56,7 @@ export interface IAppConfig {
targetRootID?: string; // 渲染根节点 ID
layout?: NodeSchema;
theme?: object; // 主题配置,根据接入的主题模块不同
miniAppBuildType?: 'runtime' | 'compile'; // 小程序的构建类型
}
export interface IAppMeta {

View File

@ -0,0 +1 @@
# 这个 demo 是用来演示运行时的方案的。

View File

@ -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

View File

@ -0,0 +1,11 @@
# 忽略目录
build/
tests/
demo/
# node 覆盖率文件
coverage/
# 忽略文件
**/*-min.js
**/*.min.js

View File

@ -0,0 +1,3 @@
module.exports = {
extends: ['rax'],
};

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,7 @@
{
"type": "rax",
"builder": "@ali/builder-rax-v1",
"info": {
"raxVersion": "1.x"
}
}

View File

@ -0,0 +1,15 @@
{
"inlineStyle": false,
"plugins": [
[
"build-plugin-rax-app",
{
"targets": ["web", "miniapp"],
"miniapp": {
"buildType": "runtime"
}
}
],
"@ali/build-plugin-rax-app-def"
]
}

View File

@ -0,0 +1,34 @@
{
"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": "^0.1.0",
"universal-env": "^3.2.0",
"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"
}
}

View File

@ -0,0 +1,6 @@
import { runApp } from 'rax-app';
import appConfig from './app.json';
import './global.scss';
runApp(appConfig);

View File

@ -0,0 +1,11 @@
{
"routes": [
{
"path": "/",
"source": "pages/Home/index"
}
],
"window": {
"title": "Rax App Demo"
}
}

View File

@ -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;

View File

@ -0,0 +1,9 @@
body {
-webkit-font-smoothing: antialiased;
}
page,
body {
width: 750rpx;
overflow-x: hidden;
}

View File

@ -0,0 +1,134 @@
// : "__$$" 访
// 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';
import { isMiniApp as __$$isMiniApp } from 'universal-env';
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;
return (
<View>
<Card>
<Text>This is a demo card.</Text>
</Card>
</View>
);
}
_createContext() {
const self = this;
const context = {
get state() {
return self.state;
},
setState(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;
},
...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 : [];
}

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1,84 @@
{
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: '张三',
},
}