mirror of https://github.com/alibaba/ice.git
				
				
				
			feat: support lazy store (#236)
* feat: support lazy store * feat: support component model * fix: typo * feat: support store api * chore: lazy example * feat: add babelPluginReplacePath * feat: replace router component path * feat: add getRoutes util * feat: support custom routes path * feat: support replace custom alias * fix: only transform Import node * fix: alias key * fix: only transform pages * fix: set default alias * fix: match pages * fix: calculate relative path Co-authored-by: 许文涛 <alvin.hui@qq.com>
This commit is contained in:
		
							parent
							
								
									c85e2491bc
								
							
						
					
					
						commit
						a787dd099b
					
				|  | @ -0,0 +1,6 @@ | ||||||
|  | { | ||||||
|  |   "plugins": [], | ||||||
|  |   "router": { | ||||||
|  |     "lazy": false | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -34,4 +34,8 @@ const About = () => { | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | About.pageConfig = { | ||||||
|  |   title: 'About' | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export default About; | export default About; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | import React from 'react'; | ||||||
|  | import model from 'ice/Home/components/List/model'; | ||||||
|  | 
 | ||||||
|  | const List = () => { | ||||||
|  |   console.log('List Component:', model.useValue()); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <p>List</p> | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default List; | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | export default { | ||||||
|  |   state: { | ||||||
|  |     title: 'List Model' | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | import React from 'react'; | ||||||
|  | import model from 'ice/Home/components/Todo/model'; | ||||||
|  | 
 | ||||||
|  | const Todo = () => { | ||||||
|  |   console.log('Todo Component:', model.useValue()); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <p>Todo</p> | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default Todo; | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | export default { | ||||||
|  |   state: { | ||||||
|  |     title: 'Todo Model' | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import { Link, store as appStore } from 'ice'; | import { Link, store as appStore } from 'ice'; | ||||||
| import { store as pageStore } from 'ice/Home'; | import { store as pageStore } from 'ice/Home'; | ||||||
|  | import Todo from './components/Todo'; | ||||||
|  | import List from './components/List'; | ||||||
| 
 | 
 | ||||||
| const Home = () => { | const Home = () => { | ||||||
|   const [counterState, counterActions] = appStore.useModel('counter'); |   const [counterState, counterActions] = appStore.useModel('counter'); | ||||||
|  | @ -16,6 +18,9 @@ const Home = () => { | ||||||
|         <button type="button" onClick={counterActions.decrementAsync}>-</button> |         <button type="button" onClick={counterActions.decrementAsync}>-</button> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|  |       <Todo /> | ||||||
|  |       <List /> | ||||||
|  | 
 | ||||||
|       <Link to="/about">about</Link> |       <Link to="/about">about</Link> | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,10 @@ | ||||||
| import Home from '@/pages/Home'; | import { lazy } from 'ice'; | ||||||
| import About from '@/pages/About'; | 
 | ||||||
|  | // import Home from '@/pages/Home';
 | ||||||
|  | // import About from '@/pages/About';
 | ||||||
|  | 
 | ||||||
|  | const Home = lazy(() => import('@/pages/Home')); | ||||||
|  | const About =lazy (() => import('@/pages/About')); | ||||||
| 
 | 
 | ||||||
| export default [ | export default [ | ||||||
|   { |   { | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ import checkExportData from '../utils/checkExportData'; | ||||||
| import removeExportData from '../utils/removeExportData'; | import removeExportData from '../utils/removeExportData'; | ||||||
| import { IExportData } from '../types'; | import { IExportData } from '../types'; | ||||||
| 
 | 
 | ||||||
| export default class UsePageGenerator { | export default class PageGenerator { | ||||||
|   private generator: Generator; |   private generator: Generator; | ||||||
| 
 | 
 | ||||||
|   private templatePath: string; |   private templatePath: string; | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import * as globby from 'globby'; | ||||||
| import Generator from './generator'; | import Generator from './generator'; | ||||||
| import PageGenerator from './generator/pageGenerator'; | import PageGenerator from './generator/pageGenerator'; | ||||||
| import getPages from './utils/getPages'; | import getPages from './utils/getPages'; | ||||||
|  | import getRoutes from './utils/getRoutes'; | ||||||
| import formatPath from './utils/formatPath'; | import formatPath from './utils/formatPath'; | ||||||
| 
 | 
 | ||||||
| export default (api) => { | export default (api) => { | ||||||
|  | @ -143,6 +144,7 @@ export default (api) => { | ||||||
|   // register utils method
 |   // register utils method
 | ||||||
|   registerMethod('getPages', getPages); |   registerMethod('getPages', getPages); | ||||||
|   registerMethod('formatPath', formatPath); |   registerMethod('formatPath', formatPath); | ||||||
|  |   registerMethod('getRoutes', getRoutes); | ||||||
| 
 | 
 | ||||||
|   // registerMethod for modify page
 |   // registerMethod for modify page
 | ||||||
|   registerMethod('addPageExport', pageGenerator.addPageExport); |   registerMethod('addPageExport', pageGenerator.addPageExport); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | import * as path from 'path'; | ||||||
|  | import * as fse from 'fs-extra'; | ||||||
|  | 
 | ||||||
|  | interface IParams { | ||||||
|  |   rootDir: string; | ||||||
|  |   tempDir: string; | ||||||
|  |   configPath: string; | ||||||
|  |   projectType: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface IResult { | ||||||
|  |   routesPath: string; | ||||||
|  |   isConfigRoutes: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getRoutes({ rootDir, tempDir, configPath, projectType }: IParams): IResult { | ||||||
|  |   const routesPath = configPath | ||||||
|  |     ? path.join(rootDir, configPath) | ||||||
|  |     : path.join(rootDir, `src/routes.${projectType}`); | ||||||
|  | 
 | ||||||
|  |   // 配置式路由
 | ||||||
|  |   const configPathExists = fse.existsSync(routesPath); | ||||||
|  |   if (configPathExists) { | ||||||
|  |     return { | ||||||
|  |       routesPath, | ||||||
|  |       isConfigRoutes: true | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 约定式路由
 | ||||||
|  |   return { | ||||||
|  |     routesPath: path.join(tempDir, `routes.${projectType}`), | ||||||
|  |     isConfigRoutes: false | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default getRoutes; | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| // eslint-disable-next-line no-unused-vars
 | module.exports = ({ types }, { routesPath }) => { | ||||||
| module.exports = ({ types }, { routeFile }) => { |  | ||||||
|   let hasLazyImport = false; |   let hasLazyImport = false; | ||||||
|   let importName = ''; |   let importName = ''; | ||||||
|   return { |   return { | ||||||
|     visitor: { |     visitor: { | ||||||
|       ImportDeclaration(nodePath, state) { |       ImportDeclaration(nodePath, state) { | ||||||
|         // only transform route files
 |         // only transform route files
 | ||||||
|         const isRouteConfig = routeFile === state.filename; |         const isRoutesFile = routesPath === state.filename; | ||||||
|         if (isRouteConfig) { |         if (isRoutesFile) { | ||||||
|           const { node } = nodePath; |           const { node } = nodePath; | ||||||
|           if (types.isStringLiteral(node.source, { value: 'ice'})) { |           if (types.isStringLiteral(node.source, { value: 'ice'})) { | ||||||
|             node.specifiers.forEach((importSpecifier) => { |             node.specifiers.forEach((importSpecifier) => { | ||||||
|  | @ -24,8 +23,8 @@ module.exports = ({ types }, { routeFile }) => { | ||||||
|       }, |       }, | ||||||
|       CallExpression(nodePath, state) { |       CallExpression(nodePath, state) { | ||||||
|         // only transform route files
 |         // only transform route files
 | ||||||
|         const isRouteConfig = routeFile === state.filename; |         const isRoutesFile = routesPath === state.filename; | ||||||
|         if (isRouteConfig) { |         if (isRoutesFile) { | ||||||
|           const { node } = nodePath; |           const { node } = nodePath; | ||||||
|           if ( |           if ( | ||||||
|             // case import * as xxx from 'ice'; xxx.lazy
 |             // case import * as xxx from 'ice'; xxx.lazy
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ function ignorePath(checkPath: string, ignoreOptions: IgnoreOptions) { | ||||||
| export default function walker({ | export default function walker({ | ||||||
|   rootDir, |   rootDir, | ||||||
|   routerOptions, |   routerOptions, | ||||||
|   routersTempPath, |   routesTempPath, | ||||||
|   pagesDir, |   pagesDir, | ||||||
| }) { | }) { | ||||||
|   const { ignoreRoutes, ignorePaths = ['components'], caseSensitive } = routerOptions; |   const { ignoreRoutes, ignorePaths = ['components'], caseSensitive } = routerOptions; | ||||||
|  | @ -84,7 +84,7 @@ export default function walker({ | ||||||
|     const layoutName = `Layout${dirArrUpper}`; |     const layoutName = `Layout${dirArrUpper}`; | ||||||
|     const filePath = formatPathForWin( |     const filePath = formatPathForWin( | ||||||
|       path.relative( |       path.relative( | ||||||
|         path.dirname(routersTempPath), |         path.dirname(routesTempPath), | ||||||
|         path.join(pagesDir, pageFilePath) |         path.join(pagesDir, pageFilePath) | ||||||
|       ) |       ) | ||||||
|     ); |     ); | ||||||
|  | @ -117,10 +117,10 @@ export default function walker({ | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   // amend collects
 |   // amend collects
 | ||||||
|   amender(rootDir, routersTempPath, routesCollect); |   amender(rootDir, routesTempPath, routesCollect); | ||||||
|   // generate splices
 |   // generate splices
 | ||||||
|   let routesSplices = splicer(routesCollect, routerOptions); |   let routesSplices = splicer(routesCollect, routerOptions); | ||||||
|   // output into .tmp
 |   // output into .tmp
 | ||||||
|   fse.outputFileSync(routersTempPath, routesSplices); |   fse.outputFileSync(routesTempPath, routesSplices); | ||||||
|   routesSplices = null; |   routesSplices = null; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,22 +11,37 @@ const TEM_ROUTER_SETS = [TEM_ROUTER_COMPATIBLE]; | ||||||
| const plugin: IPlugin = ({ context, onGetWebpackConfig, modifyUserConfig, getValue, applyMethod, registerUserConfig }) => { | const plugin: IPlugin = ({ context, onGetWebpackConfig, modifyUserConfig, getValue, applyMethod, registerUserConfig }) => { | ||||||
|   const { rootDir, userConfig, command } = context; |   const { rootDir, userConfig, command } = context; | ||||||
|   // [enum] js or ts
 |   // [enum] js or ts
 | ||||||
|   const isMpa = userConfig.mpa; |  | ||||||
|   const projectType = getValue('PROJECT_TYPE'); |   const projectType = getValue('PROJECT_TYPE'); | ||||||
|  | 
 | ||||||
|   // .tmp path
 |   // .tmp path
 | ||||||
|   const iceTempPath = getValue('ICE_TEMP'); |   const iceTempPath = getValue('ICE_TEMP'); | ||||||
|   const routersTempPath = path.join(iceTempPath, `routes.${projectType}`); |  | ||||||
|   const routerOptions = (userConfig.router || {}) as IRouterOptions; |   const routerOptions = (userConfig.router || {}) as IRouterOptions; | ||||||
|   const { configPath } = routerOptions; |   let { configPath } = routerOptions; | ||||||
|   let routeConfigPath = configPath | 
 | ||||||
|     ? path.join(rootDir, configPath) |   const isMpa = userConfig.mpa; | ||||||
|     : path.join(rootDir, `src/routes.${projectType}`); |   const routesTempPath = path.join(iceTempPath, `routes.${projectType}`); | ||||||
|   if (isMpa) { |  | ||||||
|   // if is mpa use empty router file
 |   // if is mpa use empty router file
 | ||||||
|     fse.writeFileSync(routersTempPath, 'export default [];', 'utf-8'); |   if (isMpa) { | ||||||
|     routeConfigPath = routersTempPath; |     fse.writeFileSync(routesTempPath, 'export default [];', 'utf-8'); | ||||||
|  |     configPath = routesTempPath; | ||||||
|   } |   } | ||||||
|   const hasRouteFile = fse.existsSync(routeConfigPath); | 
 | ||||||
|  |   const { routesPath, isConfigRoutes } = applyMethod('getRoutes', { | ||||||
|  |     rootDir, | ||||||
|  |     tempDir: iceTempPath, | ||||||
|  |     configPath, | ||||||
|  |     projectType | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   // add babel plugins for ice lazy
 | ||||||
|  |   modifyUserConfig('babelPlugins', | ||||||
|  |     [ | ||||||
|  |       ...(userConfig.babelPlugins as [] || []), | ||||||
|  |       [ | ||||||
|  |         require.resolve('./babelPluginLazy'), | ||||||
|  |         { routesPath } | ||||||
|  |       ] | ||||||
|  |     ]); | ||||||
| 
 | 
 | ||||||
|   // copy templates and export react-router-dom/history apis to ice
 |   // copy templates and export react-router-dom/history apis to ice
 | ||||||
|   const routerTemplatesPath = path.join(__dirname, '../templates'); |   const routerTemplatesPath = path.join(__dirname, '../templates'); | ||||||
|  | @ -38,14 +53,12 @@ const plugin: IPlugin = ({ context, onGetWebpackConfig, modifyUserConfig, getVal | ||||||
|   // copy types
 |   // copy types
 | ||||||
|   fse.copySync(path.join(__dirname, '../src/types/index.ts'), path.join(iceTempPath, 'router/types.ts')); |   fse.copySync(path.join(__dirname, '../src/types/index.ts'), path.join(iceTempPath, 'router/types.ts')); | ||||||
|   applyMethod('addIceTypesExport', { source: './router/types', specifier: '{ IAppRouterProps }', exportName: 'router?: IAppRouterProps' }); |   applyMethod('addIceTypesExport', { source: './router/types', specifier: '{ IAppRouterProps }', exportName: 'router?: IAppRouterProps' }); | ||||||
|   const routeFile = hasRouteFile ? routeConfigPath : routersTempPath; | 
 | ||||||
|   // add babel plugins for ice lazy
 |  | ||||||
|   modifyUserConfig('babelPlugins', [...(userConfig.babelPlugins as [] || []), [require.resolve('./babelPluginLazy'), { routeFile }]]); |  | ||||||
|   // modify webpack config
 |   // modify webpack config
 | ||||||
|   onGetWebpackConfig((config) => { |   onGetWebpackConfig((config) => { | ||||||
|     // add alias
 |     // add alias
 | ||||||
|     TEM_ROUTER_SETS.forEach(i => { |     TEM_ROUTER_SETS.forEach(i => { | ||||||
|       config.resolve.alias.set(i, routeFile); |       config.resolve.alias.set(i, routesPath); | ||||||
|     }); |     }); | ||||||
|     // alias for runtime/Router
 |     // alias for runtime/Router
 | ||||||
|     config.resolve.alias.set('$ice/Router', path.join(__dirname, 'runtime/Router')); |     config.resolve.alias.set('$ice/Router', path.join(__dirname, 'runtime/Router')); | ||||||
|  | @ -68,10 +81,10 @@ const plugin: IPlugin = ({ context, onGetWebpackConfig, modifyUserConfig, getVal | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   // do not watch folder pages when route config is exsits
 |   // do not watch folder pages when route config is exsits
 | ||||||
|   if (!hasRouteFile) { |   if (!isConfigRoutes) { | ||||||
|     const routerMatch = 'src/pages'; |     const routerMatch = 'src/pages'; | ||||||
|     const pagesDir = path.join(rootDir, routerMatch); |     const pagesDir = path.join(rootDir, routerMatch); | ||||||
|     const walkerOptions = { rootDir, routerOptions, routersTempPath, pagesDir }; |     const walkerOptions = { rootDir, routerOptions, routesTempPath, pagesDir }; | ||||||
|     walker(walkerOptions); |     walker(walkerOptions); | ||||||
|     if (command === 'start') { |     if (command === 'start') { | ||||||
|       // watch folder change when dev
 |       // watch folder change when dev
 | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| import { createStore } from '@ice/store'; |  | ||||||
| 
 |  | ||||||
| const Dashboard = createStore({}); |  | ||||||
| 
 |  | ||||||
| const About = createStore({}); |  | ||||||
| 
 |  | ||||||
| const PageStores = { Dashboard, About }; |  | ||||||
| 
 |  | ||||||
| export default PageStores; |  | ||||||
|  | @ -0,0 +1,115 @@ | ||||||
|  | import * as path from 'path'; | ||||||
|  | 
 | ||||||
|  | module.exports = ({ types: t }, { routesPath, alias }) => { | ||||||
|  |   const regex = /src\/pages\/\w+(.tsx|.jsx)?(\/index(.tsx|.jsx)?)?/; | ||||||
|  |   return { | ||||||
|  |     visitor: { | ||||||
|  |       ImportDeclaration(nodePath, state) { | ||||||
|  |         const isRoutesFile = (routesPath === state.filename); | ||||||
|  |         if (isRoutesFile) { | ||||||
|  |           let value = nodePath.node.source.value; | ||||||
|  |           if (typeof value === 'string') { | ||||||
|  |             // 配置式路由
 | ||||||
|  |             // default alias: import Home from '@/pages/Home';
 | ||||||
|  |             // custom alias: import Home from '$pages/Home';
 | ||||||
|  |             // relative path: import Home from '../pages/Home'
 | ||||||
|  |             const matchedPagePath = matchRelativePath(routesPath, value) || matchAliasPath(alias, value); | ||||||
|  |             if (matchedPagePath && regex.test(matchedPagePath)) { | ||||||
|  |               const [, , pageName] = matchedPagePath.split('/'); | ||||||
|  |               // replace to: import Home from 'ice/Home/Home'
 | ||||||
|  |               value = `ice/${pageName}/${pageName}`; | ||||||
|  |               replaceWith(t, nodePath, value); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // 约定式路由
 | ||||||
|  |             // e.g: import Home from '../src/pages/Home/index.tsx';
 | ||||||
|  |             if (value.startsWith('../src/pages')) { | ||||||
|  |               const [, , pageName] = value.split('/'); | ||||||
|  |               // replace to: import Home from './pages/Home/Home'
 | ||||||
|  |               value = `./pages/${pageName}/${pageName}`; | ||||||
|  |               replaceWith(t, nodePath, value); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  | 
 | ||||||
|  |       CallExpression(nodePath, state) { | ||||||
|  |         const isRoutesFile = (routesPath === state.filename); | ||||||
|  |         if (isRoutesFile) { | ||||||
|  |           if (t.isImport(nodePath.node.callee)) { | ||||||
|  |             const args = nodePath.node.arguments; | ||||||
|  |             for (let i = 0; i < args.length; i++) { | ||||||
|  |               let value = args[i].value; | ||||||
|  |               if (typeof value === 'string') { | ||||||
|  |                 // 配置式路由
 | ||||||
|  |                 // default alias: const Home = lazy(() => import('@/pages/Home'));
 | ||||||
|  |                 // custom alias: const Home = lazy(() => import('$pages/home));
 | ||||||
|  |                 // relative path: const Home = lazy(() => import('../pages/Home'));
 | ||||||
|  |                 const matchedPagePath = matchRelativePath(routesPath, value) || matchAliasPath(alias, value); | ||||||
|  |                 if (matchedPagePath && regex.test(matchedPagePath)) { | ||||||
|  |                   const [, , pageName] = matchedPagePath.split('/'); | ||||||
|  |                   // replace to: const Home =lazy (() => import('ice/Home/Home'));
 | ||||||
|  |                   value = `ice/${pageName}/${pageName}`; | ||||||
|  |                   args[i].value = value; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 // 约定式路由
 | ||||||
|  |                 // e.g: const Home = lazy(() => import(/* webpackChunkName: 'Home' */ '../src/pages/Home/index.tsx'));
 | ||||||
|  |                 if (value.startsWith('../src/pages')) { | ||||||
|  |                   const [, , pageName] = value.split('/'); | ||||||
|  |                   // replace to: import Home from './pages/Home/Home'
 | ||||||
|  |                   value = `./pages/${pageName}/${pageName}`; | ||||||
|  |                   args[i].value = value; | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | interface IAlias { | ||||||
|  |   [key: string]: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // enum alias:
 | ||||||
|  | //  case1: { "@": "./src", "@pages": "./src/pages" }
 | ||||||
|  | //  case2: { "@src": "./src", "@pages": "./src/pages" }
 | ||||||
|  | //  case3: { "@": "./src", "@/pages": "./src/pages" }
 | ||||||
|  | function matchAliasPath(alias: IAlias, value: string): string { | ||||||
|  |   let aliasPath = ''; | ||||||
|  |   // use default alias
 | ||||||
|  |   if (!Object.keys(alias).length) { | ||||||
|  |     alias['@'] = 'src'; | ||||||
|  |   } | ||||||
|  |   // use custom alias
 | ||||||
|  |   Object.keys(alias).forEach(currKey => { | ||||||
|  |     if (value.startsWith(currKey)) { | ||||||
|  |       const [, ...args] = value.split(currKey); | ||||||
|  |       const currAliasPath = path.join(alias[currKey], ...args); | ||||||
|  |       if (currAliasPath.includes('src/pages')) { | ||||||
|  |         aliasPath = currAliasPath; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |   return aliasPath; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function matchRelativePath(routesPath: string, value: string) { | ||||||
|  |   let relativePath = ''; | ||||||
|  |   if (/^(\.\/|\.{2}\/)/.test(value)) { | ||||||
|  |     relativePath = path.relative(process.cwd(), path.join(routesPath, '..', value)); | ||||||
|  |   } | ||||||
|  |   return relativePath; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function replaceWith(t, nodePath, value) { | ||||||
|  |   nodePath.replaceWith( | ||||||
|  |     t.ImportDeclaration( | ||||||
|  |       nodePath.node.specifiers, | ||||||
|  |       t.stringLiteral(value) | ||||||
|  |     ) | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | @ -4,10 +4,12 @@ import * as ejs from 'ejs'; | ||||||
| import * as recursiveReaddir from 'fs-readdir-recursive'; | import * as recursiveReaddir from 'fs-readdir-recursive'; | ||||||
| import * as prettier from 'prettier'; | import * as prettier from 'prettier'; | ||||||
| 
 | 
 | ||||||
| export interface IExportData { | export interface IRenderPageParams { | ||||||
|   specifier?: string; |   pageName: string; | ||||||
|   source: string; |   pageNameDir: string; | ||||||
|   exportName: string; |   pageModelsDir: string; | ||||||
|  |   pageModelFile: string; | ||||||
|  |   pageComponentFiles: []; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default class Generator { | export default class Generator { | ||||||
|  | @ -17,8 +19,6 @@ export default class Generator { | ||||||
| 
 | 
 | ||||||
|   private pageStoreTemplatePath: string |   private pageStoreTemplatePath: string | ||||||
| 
 | 
 | ||||||
|   private pageStoresTemplatePath: string |  | ||||||
| 
 |  | ||||||
|   private targetPath: string |   private targetPath: string | ||||||
| 
 | 
 | ||||||
|   private projectType: string |   private projectType: string | ||||||
|  | @ -29,7 +29,6 @@ export default class Generator { | ||||||
|     rootDir, |     rootDir, | ||||||
|     appStoreTemplatePath, |     appStoreTemplatePath, | ||||||
|     pageStoreTemplatePath, |     pageStoreTemplatePath, | ||||||
|     pageStoresTemplatePath, |  | ||||||
|     targetPath, |     targetPath, | ||||||
|     applyMethod, |     applyMethod, | ||||||
|     projectType |     projectType | ||||||
|  | @ -45,13 +44,12 @@ export default class Generator { | ||||||
|     this.rootDir = rootDir; |     this.rootDir = rootDir; | ||||||
|     this.appStoreTemplatePath = appStoreTemplatePath; |     this.appStoreTemplatePath = appStoreTemplatePath; | ||||||
|     this.pageStoreTemplatePath = pageStoreTemplatePath; |     this.pageStoreTemplatePath = pageStoreTemplatePath; | ||||||
|     this.pageStoresTemplatePath = pageStoresTemplatePath; |  | ||||||
|     this.targetPath = targetPath; |     this.targetPath = targetPath; | ||||||
|     this.applyMethod = applyMethod; |     this.applyMethod = applyMethod; | ||||||
|     this.projectType = projectType; |     this.projectType = projectType; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private getPageModels (pageName: string, pageModelsDir: string, pageModelFile: string) { |   private getPageModels(pageName: string, pageModelsDir: string, pageModelFile: string) { | ||||||
|     if (fse.pathExistsSync(pageModelsDir)) { |     if (fse.pathExistsSync(pageModelsDir)) { | ||||||
|       const pageModels = recursiveReaddir(pageModelsDir).map(item => path.parse(item)); |       const pageModels = recursiveReaddir(pageModelsDir).map(item => path.parse(item)); | ||||||
| 
 | 
 | ||||||
|  | @ -82,8 +80,19 @@ export default class Generator { | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private getComponentModels(componentFiles: []) { | ||||||
|  |     const componentModels = []; | ||||||
|  |     componentFiles.forEach(componentFile => { | ||||||
|  |       const parsedPath = path.parse(componentFile); | ||||||
|  |       if (parsedPath.name === 'model') { | ||||||
|  |         componentModels.push(parsedPath); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     return componentModels; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private renderAppStore() { |   private renderAppStore() { | ||||||
|     const sourceFilename = 'appStore'; |     const sourceFilename = 'store/index'; | ||||||
|     const exportName = 'store'; |     const exportName = 'store'; | ||||||
|     const targetPath = path.join(this.targetPath, `${sourceFilename}.ts`); |     const targetPath = path.join(this.targetPath, `${sourceFilename}.ts`); | ||||||
| 
 | 
 | ||||||
|  | @ -106,50 +115,72 @@ export default class Generator { | ||||||
|     this.applyMethod('addIceExport', { source: `./${sourceFilename}`, exportName }); |     this.applyMethod('addIceExport', { source: `./${sourceFilename}`, exportName }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private renderPageStores() { |   private renderPageStore({ pageName, pageNameDir, pageModelsDir, pageModelFile }: IRenderPageParams) { | ||||||
|     const pages = this.applyMethod('getPages', this.rootDir); |  | ||||||
|     const pageStores = []; |  | ||||||
| 
 |  | ||||||
|     // generate .ice/pages/*/store.ts
 |  | ||||||
|     pages.forEach(pageName => { |  | ||||||
|       const sourceFilename = 'store'; |  | ||||||
|       const targetPath = path.join(this.targetPath, 'pages', pageName, `${sourceFilename}.ts`); |  | ||||||
|       const pageNameDir = path.join(this.rootDir, 'src', 'pages', pageName); |  | ||||||
| 
 |  | ||||||
|       // example: src/pages/*/models/*
 |  | ||||||
|       const pageModelsDir = path.join(pageNameDir, 'models'); |  | ||||||
| 
 |  | ||||||
|       // example: src/pages/*/model.ts
 |  | ||||||
|       const pageModelFile = path.join(pageNameDir, `model.${this.projectType}`); |  | ||||||
| 
 |  | ||||||
|     if (fse.pathExistsSync(pageModelsDir) || fse.pathExistsSync(pageModelFile)) { |     if (fse.pathExistsSync(pageModelsDir) || fse.pathExistsSync(pageModelFile)) { | ||||||
|         pageStores.push(pageName); |       const sourceFilename = 'store'; | ||||||
|  |       const exportName = 'store'; | ||||||
|  |       const targetPath = path.join(this.targetPath, 'pages', pageName, `${sourceFilename}.ts`); | ||||||
| 
 | 
 | ||||||
|       const pageModelFilePath = path.join(pageNameDir, 'model'); |       const pageModelFilePath = path.join(pageNameDir, 'model'); | ||||||
|       const renderData = this.getPageModels(pageName, pageModelsDir, pageModelFilePath); |       const renderData = this.getPageModels(pageName, pageModelsDir, pageModelFilePath); | ||||||
|       this.renderFile(this.pageStoreTemplatePath, targetPath, renderData); |       this.renderFile(this.pageStoreTemplatePath, targetPath, renderData); | ||||||
| 
 | 
 | ||||||
|         const exportName = 'store'; |  | ||||||
|       this.applyMethod('removePageExport', pageName, exportName); |       this.applyMethod('removePageExport', pageName, exportName); | ||||||
|       this.applyMethod('addPageExport', pageName, { source: `./${sourceFilename}`, exportName }); |       this.applyMethod('addPageExport', pageName, { source: `./${sourceFilename}`, exportName }); | ||||||
|     } |     } | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // generate .ice/pageStores.ts
 |  | ||||||
|     this.generatePageStores(pageStores); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private generatePageStores(pageStores: string[]) { |   private renderPageComponent({ pageName, pageNameDir, pageModelsDir, pageModelFile, pageComponentFiles }: IRenderPageParams) { | ||||||
|     const targetPath = path.join(this.targetPath, 'pageStores.ts'); |     const pageComponentTemplatePath = path.join(__dirname, './template/pageComponent.tsx.ejs'); | ||||||
|  |     const pageComponentTargetPath = path.join(this.targetPath, 'pages', pageName, `${pageName}.tsx`); | ||||||
|  |     const pageComponentSourcePath = this.applyMethod('formatPath', pageNameDir); | ||||||
| 
 | 
 | ||||||
|     let importPageStoreStr = ''; |     const pageComponentRenderData = { | ||||||
|     let pageStoreStr = ''; |       pageComponentImport: `import ${pageName} from '${pageComponentSourcePath}'` , | ||||||
|     pageStores.forEach(name => { |       pageComponentExport: pageName, | ||||||
|       importPageStoreStr += `\nimport ${name} from './pages/${name}/store';`; |       hasPageStore: false, | ||||||
|       pageStoreStr += `${name},`; |       hasComponentStore: false | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     if (fse.pathExistsSync(pageModelsDir) || fse.pathExistsSync(pageModelFile)) { | ||||||
|  |       pageComponentRenderData.hasPageStore = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (this.getComponentModels(pageComponentFiles).length) { | ||||||
|  |       pageComponentRenderData.hasComponentStore = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.renderFile(pageComponentTemplatePath, pageComponentTargetPath , pageComponentRenderData); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private renderComponentStore(pageName: string, componentDir: string, componentFiles: []) { | ||||||
|  |     const componentModels = this.getComponentModels(componentFiles); | ||||||
|  | 
 | ||||||
|  |     let importStr = ''; | ||||||
|  |     let modelsStr = ''; | ||||||
|  |     componentModels.forEach(componentModel => { | ||||||
|  |       importStr += `\nimport ${componentModel.dir} from '${componentDir}/${componentModel.dir}/${componentModel.name}'`; | ||||||
|  |       modelsStr += `${componentModel.dir},`; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     this.renderFile(this.pageStoresTemplatePath, targetPath, { importPageStoreStr, pageStoreStr }); |     const templatePath = path.join(__dirname, './template/componentStore.ts.ejs'); | ||||||
|  |     const targetPath = path.join(this.targetPath, `pages/${pageName}/componentStore.ts`); | ||||||
|  |     componentFiles.forEach(componentFile => { | ||||||
|  |       const parsedPath = path.parse(componentFile); | ||||||
|  |       if (parsedPath.name === 'model') { | ||||||
|  |         this.renderFile(templatePath, targetPath, { importStr, modelsStr }); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private renderComponentModel(pageName: string, componentDir: string, componentFiles: []) { | ||||||
|  |     const componentModels = this.getComponentModels(componentFiles); | ||||||
|  |     const templatePath = path.join(__dirname, './template/componentModel.ts.ejs'); | ||||||
|  | 
 | ||||||
|  |     componentModels.forEach(componentModel => { | ||||||
|  |       const targetPath = path.join(this.targetPath, `pages/${pageName}/components/${componentModel.dir}/${componentModel.base}`); | ||||||
|  |       this.renderFile(templatePath, targetPath, { modelName: componentModel.dir }); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private renderFile(templatePath: string, targetPath: string, extraData = {}) { |   private renderFile(templatePath: string, targetPath: string, extraData = {}) { | ||||||
|  | @ -168,7 +199,34 @@ export default class Generator { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public render() { |   public render() { | ||||||
|  |     // generate .ice/store/index.ts
 | ||||||
|     this.renderAppStore(); |     this.renderAppStore(); | ||||||
|     this.renderPageStores(); | 
 | ||||||
|  |     const pages = this.applyMethod('getPages', this.rootDir); | ||||||
|  |     pages.forEach(pageName => { | ||||||
|  |       const pageNameDir = path.join(this.rootDir, 'src', 'pages', pageName); | ||||||
|  |       const pageComponentDir = path.join(pageNameDir, 'components'); | ||||||
|  |       const pageComponentFiles = recursiveReaddir(pageComponentDir); | ||||||
|  | 
 | ||||||
|  |       // e.g: src/pages/${pageName}/models/*
 | ||||||
|  |       const pageModelsDir = path.join(pageNameDir, 'models'); | ||||||
|  | 
 | ||||||
|  |       // e.g: src/pages/${pageName}/model.ts
 | ||||||
|  |       const pageModelFile = path.join(pageNameDir, `model.${this.projectType}`); | ||||||
|  | 
 | ||||||
|  |       const params = { pageName, pageNameDir, pageModelsDir, pageModelFile, pageComponentFiles }; | ||||||
|  | 
 | ||||||
|  |       // generate .ice/pages/${pageName}/store.ts
 | ||||||
|  |       this.renderPageStore(params); | ||||||
|  | 
 | ||||||
|  |       // generate .ice/pages/${pageName}/${pageName}.tsx
 | ||||||
|  |       this.renderPageComponent(params); | ||||||
|  | 
 | ||||||
|  |       // generate .ice/pages/${pageName}/componentStore.ts
 | ||||||
|  |       this.renderComponentStore(pageName, pageComponentDir, pageComponentFiles); | ||||||
|  | 
 | ||||||
|  |       // generate .ice/pages/${pageName}/components/${componentName}/model.ts
 | ||||||
|  |       this.renderComponentModel(pageName, pageComponentDir, pageComponentFiles); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ import * as ejs from 'ejs'; | ||||||
| import Generator from './generator'; | import Generator from './generator'; | ||||||
| 
 | 
 | ||||||
| export default async (api) => { | export default async (api) => { | ||||||
|   const { context, getValue, onHook, applyMethod, onGetWebpackConfig } = api; |   const { context, getValue, onHook, applyMethod, onGetWebpackConfig, modifyUserConfig } = api; | ||||||
|   const { rootDir, command } = context; |   const { rootDir, command, userConfig } = context; | ||||||
| 
 | 
 | ||||||
|   const targetPath = getValue('ICE_TEMP'); |   const targetPath = getValue('ICE_TEMP'); | ||||||
|   const templatePath = path.join(__dirname, 'template'); |   const templatePath = path.join(__dirname, 'template'); | ||||||
|  | @ -15,8 +15,7 @@ export default async (api) => { | ||||||
|   const typesTemplatePath = path.join(templatePath, 'types.ts.ejs'); |   const typesTemplatePath = path.join(templatePath, 'types.ts.ejs'); | ||||||
|   const projectType = getValue('PROJECT_TYPE'); |   const projectType = getValue('PROJECT_TYPE'); | ||||||
| 
 | 
 | ||||||
|   // copy types/index.ts to .ice/store/index.ts
 |   // set IStore to IAppConfig
 | ||||||
|   await fse.copy(path.join(__dirname, '..', 'src/types'), path.join(targetPath, './store')); |  | ||||||
|   applyMethod('addIceTypesExport', { source: './store', specifier: '{ IStore }', exportName: 'store?: IStore' }); |   applyMethod('addIceTypesExport', { source: './store', specifier: '{ IStore }', exportName: 'store?: IStore' }); | ||||||
| 
 | 
 | ||||||
|   // render template/types.ts.ejs to .ice/store/types.ts
 |   // render template/types.ts.ejs to .ice/store/types.ts
 | ||||||
|  | @ -27,6 +26,24 @@ export default async (api) => { | ||||||
|   fse.writeFileSync(typesTargetPath, content, 'utf-8'); |   fse.writeFileSync(typesTargetPath, content, 'utf-8'); | ||||||
|   applyMethod('addIceTypesExport', { source: './store/types' }); |   applyMethod('addIceTypesExport', { source: './store/types' }); | ||||||
| 
 | 
 | ||||||
|  |   // add babel plugins for ice lazy
 | ||||||
|  |   const { configPath } = userConfig.router || {}; | ||||||
|  |   const { routesPath } = applyMethod('getRoutes', { | ||||||
|  |     rootDir, | ||||||
|  |     tempDir: targetPath, | ||||||
|  |     configPath, | ||||||
|  |     projectType | ||||||
|  |   }); | ||||||
|  |   modifyUserConfig('babelPlugins', | ||||||
|  |     [ | ||||||
|  |       ...(userConfig.babelPlugins as [] || []), | ||||||
|  |       [ | ||||||
|  |         require.resolve('./babelPluginReplacePath'), | ||||||
|  |         { routesPath, alias: userConfig.alias } | ||||||
|  |       ] | ||||||
|  |     ] | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|   onGetWebpackConfig(config => { |   onGetWebpackConfig(config => { | ||||||
|     if (command === 'build') { |     if (command === 'build') { | ||||||
|       config.optimization.minimizer('TerserPlugin').tap(([args]) => [ |       config.optimization.minimizer('TerserPlugin').tap(([args]) => [ | ||||||
|  | @ -38,8 +55,7 @@ export default async (api) => { | ||||||
|       ]); |       ]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     config.resolve.alias.set('$ice/appStore', path.join(targetPath, 'appStore.ts')); |     config.resolve.alias.set('$ice/store', path.join(targetPath, 'store', 'index.ts')); | ||||||
|     config.resolve.alias.set('$ice/pageStores', path.join(targetPath, 'pageStores.ts')); |  | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   const gen = new Generator({ |   const gen = new Generator({ | ||||||
|  |  | ||||||
|  | @ -1,26 +1,7 @@ | ||||||
| import * as React from 'react'; | import * as React from 'react'; | ||||||
| import AppStore from '$ice/appStore'; | import AppStore from '$ice/store'; | ||||||
| import PageStores from '$ice/pageStores'; |  | ||||||
| 
 | 
 | ||||||
| const wrapperComponent = (PageComponent) => { | export default ({ addProvider, appConfig, context }) => { | ||||||
|   const { pageConfig = {} } = PageComponent; |  | ||||||
|   const StoreWrapperedComponent = (props) => { |  | ||||||
|     const pageComponentName = pageConfig.componentName; |  | ||||||
|     const PageStore = PageStores[pageComponentName]; |  | ||||||
|     if (PageStore) { |  | ||||||
|       return ( |  | ||||||
|         <PageStore.Provider initialStates={pageConfig.initialStates}> |  | ||||||
|           <PageComponent {...props}/> |  | ||||||
|         </PageStore.Provider> |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
|     return <PageComponent {...props} />; |  | ||||||
|   }; |  | ||||||
|   return StoreWrapperedComponent; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export default ({ addProvider, wrapperRouteComponent, appConfig, context }) => { |  | ||||||
|   wrapperRouteComponent(wrapperComponent); |  | ||||||
| 
 | 
 | ||||||
|   const StoreProvider = ({children}) => { |   const StoreProvider = ({children}) => { | ||||||
|     const storeConfig = appConfig.store || {}; |     const storeConfig = appConfig.store || {}; | ||||||
|  |  | ||||||
|  | @ -1,20 +1,28 @@ | ||||||
| <% if (importStr) { %> | <% if (importStr) { %> | ||||||
| import { createStore, IcestoreRootState, IcestoreDispatch, Models } from '@ice/store'; |   import { createStore, IcestoreRootState, IcestoreDispatch, Models } from '@ice/store'; | ||||||
| <%- importStr %> |   <%- importStr %> | ||||||
| 
 | 
 | ||||||
| interface AppModel extends Models { |   interface AppModel extends Models { | ||||||
|     <% modelsStr.split(',').forEach(function(model){ %> |     <% modelsStr.split(',').forEach(function(model){ %> | ||||||
|       <% if (model) { %> |       <% if (model) { %> | ||||||
|         <%- model %>: typeof <%- model %>; |         <%- model %>: typeof <%- model %>; | ||||||
|       <% } %> |       <% } %> | ||||||
|     <% }); %> |     <% }); %> | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const appModel: AppModel = { <%- modelsStr %> }; | ||||||
|  |   const store = createStore(appModel); | ||||||
|  |   export default store; | ||||||
|  | 
 | ||||||
|  |   export type IRootDispatch = IcestoreDispatch<typeof appModel>; | ||||||
|  |   export type IRootState = IcestoreRootState<typeof appModel>; | ||||||
|  | <% } %> | ||||||
|  | 
 | ||||||
|  | interface IInitialStates { | ||||||
|  |   [key: string]: any; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const appModel: AppModel = { <%- modelsStr %> }; | export interface IStore { | ||||||
| 
 |   initialStates?: IInitialStates; | ||||||
| const store = createStore(appModel); |   getInitialStates?: (initialData) => IInitialStates; | ||||||
| export default store; | } | ||||||
| 
 |  | ||||||
| export type IRootDispatch = IcestoreDispatch<typeof appModel>; |  | ||||||
| export type IRootState = IcestoreRootState<typeof appModel>; |  | ||||||
| <% } %> |  | ||||||
|  |  | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | // .ice/pages/components/Todo/store.ts | ||||||
|  | import store from '../../componentStore' | ||||||
|  | 
 | ||||||
|  | const modelName = '<%= modelName %>'; | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   useValue() { | ||||||
|  |     return store.useModel(modelName) | ||||||
|  |   }, | ||||||
|  |   useState() { | ||||||
|  |     return store.useModelState(modelName) | ||||||
|  |   }, | ||||||
|  |   useDispatchers() { | ||||||
|  |     return store.useModelDispatchers(modelName) | ||||||
|  |   }, | ||||||
|  |   getValue() { | ||||||
|  |     return store.getModel(modelName) | ||||||
|  |   }, | ||||||
|  |   getState() { | ||||||
|  |     return store.getModelState(modelName) | ||||||
|  |   }, | ||||||
|  |   getDispatchers() { | ||||||
|  |     return store.getModelDispatchers(modelName) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | <% if (importStr) { %> | ||||||
|  | import { createStore } from '@ice/store'; | ||||||
|  | <%- importStr %> | ||||||
|  | 
 | ||||||
|  | const models = { <%- modelsStr %> } | ||||||
|  | const store = createStore(models); | ||||||
|  | export default store; | ||||||
|  | <% } %> | ||||||
|  | @ -0,0 +1,53 @@ | ||||||
|  | import * as React from 'react'; | ||||||
|  | <%- pageComponentImport %> | ||||||
|  | 
 | ||||||
|  | <% if(hasPageStore) { %> | ||||||
|  |   import store from './store'; | ||||||
|  | <% } %> | ||||||
|  | 
 | ||||||
|  | <% if(hasComponentStore) { %> | ||||||
|  |   import componentStore from './componentStore'; | ||||||
|  | <% } %> | ||||||
|  | 
 | ||||||
|  | const PageComponentName = <%= pageComponentExport %>; | ||||||
|  | 
 | ||||||
|  | <% if(hasPageStore || hasComponentStore) { %> | ||||||
|  |   let PageProvider = null; | ||||||
|  |   let ComponentProvider = null; | ||||||
|  | 
 | ||||||
|  |   <% if(hasPageStore) { %> | ||||||
|  |     PageProvider = store.Provider; | ||||||
|  |   <% } %> | ||||||
|  | 
 | ||||||
|  |   <% if(hasComponentStore) { %> | ||||||
|  |     ComponentProvider = componentStore.Provider; | ||||||
|  |   <% } %> | ||||||
|  | 
 | ||||||
|  |   const StoreWrapperedPage = () => getComponent(PageProvider, ComponentProvider); | ||||||
|  |   StoreWrapperedPage.pageConfig = PageComponentName.pageConfig || {}; | ||||||
|  |   export default StoreWrapperedPage; | ||||||
|  | <% } else { %> | ||||||
|  |   export default PageComponentName; | ||||||
|  | <% } %> | ||||||
|  | 
 | ||||||
|  | function getComponent(PageProvider, ComponentProvider) { | ||||||
|  |   if (PageProvider && ComponentProvider) { | ||||||
|  |     return ( | ||||||
|  |       <PageProvider> | ||||||
|  |         <ComponentProvider> | ||||||
|  |           <PageComponentName /> | ||||||
|  |         </ComponentProvider> | ||||||
|  |       </PageProvider> | ||||||
|  |     ) | ||||||
|  |   } else if (PageProvider) { | ||||||
|  |     return ( | ||||||
|  |       <PageProvider> | ||||||
|  |         <PageComponentName /> | ||||||
|  |       </PageProvider> | ||||||
|  |     ) | ||||||
|  |   } else if (ComponentProvider) ( | ||||||
|  |     <ComponentProvider> | ||||||
|  |       <PageComponentName /> | ||||||
|  |     </ComponentProvider> | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| <%- importPageStoreStr %> |  | ||||||
| 
 |  | ||||||
| const pageStores = { <%- pageStoreStr %> }; |  | ||||||
| 
 |  | ||||||
| export default pageStores; |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| export interface IInitialStates { |  | ||||||
|   [key: string]: any; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface IStore { |  | ||||||
|   initialStates?: IInitialStates; |  | ||||||
|   getInitialStates?: (initialData) => IInitialStates; |  | ||||||
| } |  | ||||||
|  | @ -5,8 +5,7 @@ | ||||||
|     "rootDir": "src", |     "rootDir": "src", | ||||||
|     "outDir": "lib", |     "outDir": "lib", | ||||||
|     "paths": { |     "paths": { | ||||||
|       "$ice/appStore": ["./src/_appStore"], |       "$ice/store": ["./src/_store"] | ||||||
|       "$ice/pageStores": ["./src/_pageStores"] |  | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue