Skip to content

Commit b607b24

Browse files
LeoYuaneternalsky
authored andcommitted
feat: add a new built-in solution icejs3 which is corresponding to the latest icejs framework
1 parent a6e768f commit b607b24

File tree

304 files changed

+19427
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

304 files changed

+19427
-3
lines changed

modules/code-generator/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alilc/lowcode-code-generator",
3-
"version": "1.0.8",
3+
"version": "1.1.0",
44
"description": "出码引擎 for LowCode Engine",
55
"license": "MIT",
66
"main": "lib/index.js",

modules/code-generator/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { createModuleBuilder } from './generator/ModuleBuilder';
99
import { createDiskPublisher } from './publisher/disk';
1010
import { createZipPublisher } from './publisher/zip';
1111
import createIceJsProjectBuilder, { plugins as reactPlugins } from './solutions/icejs';
12+
import createIce3JsProjectBuilder, { plugins as icejs3Plugins } from './solutions/icejs3';
1213
import createRaxAppProjectBuilder, { plugins as raxPlugins } from './solutions/rax-app';
1314

1415
// 引入说明
@@ -32,17 +33,20 @@ import * as CONSTANTS from './const';
3233

3334
// 引入内置解决方案模块
3435
import icejs from './plugins/project/framework/icejs';
36+
import icejs3 from './plugins/project/framework/icejs3';
3537
import rax from './plugins/project/framework/rax';
3638

