mirror of https://github.com/alibaba/ice.git
feat: rework entry
This commit is contained in:
parent
6bbc638e45
commit
72a6f3bfb7
|
@ -1,4 +1,20 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { runApp } from 'ice';
|
// import { AppConfig } from 'ice';
|
||||||
|
|
||||||
runApp({});
|
// runApp({
|
||||||
|
// app: {
|
||||||
|
// getInitialData: async (ctx) => {
|
||||||
|
// console.log(ctx);
|
||||||
|
// return {
|
||||||
|
// auth: {
|
||||||
|
// admin: true,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
const appConfig = {
|
||||||
|
|
||||||
|
};
|
||||||
|
export default appConfig;
|
|
@ -30,7 +30,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config }) => {
|
||||||
const webpackPlugins = getTransformPlugins(rootDir, config).map((plugin) => createUnplugin(() => plugin).webpack());
|
const webpackPlugins = getTransformPlugins(rootDir, config).map((plugin) => createUnplugin(() => plugin).webpack());
|
||||||
return {
|
return {
|
||||||
mode,
|
mode,
|
||||||
entry: path.join(rootDir, 'src/app'),
|
entry: path.join(rootDir, '.ice/entry.client'),
|
||||||
externals,
|
externals,
|
||||||
output: {
|
output: {
|
||||||
publicPath,
|
publicPath,
|
||||||
|
@ -44,6 +44,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config }) => {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
ice: path.join(rootDir, '.ice', 'index.ts'),
|
ice: path.join(rootDir, '.ice', 'index.ts'),
|
||||||
|
'@': path.join(rootDir, 'src'),
|
||||||
...alias,
|
...alias,
|
||||||
},
|
},
|
||||||
extensions: ['.ts', '.tsx', '.jsx', '...'],
|
extensions: ['.ts', '.tsx', '.jsx', '...'],
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"@builder/pack": "^0.6.0",
|
"@builder/pack": "^0.6.0",
|
||||||
"@builder/webpack-config": "^3.0.0",
|
"@builder/webpack-config": "^3.0.0",
|
||||||
"@ice/plugin-app": "^1.0.0",
|
"@ice/plugin-app": "^1.0.0",
|
||||||
|
"@ice/plugin-auth": "^1.0.0",
|
||||||
"@ice/plugin-router": "^1.0.0",
|
"@ice/plugin-router": "^1.0.0",
|
||||||
"@ice/runtime": "^1.0.0",
|
"@ice/runtime": "^1.0.0",
|
||||||
"address": "^1.1.2",
|
"address": "^1.1.2",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import * as path from 'path';
|
||||||
import consola from 'consola';
|
import consola from 'consola';
|
||||||
import type { Context } from 'build-scripts';
|
import type { Context } from 'build-scripts';
|
||||||
import type { StatsError } from 'webpack';
|
import type { StatsError } from 'webpack';
|
||||||
|
@ -5,6 +6,7 @@ import webpackCompiler from '../service/webpackCompiler.js';
|
||||||
import formatWebpackMessages from '../utils/formatWebpackMessages.js';
|
import formatWebpackMessages from '../utils/formatWebpackMessages.js';
|
||||||
import { getWebpackConfig, getTransformPlugins } from '@builder/webpack-config';
|
import { getWebpackConfig, getTransformPlugins } from '@builder/webpack-config';
|
||||||
import type { Config } from '@ice/types';
|
import type { Config } from '@ice/types';
|
||||||
|
import { config } from 'process';
|
||||||
|
|
||||||
const build = async (context: Context<any>) => {
|
const build = async (context: Context<any>) => {
|
||||||
const { getConfig, applyHook, commandArgs, command } = context;
|
const { getConfig, applyHook, commandArgs, command } = context;
|
||||||
|
@ -14,11 +16,17 @@ const build = async (context: Context<any>) => {
|
||||||
await applyHook('error', { err: new Error(errMsg) });
|
await applyHook('error', { err: new Error(errMsg) });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform config to webpack config
|
// transform config to webpack config
|
||||||
const webpackConfig = configs.map((task) => {
|
const webpackConfig = configs.map((task) => {
|
||||||
|
const { config } = task;
|
||||||
|
config.alias = {
|
||||||
|
...config.alias,
|
||||||
|
'@ice/plugin-auth/runtime': path.join(require.resolve('@ice/plugin-auth'), '../../runtime'),
|
||||||
|
};
|
||||||
return getWebpackConfig({
|
return getWebpackConfig({
|
||||||
rootDir,
|
rootDir,
|
||||||
config: task.config,
|
config,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const transformPlugins = getTransformPlugins(rootDir, configs.find(({ name }) => name === 'web').config);
|
const transformPlugins = getTransformPlugins(rootDir, configs.find(({ name }) => name === 'web').config);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { createRequire } from 'module';
|
||||||
|
import * as path from 'path';
|
||||||
import WebpackDevServer from 'webpack-dev-server';
|
import WebpackDevServer from 'webpack-dev-server';
|
||||||
import type { Context } from 'build-scripts';
|
import type { Context } from 'build-scripts';
|
||||||
import { getWebpackConfig, getTransformPlugins } from '@builder/webpack-config';
|
import { getWebpackConfig, getTransformPlugins } from '@builder/webpack-config';
|
||||||
|
@ -6,6 +8,7 @@ import webpackCompiler from '../service/webpackCompiler.js';
|
||||||
import prepareURLs from '../utils/prepareURLs.js';
|
import prepareURLs from '../utils/prepareURLs.js';
|
||||||
import type { Config } from '@ice/types';
|
import type { Config } from '@ice/types';
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
const { defaultsDeep } = lodash;
|
const { defaultsDeep } = lodash;
|
||||||
|
|
||||||
interface IWebTaskConfig {
|
interface IWebTaskConfig {
|
||||||
|
@ -32,6 +35,13 @@ const start = async (context: Context<any>) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { config } = webConfig as IWebTaskConfig;
|
const { config } = webConfig as IWebTaskConfig;
|
||||||
|
config.alias = {
|
||||||
|
...config.alias,
|
||||||
|
// TODO: 放在各自插件里还是放在 ice 里?
|
||||||
|
// TODO: make pkg.json exports works; build 复用逻辑
|
||||||
|
// '@ice/plugin-auth/runtime': require.resolve('@ice/plugin-auth/runtime'),
|
||||||
|
'@ice/plugin-auth/runtime': path.join(require.resolve('@ice/plugin-auth'), '../../runtime'),
|
||||||
|
};
|
||||||
|
|
||||||
// transform config to webpack config
|
// transform config to webpack config
|
||||||
const webpackConfig = getWebpackConfig({
|
const webpackConfig = getWebpackConfig({
|
||||||
|
|
|
@ -64,6 +64,7 @@ const getBuiltInPlugins: IGetBuiltInPlugins = (userConfig) => {
|
||||||
// react base plugin
|
// react base plugin
|
||||||
require.resolve('@ice/plugin-app'),
|
require.resolve('@ice/plugin-app'),
|
||||||
require.resolve('@ice/plugin-router'),
|
require.resolve('@ice/plugin-router'),
|
||||||
|
require.resolve('@ice/plugin-auth'),
|
||||||
// for ice/react plugins
|
// for ice/react plugins
|
||||||
/* 'build-plugin-ice-config',
|
/* 'build-plugin-ice-config',
|
||||||
'build-plugin-ice-mpa',
|
'build-plugin-ice-mpa',
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { runApp } from '@ice/runtime';
|
||||||
|
import appConfig from '@/app';
|
||||||
|
import runtimeModules from './runtimeModules';
|
||||||
|
import routes from './routes';
|
||||||
|
|
||||||
|
runApp(appConfig, runtimeModules, routes);
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { runServerApp } from '@ice/runtime';
|
||||||
|
import appConfig from '@/app';
|
||||||
|
import runtimeModules from './runtimeModules';
|
||||||
|
import routes from './routes';
|
||||||
|
|
||||||
|
export async function render() {
|
||||||
|
return await runServerApp(appConfig, runtimeModules, routes);
|
||||||
|
}
|
|
@ -4,5 +4,4 @@
|
||||||
export {
|
export {
|
||||||
<%- framework.exports %>
|
<%- framework.exports %>
|
||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
export * from './runApp';
|
|
|
@ -1,13 +0,0 @@
|
||||||
<% const moduleNames = []; %>
|
|
||||||
<% if (runtimeModules.length) {%>
|
|
||||||
<% runtimeModules.filter((moduleInfo) => !moduleInfo.staticModule).forEach((runtimeModule, index) => { %>
|
|
||||||
<% moduleNames.push('module' + index) %>import module<%= index %> from '<%= runtimeModule.path %>';<% }) %><% } %>
|
|
||||||
import type { Runtime } from '@ice/runtime';
|
|
||||||
|
|
||||||
function loadRuntimeModules(runtime: Runtime) {
|
|
||||||
<% if (moduleNames.length) {%>
|
|
||||||
<% moduleNames.forEach((name) => { %>runtime.loadModule(<%= name%>);<% }) %>
|
|
||||||
<% } %>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default loadRuntimeModules;
|
|
|
@ -1,14 +0,0 @@
|
||||||
<% const moduleNames = []; %>
|
|
||||||
<% if (runtimeModules.length) {%>
|
|
||||||
<% runtimeModules.filter((moduleInfo) => moduleInfo.staticModule).forEach((runtimeModule, index) => { %>
|
|
||||||
<% moduleNames.push('module' + index) %>import module<%= index %> from '<%= runtimeModule.path %>';<% }) %>
|
|
||||||
<% } %>
|
|
||||||
import type { AppConfig } from './types';
|
|
||||||
|
|
||||||
function loadStaticModules(appConfig: AppConfig) {
|
|
||||||
<% if (moduleNames.length) {%>
|
|
||||||
<% moduleNames.forEach((name) => { %><%= name%>({appConfig});<% }) %>
|
|
||||||
<% } %>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default loadStaticModules;
|
|
|
@ -1,40 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { Runtime, App, render } from '@ice/runtime';
|
|
||||||
import type { BuildConfig } from '@ice/runtime';
|
|
||||||
import loadStaticModules from './loadStaticModules';
|
|
||||||
import loadRuntimeModules from './loadRuntimeModules';
|
|
||||||
import type { AppConfig } from './types';
|
|
||||||
import routes from './routes';
|
|
||||||
|
|
||||||
export function runApp(config: AppConfig = {}) {
|
|
||||||
const appConfig = {
|
|
||||||
...config,
|
|
||||||
app: {
|
|
||||||
rootId: 'root',
|
|
||||||
strict: true,
|
|
||||||
...(config?.app || {}),
|
|
||||||
},
|
|
||||||
router: {
|
|
||||||
type: 'hash',
|
|
||||||
...(config?.router || {}),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loadStaticModules(appConfig);
|
|
||||||
// TODO generate buildConfig
|
|
||||||
const buildConfig: BuildConfig = {
|
|
||||||
ssr: false,
|
|
||||||
};
|
|
||||||
// TODO create context
|
|
||||||
const context: Context = {
|
|
||||||
routes,
|
|
||||||
};
|
|
||||||
|
|
||||||
const runtime = new Runtime(appConfig, buildConfig, context);
|
|
||||||
|
|
||||||
runtime.setRenderApp((args) => {
|
|
||||||
return <App {...args} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
loadRuntimeModules(runtime);
|
|
||||||
render(runtime);
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<% const moduleNames = []; %>
|
||||||
|
<% if (runtimeModules.length) {%>
|
||||||
|
<% runtimeModules.filter((moduleInfo) => !moduleInfo.staticModule).forEach((runtimeModule, index) => { %>
|
||||||
|
<% moduleNames.push('module' + index) %>import module<%= index %> from '<%= runtimeModule.path %>';
|
||||||
|
<% }) %>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
const modules = [
|
||||||
|
<% moduleNames.forEach((moduleName, index) => { %>
|
||||||
|
<%= moduleName %>,
|
||||||
|
<% }) %>
|
||||||
|
];
|
||||||
|
|
||||||
|
export default modules;
|
|
@ -1,21 +1,15 @@
|
||||||
|
import type { AppConfig as DefaultAppConfig } from '@ice/runtime';
|
||||||
|
|
||||||
<%- configTypes.imports %>
|
<%- configTypes.imports %>
|
||||||
|
|
||||||
export interface App {
|
|
||||||
rootId?: string;
|
|
||||||
mountNode?: HTMLElement;
|
|
||||||
renderComponent?: ComponentType;
|
|
||||||
}
|
|
||||||
<% if (configTypes.imports) {%>
|
<% if (configTypes.imports) {%>
|
||||||
interface ExtendsAppConfig {
|
interface ExtendsAppConfig extends DefaultAppConfig {
|
||||||
<% if (configTypes.imports) { %>
|
<% if (configTypes.imports) { %>
|
||||||
<%- configTypes.exports %>
|
<%- configTypes.exports %>
|
||||||
<% } %>
|
<% } %>
|
||||||
};
|
};
|
||||||
export type AppConfig = Omit<ExtendsAppConfig, 'app'> & {
|
|
||||||
app?: App & ('app' extends keyof ExtendsAppConfig ? ExtendsAppConfig['app'] : {});
|
export type AppConfig = ExtendsAppConfig;
|
||||||
}
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
export interface AppConfig {
|
export type AppConfig = DefaultAppConfig;
|
||||||
app?: App;
|
|
||||||
}
|
|
||||||
<% } %>
|
<% } %>
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.0
|
|
@ -0,0 +1 @@
|
||||||
|
# `plugin-auth`
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "@ice/plugin-auth",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
|
"main": "./esm/index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./esm/index.js",
|
||||||
|
"./runtime": "./runtime"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"esm",
|
||||||
|
"runtime",
|
||||||
|
"!esm/**/*.map"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@ice/types": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">16.0.0",
|
||||||
|
"react-dom": ">16.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "https://github.com/ice-lab/ice-next/tree/master/packages/plugin-auth"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { createContext, useState, useContext } from 'react';
|
||||||
|
import type { FC } from 'react';
|
||||||
|
import type { ContextType, AuthType } from './types';
|
||||||
|
|
||||||
|
const Context = createContext<any>(null);
|
||||||
|
|
||||||
|
interface ProviderProps {
|
||||||
|
value: AuthType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InjectProps {
|
||||||
|
auth: ContextType[0];
|
||||||
|
useAuth: ContextType[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const AuthProvider: FC<ProviderProps> = ({ value = {}, children }) => {
|
||||||
|
const [state, setState] = useState<AuthType>(value);
|
||||||
|
const updateState: InjectProps['useAuth'] = (newState = {}) => {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
...newState,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return <Context.Provider value={[state, updateState]}>{children}</Context.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useAuth = (): ContextType => {
|
||||||
|
const value = useContext(Context);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// class 组件支持 Hoc 用法
|
||||||
|
function withAuth<Props extends InjectProps>(Component: React.ComponentType<Props>) {
|
||||||
|
type OriginalProps = Omit<Props, keyof InjectProps>;
|
||||||
|
const AuthWrapped = (props: OriginalProps) => {
|
||||||
|
const [auth, setAuth] = useAuth();
|
||||||
|
const WrappedComponent = Component as React.ComponentType<OriginalProps>;
|
||||||
|
return <WrappedComponent {...props} auth={auth} setAuth={setAuth} />;
|
||||||
|
};
|
||||||
|
return AuthWrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useAuth, withAuth, AuthProvider };
|
|
@ -0,0 +1,52 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import type { RuntimePlugin } from '@ice/types';
|
||||||
|
import { AuthProvider, useAuth } from './Auth';
|
||||||
|
import type { IAuth } from './types';
|
||||||
|
|
||||||
|
const wrapperComponentFn = (authConfig: IAuth) => (PageComponent) => {
|
||||||
|
const { pageConfig = {} } = PageComponent;
|
||||||
|
|
||||||
|
const AuthWrappedComponent = (props) => {
|
||||||
|
const [auth] = useAuth();
|
||||||
|
const pageConfigAuth = pageConfig.auth;
|
||||||
|
|
||||||
|
if (pageConfigAuth && !Array.isArray(pageConfigAuth)) {
|
||||||
|
throw new Error('pageConfig.auth must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasAuth =
|
||||||
|
Array.isArray(pageConfigAuth) && pageConfigAuth.length
|
||||||
|
? Object.keys(auth).filter((item) =>
|
||||||
|
(pageConfigAuth.includes(item) ? auth[item] : false),
|
||||||
|
).length
|
||||||
|
: true;
|
||||||
|
|
||||||
|
if (!hasAuth) {
|
||||||
|
if (authConfig.NoAuthFallback) {
|
||||||
|
if (typeof authConfig.NoAuthFallback === 'function') {
|
||||||
|
return <authConfig.NoAuthFallback {...Object.assign({}, props, { pageConfig })} />;
|
||||||
|
}
|
||||||
|
return authConfig.NoAuthFallback;
|
||||||
|
}
|
||||||
|
return <>No Auth</>;
|
||||||
|
}
|
||||||
|
return <PageComponent {...props} />;
|
||||||
|
};
|
||||||
|
return AuthWrappedComponent;
|
||||||
|
};
|
||||||
|
|
||||||
|
const runtime: RuntimePlugin = ({ context, appConfig, addProvider, wrapperPageComponent }) => {
|
||||||
|
const initialData = context && context.initialData ? context.initialData : {};
|
||||||
|
const initialAuth = initialData.auth || {};
|
||||||
|
const authConfig = appConfig.auth || {};
|
||||||
|
|
||||||
|
// TODO: React Devtools 里多一层
|
||||||
|
const AuthStoreProvider = ({ children }) => {
|
||||||
|
return <AuthProvider value={initialAuth}>{children}</AuthProvider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
addProvider(AuthStoreProvider);
|
||||||
|
wrapperPageComponent(wrapperComponentFn(authConfig));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default runtime;
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface IAuth {
|
||||||
|
NoAuthFallback?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AuthType = Record<string, boolean>;
|
||||||
|
export type ContextType = [AuthType, React.Dispatch<React.SetStateAction<AuthType>>];
|
|
@ -0,0 +1,24 @@
|
||||||
|
import type { Plugin } from '@ice/types';
|
||||||
|
|
||||||
|
const plugin: Plugin = ({ generator }) => {
|
||||||
|
// 注册 API:import { useAuth, withAuth } from 'ice';
|
||||||
|
generator.addExport({
|
||||||
|
specifier: ['withAuth', 'useAuth'],
|
||||||
|
source: '@ice/plugin-auth/runtime/Auth',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注册类型:appConfig.auth
|
||||||
|
// export interface IAppConfig {
|
||||||
|
// auth?: IAuth;
|
||||||
|
// }
|
||||||
|
generator.addConfigTypes({
|
||||||
|
specifier: ['IAuth'],
|
||||||
|
source: '@ice/plugin-auth/runtime/types',
|
||||||
|
type: true,
|
||||||
|
exportAlias: {
|
||||||
|
IAuth: 'auth?',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default plugin;
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "esm",
|
||||||
|
"jsx": "react"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ const runtime: RuntimePlugin = ({ setRenderApp }) => {
|
||||||
// setRenderApp(({ renderComponent }) => {
|
// setRenderApp(({ renderComponent }) => {
|
||||||
// return renderComponent || (() => <>empty content</>);
|
// return renderComponent || (() => <>empty content</>);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default runtime;
|
export default runtime;
|
||||||
|
|
|
@ -21,14 +21,14 @@ export default function AppRouter(props: RenderOptions) {
|
||||||
<Routes>
|
<Routes>
|
||||||
{
|
{
|
||||||
routes.map((route, index) => {
|
routes.map((route, index) => {
|
||||||
const RouteComponent = route.component;
|
const PageComponent = route.component;
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
key={index}
|
key={index}
|
||||||
path={route.path}
|
path={route.path}
|
||||||
element={
|
element={
|
||||||
<React.Suspense fallback={<>loading chunk....</>}>
|
<React.Suspense fallback={<>loading chunk....</>}>
|
||||||
<RouteComponent />
|
<PageComponent />
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import type { Context } from './types';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
context: Context;
|
||||||
|
// pageWrappers: React.ComponentType<any>[];
|
||||||
|
PageComponent: React.ComponentType<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RouteItem(props: Props) {
|
||||||
|
const { context, PageComponent } = props;
|
||||||
|
// const Wrapper = pageWrappers[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Suspense fallback={<>loading chunk....</>}>
|
||||||
|
{/* {
|
||||||
|
(pageWrappers || []).reduce((Prev, Curr) => {
|
||||||
|
// const compose = curr(acc);
|
||||||
|
// if (acc.pageConfig) {
|
||||||
|
// compose.pageConfig = acc.pageConfig;
|
||||||
|
// }
|
||||||
|
// if (acc.getInitialProps) {
|
||||||
|
// compose.getInitialProps = acc.getInitialProps;
|
||||||
|
// }
|
||||||
|
return <Prev><Curr /></Prev>;
|
||||||
|
}, PageComponent)
|
||||||
|
} */}
|
||||||
|
{/* <Wrapper> */}
|
||||||
|
<PageComponent />
|
||||||
|
{/* </Wrapper> */}
|
||||||
|
</React.Suspense>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,19 +1,24 @@
|
||||||
import Runtime from './runtime.js';
|
import Runtime from './runtime.js';
|
||||||
import App from './App.js';
|
import App from './App.js';
|
||||||
import render from './render.js';
|
import render from './render.js';
|
||||||
|
import runApp from './runApp.js';
|
||||||
|
import runServerApp from './runServerApp.js';
|
||||||
import {
|
import {
|
||||||
RuntimePlugin,
|
RuntimePlugin,
|
||||||
Context,
|
Context,
|
||||||
BuildConfig,
|
BuildConfig,
|
||||||
|
AppConfig,
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Runtime,
|
Runtime,
|
||||||
App,
|
App,
|
||||||
render,
|
render,
|
||||||
|
runApp,
|
||||||
|
runServerApp,
|
||||||
// types
|
// types
|
||||||
RuntimePlugin,
|
RuntimePlugin,
|
||||||
BuildConfig,
|
BuildConfig,
|
||||||
Context,
|
Context,
|
||||||
|
AppConfig,
|
||||||
};
|
};
|
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import Runtime from './runtime.js';
|
||||||
|
import App from './App.js';
|
||||||
|
import render from './render.js';
|
||||||
|
import type { BuildConfig, Context, InitialContext, AppConfig } from './types';
|
||||||
|
|
||||||
|
export default async function runApp(config: AppConfig, runtimeModules, routes) {
|
||||||
|
const appConfig: AppConfig = {
|
||||||
|
...config,
|
||||||
|
app: {
|
||||||
|
rootId: 'root',
|
||||||
|
strict: true,
|
||||||
|
...(config?.app || {}),
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
type: 'hash',
|
||||||
|
...(config?.router || {}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// loadStaticModules(appConfig);
|
||||||
|
|
||||||
|
// TODO generate buildConfig
|
||||||
|
const buildConfig: BuildConfig = {};
|
||||||
|
|
||||||
|
const context: Context = {
|
||||||
|
routes,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ssr enabled and the server has returned data
|
||||||
|
if ((window as any).__ICE_APP_DATA__) {
|
||||||
|
context.initialData = (window as any).__ICE_APP_DATA__;
|
||||||
|
// context.pageInitialProps = (window as any).__ICE_PAGE_PROPS__;
|
||||||
|
} else if (appConfig?.app?.getInitialData) {
|
||||||
|
const { href, origin, pathname, search } = window.location;
|
||||||
|
const path = href.replace(origin, '');
|
||||||
|
// const query = queryString.parse(search);
|
||||||
|
const query = {};
|
||||||
|
const ssrError = (window as any).__ICE_SSR_ERROR__;
|
||||||
|
const initialContext: InitialContext = {
|
||||||
|
pathname,
|
||||||
|
path,
|
||||||
|
query,
|
||||||
|
ssrError,
|
||||||
|
};
|
||||||
|
context.initialData = await appConfig.app.getInitialData(initialContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtime = new Runtime(appConfig, buildConfig, context);
|
||||||
|
runtime.setRenderApp((args) => {
|
||||||
|
return <App {...args} />;
|
||||||
|
});
|
||||||
|
|
||||||
|
runtimeModules.forEach(m => {
|
||||||
|
runtime.loadModule(m);
|
||||||
|
});
|
||||||
|
|
||||||
|
render(runtime);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
export default async function runServerApp(appConfig, runtimeModules, routes) {
|
||||||
|
|
||||||
|
}
|
|
@ -1,20 +1,19 @@
|
||||||
import type { ComponentType } from 'react';
|
import type { ComponentType, ReactNode } from 'react';
|
||||||
import { RouterProps } from 'react-router-dom';
|
|
||||||
type VoidFunction = () => void;
|
type VoidFunction = () => void;
|
||||||
type AppLifecycle = 'onShow' | 'onHide' | 'onPageNotFound' | 'onShareAppMessage' | 'onUnhandledRejection' | 'onLaunch' | 'onError' | 'onTabItemClick';
|
type AppLifecycle = 'onShow' | 'onHide' | 'onPageNotFound' | 'onShareAppMessage' | 'onUnhandledRejection' | 'onLaunch' | 'onError' | 'onTabItemClick';
|
||||||
type App = Partial<{
|
type App = Partial<{
|
||||||
rootId: string;
|
rootId?: string;
|
||||||
strict: boolean;
|
strict?: boolean;
|
||||||
|
addProvider?: ({ children }: { children: ReactNode }) => ReactNode;
|
||||||
|
getInitialData?: (ctx?: any) => Promise<any>;
|
||||||
} & Record<AppLifecycle, VoidFunction>>;
|
} & Record<AppLifecycle, VoidFunction>>;
|
||||||
|
|
||||||
interface Router {
|
|
||||||
type: 'hash' | 'browser';
|
|
||||||
basename: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AppConfig extends Record<string, any> {
|
export interface AppConfig extends Record<string, any> {
|
||||||
app: App;
|
app?: App;
|
||||||
router: Router;
|
router?: {
|
||||||
|
type: 'hash' | 'browser';
|
||||||
|
basename?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// simplify page item type while it has been defined in plugin-router
|
// simplify page item type while it has been defined in plugin-router
|
||||||
export interface DOMRender {
|
export interface DOMRender {
|
||||||
|
@ -47,10 +46,17 @@ export interface BuildConfig extends Record<string, any> {
|
||||||
target?: string[];
|
target?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getInitialData: (ctx: InitialContext) => {}
|
||||||
|
export interface InitialContext {
|
||||||
|
pathname: string;
|
||||||
|
path: string;
|
||||||
|
query: Record<string, any>;
|
||||||
|
ssrError?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Context {
|
export interface Context {
|
||||||
appManifest?: Record<string, any>;
|
appManifest?: Record<string, any>;
|
||||||
routes?: Routes;
|
routes?: Routes;
|
||||||
initialContext?: Record<string, any>;
|
|
||||||
initialData?: any;
|
initialData?: any;
|
||||||
}
|
}
|
||||||
export interface RuntimeAPI {
|
export interface RuntimeAPI {
|
||||||
|
|
|
@ -29,7 +29,7 @@ export type ParseRenderData = () => Record<string, unknown>;
|
||||||
export type GenerateImportStr = (apiName: string) => string;
|
export type GenerateImportStr = (apiName: string) => string;
|
||||||
export type Render = () => void;
|
export type Render = () => void;
|
||||||
export type ModifyRenderData = (registration: RenderDataRegistration) => void;
|
export type ModifyRenderData = (registration: RenderDataRegistration) => void;
|
||||||
export type AddRenderFile = (templatePath: string, targetPath: string, extraData: ExtraData) => void;
|
export type AddRenderFile = (templatePath: string, targetPath: string, extraData?: ExtraData) => void;
|
||||||
export type AddTemplateFiles = (templateOptions: string | TemplateOptions, extraData?: ExtraData) => void;
|
export type AddTemplateFiles = (templateOptions: string | TemplateOptions, extraData?: ExtraData) => void;
|
||||||
export type RenderFile = (templatePath: string, targetDir: string, extraData?: ExtraData) => void;
|
export type RenderFile = (templatePath: string, targetDir: string, extraData?: ExtraData) => void;
|
||||||
export type AddDisableRuntimePlugin = (pluginName: string) => void;
|
export type AddDisableRuntimePlugin = (pluginName: string) => void;
|
||||||
|
|
|
@ -109,6 +109,7 @@ importers:
|
||||||
'@builder/pack': ^0.6.0
|
'@builder/pack': ^0.6.0
|
||||||
'@builder/webpack-config': ^3.0.0
|
'@builder/webpack-config': ^3.0.0
|
||||||
'@ice/plugin-app': ^1.0.0
|
'@ice/plugin-app': ^1.0.0
|
||||||
|
'@ice/plugin-auth': workspace:^1.0.0
|
||||||
'@ice/plugin-router': ^1.0.0
|
'@ice/plugin-router': ^1.0.0
|
||||||
'@ice/runtime': ^1.0.0
|
'@ice/runtime': ^1.0.0
|
||||||
'@ice/types': ^1.0.0
|
'@ice/types': ^1.0.0
|
||||||
|
@ -134,6 +135,7 @@ importers:
|
||||||
'@builder/pack': 0.6.0
|
'@builder/pack': 0.6.0
|
||||||
'@builder/webpack-config': link:../build-webpack-config
|
'@builder/webpack-config': link:../build-webpack-config
|
||||||
'@ice/plugin-app': link:../plugin-app
|
'@ice/plugin-app': link:../plugin-app
|
||||||
|
'@ice/plugin-auth': link:../plugin-auth
|
||||||
'@ice/plugin-router': link:../plugin-router
|
'@ice/plugin-router': link:../plugin-router
|
||||||
'@ice/runtime': link:../runtime
|
'@ice/runtime': link:../runtime
|
||||||
address: 1.1.2
|
address: 1.1.2
|
||||||
|
@ -176,6 +178,12 @@ importers:
|
||||||
'@types/react': 17.0.39
|
'@types/react': 17.0.39
|
||||||
'@types/react-dom': 17.0.11
|
'@types/react-dom': 17.0.11
|
||||||
|
|
||||||
|
packages/plugin-auth:
|
||||||
|
specifiers:
|
||||||
|
'@ice/types': workspace:^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@ice/types': link:../types
|
||||||
|
|
||||||
packages/plugin-router:
|
packages/plugin-router:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@ice/types': ^1.0.0
|
'@ice/types': ^1.0.0
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
{ "path": "packages/build-webpack-config" },
|
{ "path": "packages/build-webpack-config" },
|
||||||
{ "path": "packages/plugin-app"},
|
{ "path": "packages/plugin-app"},
|
||||||
{ "path": "packages/ice" },
|
{ "path": "packages/ice" },
|
||||||
{ "path": "packages/plugin-router" }
|
{ "path": "packages/plugin-router" },
|
||||||
|
{ "path": "packages/plugin-auth" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue