diff --git a/README.md b/README.md
index 2472c1248..00541798a 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,7 @@ Finally, To start developing your application run `npm run start`. The applicati
- [hello-world](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/hello-world)
- [basic-spa](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-spa)
- [basic-store](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-store)
+- [basic-mpa](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-mpa)
- [basic-request](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-request)
- [icestark-child](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/icestark-child)
- [icestark-layout](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/icestark-layout)
diff --git a/README_zh-CN.md b/README_zh-CN.md
index 7831aa678..b3649646d 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -107,6 +107,7 @@ createApp(appConfig)
- [hello-world](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/hello-world)
- [basic-spa](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-spa)
- [basic-store](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-store)
+- [basic-mpa](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-mpa)
- [basic-request](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/basic-request)
- [icestark-child](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/icestark-child)
- [icestark-layout](https://codesandbox.io/s/github/ice-lab/icejs/tree/master/examples/icestark-layout)
diff --git a/examples/basic-mpa/build.json b/examples/basic-mpa/build.json
new file mode 100644
index 000000000..c723ab840
--- /dev/null
+++ b/examples/basic-mpa/build.json
@@ -0,0 +1,4 @@
+{
+ "mpa": true,
+ "plugins": []
+}
diff --git a/examples/basic-mpa/package.json b/examples/basic-mpa/package.json
new file mode 100644
index 000000000..e9d8fdde7
--- /dev/null
+++ b/examples/basic-mpa/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "exmaple-basic-mpa",
+ "description": "",
+ "dependencies": {
+ "ice.js": "^1.0.11",
+ "react": "^16.4.1",
+ "react-dom": "^16.4.1"
+ },
+ "devDependencies": {
+ "@types/react": "^16.9.13",
+ "@types/react-dom": "^16.9.4"
+ },
+ "scripts": {
+ "start": "icejs start",
+ "build": "icejs build"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+}
diff --git a/examples/basic-mpa/public/dashboard.html b/examples/basic-mpa/public/dashboard.html
new file mode 100644
index 000000000..2d5423689
--- /dev/null
+++ b/examples/basic-mpa/public/dashboard.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ mpa-dashboard
+
+
+
+ dashboard content of html template
+
+
+
diff --git a/examples/basic-mpa/public/index.html b/examples/basic-mpa/public/index.html
new file mode 100644
index 000000000..407c28d75
--- /dev/null
+++ b/examples/basic-mpa/public/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ mpa-index
+
+
+
+
+
+
diff --git a/examples/basic-mpa/sandbox.config.json b/examples/basic-mpa/sandbox.config.json
new file mode 100644
index 000000000..19b69053c
--- /dev/null
+++ b/examples/basic-mpa/sandbox.config.json
@@ -0,0 +1,6 @@
+{
+ "template": "node",
+ "container": {
+ "port": 3333
+ }
+}
diff --git a/examples/basic-mpa/src/pages/Dashboard/app.ts b/examples/basic-mpa/src/pages/Dashboard/app.ts
new file mode 100644
index 000000000..b647eeef1
--- /dev/null
+++ b/examples/basic-mpa/src/pages/Dashboard/app.ts
@@ -0,0 +1,10 @@
+import { createApp } from 'ice'
+import Dashboard from './index'
+
+const appConfig = {
+ router: {
+ routes: [{ path: '/', component: Dashboard }],
+ },
+}
+
+createApp(appConfig)
diff --git a/examples/basic-mpa/src/pages/Dashboard/index.tsx b/examples/basic-mpa/src/pages/Dashboard/index.tsx
new file mode 100644
index 000000000..b73ddd44b
--- /dev/null
+++ b/examples/basic-mpa/src/pages/Dashboard/index.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react'
+import { store } from 'ice/Dashboard'
+
+const Dashboard = () => {
+ const [pageState, pageActions] = store.useModel('counter')
+ return (
+ <>
+ Dashboard Page...
+
+
+ {pageState.count}
+
+
+ >
+ )
+}
+
+export default Dashboard
diff --git a/examples/basic-mpa/src/pages/Dashboard/models/counter.ts b/examples/basic-mpa/src/pages/Dashboard/models/counter.ts
new file mode 100644
index 000000000..bd24bcc34
--- /dev/null
+++ b/examples/basic-mpa/src/pages/Dashboard/models/counter.ts
@@ -0,0 +1,18 @@
+const delay = (time) => new Promise((resolve) => setTimeout(() => resolve(), time));
+
+export default {
+ state: {
+ count: 0
+ },
+
+ actions: {
+ increment(prevState) {
+ return { count: prevState.count + 1 }
+ },
+
+ async decrement(prevState) {
+ await delay(10);
+ return { count: prevState.count - 1 }
+ },
+ },
+};
diff --git a/examples/basic-mpa/src/pages/Home/app.ts b/examples/basic-mpa/src/pages/Home/app.ts
new file mode 100644
index 000000000..ad841d7f3
--- /dev/null
+++ b/examples/basic-mpa/src/pages/Home/app.ts
@@ -0,0 +1,10 @@
+import { createApp } from 'ice'
+import Home from './index'
+
+const appConfig = {
+ router: {
+ routes: [{ path: '/', component: Home }],
+ },
+}
+
+createApp(appConfig)
diff --git a/examples/basic-mpa/src/pages/Home/index.tsx b/examples/basic-mpa/src/pages/Home/index.tsx
new file mode 100644
index 000000000..8e04766b4
--- /dev/null
+++ b/examples/basic-mpa/src/pages/Home/index.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+
+const Home = () => {
+ return (
+ <>
+ Home Page
+ >
+ );
+}
+
+Home.pageConfig = {
+ title: 'Home Page',
+};
+
+export default Home
diff --git a/examples/basic-mpa/tsconfig.json b/examples/basic-mpa/tsconfig.json
new file mode 100644
index 000000000..a55356b61
--- /dev/null
+++ b/examples/basic-mpa/tsconfig.json
@@ -0,0 +1,40 @@
+{
+ "compileOnSave": false,
+ "buildOnSave": false,
+ "compilerOptions": {
+ "baseUrl": ".",
+ "outDir": "build",
+ "module": "esnext",
+ "target": "es6",
+ "jsx": "react",
+ "moduleResolution": "node",
+ "allowSyntheticDefaultImports": true,
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "rootDir": "./",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": false,
+ "importHelpers": true,
+ "strictNullChecks": true,
+ "suppressImplicitAnyIndexErrors": true,
+ "noUnusedLocals": true,
+ "skipLibCheck": true,
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ],
+ "ice": [
+ ".ice/index.ts"
+ ],
+ "ice/*": [
+ ".ice/pages/*"
+ ]
+ }
+ }
+}
diff --git a/packages/icejs/src/index.ts b/packages/icejs/src/index.ts
index 71f6f8cbb..b5f5145c3 100644
--- a/packages/icejs/src/index.ts
+++ b/packages/icejs/src/index.ts
@@ -8,7 +8,8 @@ const getBuiltInPlugins = (userConfig) => {
'build-plugin-ice-helpers',
'build-plugin-ice-logger',
'build-plugin-ice-config',
- 'build-plugin-ice-request'
+ 'build-plugin-ice-request',
+ 'build-plugin-ice-mpa'
]
return builtInPlugins.filter(plugin => {
diff --git a/packages/plugin-mpa/README.md b/packages/plugin-mpa/README.md
new file mode 100644
index 000000000..6cc43bb0e
--- /dev/null
+++ b/packages/plugin-mpa/README.md
@@ -0,0 +1,30 @@
+# plugin-ice-mpa
+
+> plugin for icejs to support mpa
+
+## Usage
+
+modify build options to enable mpa
+
+`build.json`:
+
+```json
+{
+ "mpa": true
+}
+```
+
+config router in each `app.[t|j]s` under `src/pages`
+
+```js
+import { createApp } from 'ice'
+import Dashboard from './index'
+
+const appConfig = {
+ router: {
+ routes: [{ path: '/', component: Dashboard }],
+ },
+}
+
+createApp(appConfig)
+```
\ No newline at end of file
diff --git a/packages/plugin-mpa/package.json b/packages/plugin-mpa/package.json
new file mode 100644
index 000000000..7f5bc41b7
--- /dev/null
+++ b/packages/plugin-mpa/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "build-plugin-ice-mpa",
+ "version": "1.0.0",
+ "description": "enable mpa project for icejs framework",
+ "author": "ice-admin@alibaba-inc.com",
+ "homepage": "",
+ "license": "MIT",
+ "main": "lib/index.js",
+ "directories": {
+ "lib": "lib"
+ },
+ "files": [
+ "lib"
+ ],
+ "publishConfig": {
+ "registry": "http://registry.npmjs.com/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@gitlab.alibaba-inc.com:ice/ice.js.git"
+ },
+ "scripts": {
+ "test": "echo \"Error: run tests from root\" && exit 1"
+ },
+ "devDependencies": {
+ "@alib/build-scripts": "^0.1.16"
+ }
+}
diff --git a/packages/plugin-mpa/src/index.ts b/packages/plugin-mpa/src/index.ts
new file mode 100644
index 000000000..8b3778989
--- /dev/null
+++ b/packages/plugin-mpa/src/index.ts
@@ -0,0 +1,25 @@
+import { IPlugin } from '@alib/build-scripts';
+
+const plugin: IPlugin = ({ context, applyMethod, registerUserConfig, modifyUserConfig }) => {
+ const { rootDir, userConfig } = context;
+
+ if (userConfig.mpa) {
+ const pages = applyMethod('getPages', rootDir);
+
+ const mpaEntry = {};
+ pages.forEach((pageName) => {
+ const entryName = pageName.toLocaleLowerCase();
+ mpaEntry[entryName] = `src/pages/${pageName}/app`;
+ });
+ // modify entry
+ modifyUserConfig('entry', mpaEntry);
+ }
+
+ // register mpa in build.json
+ registerUserConfig({
+ name: 'mpa',
+ validation: 'boolean',
+ });
+};
+
+export default plugin;
\ No newline at end of file
diff --git a/packages/plugin-mpa/tsconfig.json b/packages/plugin-mpa/tsconfig.json
new file mode 100644
index 000000000..51e250398
--- /dev/null
+++ b/packages/plugin-mpa/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.settings.json",
+ "compilerOptions": {
+ "baseUrl": "./",
+ "rootDir": "src",
+ "outDir": "lib"
+ }
+}
diff --git a/packages/plugin-router/src/index.ts b/packages/plugin-router/src/index.ts
index d5792d23d..9d9bb8983 100644
--- a/packages/plugin-router/src/index.ts
+++ b/packages/plugin-router/src/index.ts
@@ -8,18 +8,24 @@ import walker from './collector/walker';
const TEM_ROUTER_COMPATIBLE = '$ice/routes';
const TEM_ROUTER_SETS = [TEM_ROUTER_COMPATIBLE];
-const plugin: IPlugin = ({ context,onGetWebpackConfig, getValue, applyMethod, registerUserConfig }) => {
+const plugin: IPlugin = ({ context, onGetWebpackConfig, getValue, applyMethod, registerUserConfig }) => {
const { rootDir, userConfig, command } = context;
// [enum] js or ts
+ const isMpa = userConfig.mpa;
const projectType = getValue('PROJECT_TYPE');
// .tmp path
const iceTempPath = getValue('ICE_TEMP');
const routersTempPath = path.join(iceTempPath, `routes.${projectType}`);
const routerOptions = (userConfig.router || {}) as IRouterOptions;
const { configPath } = routerOptions;
- const routeConfigPath = configPath
+ let routeConfigPath = configPath
? path.join(rootDir, configPath)
: path.join(rootDir, `src/routes.${projectType}`);
+ if (isMpa) {
+ // if is mpa use empty router file
+ fse.writeFileSync(routersTempPath, 'export default [];', 'utf-8');
+ routeConfigPath = routersTempPath
+ }
const hasRouteFile = fse.existsSync(routeConfigPath);
// copy types
diff --git a/packages/plugin-router/src/module.tsx b/packages/plugin-router/src/module.tsx
index d4ecbfb05..21ccb16f2 100644
--- a/packages/plugin-router/src/module.tsx
+++ b/packages/plugin-router/src/module.tsx
@@ -7,7 +7,7 @@ const module = ({ setRenderRouter, appConfig, modifyRoutes, wrapperRouteComponen
const { router = {} } = appConfig;
// plugin-router 内置确保了 defaultRoutes 最先被添加
modifyRoutes(() => {
- return formatRoutes(defaultRoutes, '');
+ return formatRoutes(router.routes || defaultRoutes, '');
});
wrapperRouteComponent(wrapperPage);
if (router.modifyRoutes) {
diff --git a/tsconfig.json b/tsconfig.json
index 36fd708e2..cd3d88ee4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,6 +10,7 @@
{ "path": "packages/plugin-store" },
{ "path": "packages/plugin-icestark" },
{ "path": "packages/plugin-config" },
+ { "path": "packages/plugin-mpa" },
{ "path": "packages/create-ice" },
{ "path": "packages/icejs" }
]