3739
export default {
3840
createProjectBuilder,
3941
createModuleBuilder,
4042
solutions: {
4143
icejs: createIceJsProjectBuilder,
44+
icejs3: createIce3JsProjectBuilder,
4245
rax: createRaxAppProjectBuilder,
4346
},
4447
solutionParts: {
4548
icejs,
49+
icejs3,
4650
rax,
4751
},
4852
publishers: {
@@ -74,6 +78,9 @@ export default {
7478
i18n,
7579
utils,
7680
},
81+
icejs3: {
82+
...icejs3Plugins,
83+
},
7784
},
7885
postprocessor: {
7986
prettier,

modules/code-generator/src/plugins/common/esmodule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
IWithDependency,
1717
} from '../../types';
1818

19-
import { isValidIdentifier, isValidComponentName } from '../../utils/validate';
19+
import { isValidIdentifier } from '../../utils/validate';
2020

2121
// TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
2222
const DEP_MAIN_BLOCKLIST = ['lib', 'lib/index', 'es', 'es/index', 'main'];
@@ -261,7 +261,7 @@ function buildPackageImport(
261261
if (!isValidIdentifier(name)) {
262262
throw new CodeGeneratorError(`Invalid Identifier [${name}]`);
263263
}
264-
if (info.nodeIdentifier && !isValidComponentName(info.nodeIdentifier)) {
264+
if (info.nodeIdentifier && !isValidIdentifier(info.nodeIdentifier)) {
265265
throw new CodeGeneratorError(`Invalid Identifier [${info.nodeIdentifier}]`);
266266
}
267267
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import template from './template';
2+
import globalStyle from './plugins/globalStyle';
3+
import packageJSON from './plugins/packageJSON';
4+
import layout from './plugins/layout';
5+
import appConfig from './plugins/appConfig';
6+
import buildConfig from './plugins/buildConfig';
7+
8+
export default {
9+
template,
10+
plugins: {
11+
appConfig,
12+
buildConfig,
13+
globalStyle,
14+
packageJSON,
15+
layout,
16+
},
17+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {
2+
BuilderComponentPlugin,
3+
BuilderComponentPluginFactory,
4+
ChunkType,
5+
FileType,
6+
ICodeStruct,
7+
} from '../../../../../types';
8+
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
9+
10+
export interface AppConfigPluginConfig {
11+
12+
}
13+
14+
function getContent() {
15+
return `import { defineAppConfig } from 'ice';
16+
17+
// App config, see https://v3.ice.work/docs/guide/basic/app
18+
export default defineAppConfig(() => ({
19+
// Set your configs here.
20+
app: {
21+
rootId: 'App',
22+
},
23+
router: {
24+
type: 'browser',
25+
basename: '/',
26+
},
27+
}));`;
28+
}
29+
30+
const pluginFactory: BuilderComponentPluginFactory<AppConfigPluginConfig> = () => {
31+
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
32+
const next: ICodeStruct = {
33+
...pre,
34+
};
35+
36+
next.chunks.push({
37+
type: ChunkType.STRING,
38+
fileType: FileType.TS,
39+
name: COMMON_CHUNK_NAME.FileMainContent,
40+
content: getContent(),
41+
linkAfter: [],
42+
});
43+
44+
return next;
45+
};
46+
47+
return plugin;
48+
};
49+
50+
export default pluginFactory;
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import {
2+
BuilderComponentPlugin,
3+
BuilderComponentPluginFactory,
4+
ChunkType,
5+
FileType,
6+
ICodeStruct,
7+
} from '../../../../../types';
8+
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
9+
import { format } from '../../../../../utils/format';
10+
import { getThemeInfo } from '../../../../../utils/theme';
11+
12+
export interface BuildConfigPluginConfig {
13+
14+
/** 包名 */
15+
themePackage?: string;
16+
}
17+
18+
function getContent(cfg?: BuildConfigPluginConfig, routesContent?: string) {
19+
return `
20+
import { join } from 'path';
21+
import { defineConfig } from '@ice/app';
22+
import _ from 'lodash';
23+
import fusion from '@ice/plugin-fusion';
24+
import locales from '@ice/plugin-moment-locales';
25+
import type { Plugin } from '@ice/app/esm/types';
26+
27+
interface PluginOptions {
28+
id: string;
29+
}
30+
31+
const plugin: Plugin<PluginOptions> = (options) => ({
32+
// name 可选,插件名称
33+
name: 'plugin-name',
34+
// setup 必选,用于定制工程构建配置
35+
setup: ({ onGetConfig, modifyUserConfig }) => {
36+
modifyUserConfig('codeSplitting', 'page');
37+
38+
onGetConfig((config) => {
39+
config.entry = {
40+
web: join(process.cwd(), '.ice/entry.client.tsx'),
41+
};
42+
43+
config.cssFilename = '[name].css';
44+
45+
config.configureWebpack = config.configureWebpack || [];
46+
config.configureWebpack?.push((webpackConfig) => {
47+
if (webpackConfig.output) {
48+
webpackConfig.output.filename = '[name].js';
49+
webpackConfig.output.chunkFilename = '[name].js';
50+
}
51+
return webpackConfig;
52+
});
53+
54+
config.swcOptions = _.merge(config.swcOptions, {
55+
compilationConfig: {
56+
jsc: {
57+
transform: {
58+
react: {
59+
runtime: 'classic',
60+
},
61+
},
62+
},
63+
}
64+
});
65+
66+
// 解决 webpack publicPath 问题
67+
config.transforms = config.transforms || [];
68+
config.transforms.push((source: string, id: string) => {
69+
if (id.includes('.ice/entry.client.tsx')) {
70+
let code = \`
71+
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
72+
// @ts-ignore
73+
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\\\/)[^/]+$/, '$1');
74+
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
75+
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
76+
}
77+
\`;
78+
code += source;
79+
return { code };
80+
}
81+
});
82+
});
83+
},
84+
});
85+
86+
// The project config, see https://v3.ice.work/docs/guide/basic/config
87+
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
88+
export default defineConfig(() => ({
89+
ssr: false,
90+
ssg: false,
91+
minify,
92+
${routesContent}
93+
externals: {
94+
react: 'React',
95+
'react-dom': 'ReactDOM',
96+
'react-dom/client': 'ReactDOM',
97+
'@alifd/next': 'Next',
98+
lodash: 'var window._',
99+
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
100+
},
101+
plugins: [
102+
fusion(${cfg?.themePackage ? `{
103+
importStyle: 'sass',
104+
themePackage: '${getThemeInfo(cfg.themePackage).name}',
105+
}` : `{
106+
importStyle: true,
107+
}`}),
108+
locales(),
109+
plugin(),
110+
]
111+
}));
112+
`;
113+
}
114+
115+
function getRoutesContent(navData: any, needShell = true) {
116+
const routes = [
117+
'routes: {',
118+
' defineRoutes: route => {',
119+
];
120+
function _getRoutes(nav: any, _routes: string[] = []) {
121+
const { slug, children } = nav;
122+
if (children && children.length > 0) {
123+
children.forEach((_nav: any) => _getRoutes(_nav, _routes));
124+
} else if (slug) {
125+
_routes.push(`route('/${slug}', '${slug}/index.jsx');`);
126+
}
127+
}
128+
if (needShell) {
129+
routes.push(" route('/', 'layout.jsx', () => {");
130+
}
131+
navData?.forEach((nav: any) => {
132+
_getRoutes(nav, routes);
133+
});
134+
if (needShell) {
135+
routes.push(' });');
136+
}
137+
routes.push(' }'); // end of defineRoutes
138+
routes.push(' },'); // end of routes
139+
return routes.join('\n');
140+
}
141+
142+
const pluginFactory: BuilderComponentPluginFactory<BuildConfigPluginConfig> = (cfg?) => {
143+
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
144+
const next: ICodeStruct = {
145+
...pre,
146+
};
147+
148+
const { navConfig } = next.contextData;
149+
const routesContent = navConfig?.data ? getRoutesContent(navConfig.data, true) : '';
150+
151+
next.chunks.push({
152+
type: ChunkType.STRING,
153+
fileType: FileType.MTS,
154+
name: COMMON_CHUNK_NAME.FileMainContent,
155+
content: format(getContent(cfg, routesContent)),
156+
linkAfter: [],
157+
});
158+
159+
return next;
160+
};
161+
162+
return plugin;
163+
};
164+
165+
export default pluginFactory;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
2+
3+
import {
4+
BuilderComponentPlugin,
5+
BuilderComponentPluginFactory,
6+
ChunkType,
7+
FileType,
8+
ICodeStruct,
9+
IProjectInfo,
10+
} from '../../../../../types';
11+
12+
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
13+
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
14+
const next: ICodeStruct = {
15+
...pre,
16+
};
17+
18+
const ir = next.ir as IProjectInfo;
19+
20+
next.chunks.push({
21+
type: ChunkType.STRING,
22+
fileType: FileType.SCSS,
23+
name: COMMON_CHUNK_NAME.StyleDepsImport,
24+
content: `
25+
// 引入默认全局样式
26+
@import '@alifd/next/reset.scss';
27+
`,
28+
linkAfter: [],
29+
});
30+
31+
next.chunks.push({
32+
type: ChunkType.STRING,
33+
fileType: FileType.SCSS,
34+
name: COMMON_CHUNK_NAME.StyleCssContent,
35+
content: `
36+
body {
37+
-webkit-font-smoothing: antialiased;
38+
}
39+
`,
40+
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
41+
});
42+
43+
next.chunks.push({
44+
type: ChunkType.STRING,
45+
fileType: FileType.SCSS,
46+
name: COMMON_CHUNK_NAME.StyleCssContent,
47+
content: ir.css || '',
48+
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
49+
});
50+
51+
return next;
52+
};
53+
return plugin;
54+
};
55+
56+
export default pluginFactory;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {
2+
BuilderComponentPlugin,
3+
BuilderComponentPluginFactory,
4+
ChunkType,
5+
FileType,
6+
ICodeStruct,
7+
} from '../../../../../types';
8+
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
9+
10+
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
11+
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
12+
const next: ICodeStruct = {
13+
...pre,
14+
};
15+
16+
next.chunks.push({
17+
type: ChunkType.STRING,
18+
fileType: FileType.JSX,
19+
name: COMMON_CHUNK_NAME.FileMainContent,
20+
content: `
21+
import { Outlet } from 'ice';
22+
import BasicLayout from '@/layouts/BasicLayout';
23+
24+
export default function Layout() {
25+
return (
26+
<BasicLayout>
27+
<Outlet />
28+
</BasicLayout>
29+
);;
30+
}
31+
`,
32+
linkAfter: [],
33+
});
34+
35+
return next;
36+
};
37+
38+
return plugin;
39+
};
40+
41+
export default pluginFactory;

0 commit comments

Comments
 (0)