mirror of https://github.com/alibaba/ice.git
commit
df7a474973
|
|
@ -7,65 +7,34 @@ find the full documentation for it [in our repository](https://github.com/change
|
|||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
||||
|
||||
|
||||
## Add A Changeset
|
||||
|
||||
After you have completed a feature or fixed a bug, you need to do three things:
|
||||
Read the [documentation](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md) for more detail.
|
||||
|
||||
- Select which packages should be released
|
||||
- Bump released packages version
|
||||
- Write Changelog for the released packages
|
||||
## Publish Snapshot Version
|
||||
|
||||
You can follow these steps:
|
||||
- Run the command line script `npm run changeset`
|
||||
- Select the packages you want to include in the changeset using `↑` and `↓` to navigate to packages, and `space` to select a package. Hit enter when all desired packages are selected.
|
||||
- You will be prompted to select a bump type for each selected package. Select an appropriate bump type for the changes made. See here for information on semver versioning
|
||||
- Your final prompt will be to provide a message to go alongside the changeset. This will be written into the changelog when the next release occurs.
|
||||
> NOTE: It is useful for you to release a version to test your package on your current branch.
|
||||
|
||||
After that, you should commit changes to the remote repository. For example:
|
||||
Run the following command to publish the snapshot version:
|
||||
|
||||
```bash
|
||||
$ git status
|
||||
On branch test-3
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
.changeset/curvy-jobs-fly.md
|
||||
|
||||
$ git commit -am "chore: add changeset"
|
||||
|
||||
$ git push
|
||||
$ npm run release:snapshot
|
||||
```
|
||||
|
||||
For more detail, please see [this documentation](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).
|
||||
After that, you don't need to commit the change to the branch.
|
||||
|
||||
## Publish Beta Version
|
||||
|
||||
> NOTE: You must add a changeset first before publishing beta version.
|
||||
> NOTE: Recommend you to publish a beta version on a new branch(such as `release-beta`) which is checked out from the `release*` branch.
|
||||
|
||||
Run the following command to publish the beta version
|
||||
Run the following command to publish the beta version:
|
||||
|
||||
```bash
|
||||
$ npm run release:beta
|
||||
```
|
||||
|
||||
Then, we need to commit changes to the remote repository. For example:
|
||||
|
||||
```bash
|
||||
$ git status
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
modified: packages/a/CHANGELOG.md
|
||||
modified: packages/a/package.json
|
||||
modified: pnpm-workspace.yaml
|
||||
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
.changeset/pre.json
|
||||
|
||||
$ git commit -am "chore: beta version"
|
||||
|
||||
$ git push
|
||||
```
|
||||
Then, we need to commit the changes to the branch.
|
||||
|
||||
For more detail, please see this [documentation](https://github.com/changesets/changesets/blob/main/docs/prereleases.md).
|
||||
|
||||
|
|
@ -75,4 +44,4 @@ GitHub bot will automatically create a PR to update the latest versions for the
|
|||
|
||||
<img width="701" alt="image" src="https://user-images.githubusercontent.com/44047106/215980879-965da73d-317e-4576-81ee-118e11bcc2d4.png">
|
||||
|
||||
What we need to do is merge the PR to the `release*` branch.
|
||||
What we need to do is to merge the PR to the `release*` branch. After the `release*` branch was merged to the master branch, the versions will be released automatically.
|
||||
|
|
|
|||
|
|
@ -10,5 +10,9 @@
|
|||
"ignore": [
|
||||
"@examples/*",
|
||||
"ice-website-v3"
|
||||
]
|
||||
],
|
||||
"snapshot": {
|
||||
"useCalculatedVersion": true,
|
||||
"prereleaseTemplate": "{tag}-{commit}-{datetime}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ yalc.lock
|
|||
# Packages
|
||||
packages/*/lib/
|
||||
packages/*/esm/
|
||||
packages/*/es2017/
|
||||
|
||||
# temp folder .ice
|
||||
examples/*/.ice
|
||||
|
|
|
|||
3
.npmrc
3
.npmrc
|
|
@ -1 +1,2 @@
|
|||
strict-peer-dependencies=false
|
||||
strict-peer-dependencies=false
|
||||
registry=https://registry.npmjs.org/
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@
|
|||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,6 @@
|
|||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@
|
|||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@
|
|||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ export default function FrameworkLayout({ children }) {
|
|||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ export default function About() {
|
|||
<Link to="/">home</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { defineConfig } from '@ice/app';
|
||||
import miniapp from '@ice/plugin-miniapp';
|
||||
console.log('process.env.FOO', process.env.FOO);
|
||||
export default defineConfig({
|
||||
ssg: false,
|
||||
hash: true,
|
||||
// minify: true,
|
||||
minify: true,
|
||||
dropLogLevel: 'trace',
|
||||
outputDir: 'build/wechat',
|
||||
alias: {
|
||||
|
|
@ -12,11 +11,11 @@ export default defineConfig({
|
|||
},
|
||||
plugins: [miniapp({
|
||||
nativeConfig: {
|
||||
appid: 'tourist'
|
||||
}
|
||||
appid: 'tourist',
|
||||
},
|
||||
})],
|
||||
// eslint: false,
|
||||
define: {
|
||||
ASSETS_VERSION: '1.0.1'
|
||||
}
|
||||
ASSETS_VERSION: JSON.stringify('1.0.1'),
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"start:wechat": "ice start --target wechat-miniprogram",
|
||||
"start:ali": "ice start --target ali-miniapp",
|
||||
"build": "ice build",
|
||||
"build:wechat": "ice build --target wechat-miniprogram"
|
||||
"build:wechat": "ice build --target wechat-miniprogram",
|
||||
"build:ali": "ice build --target ali-miniapp"
|
||||
},
|
||||
"description": "",
|
||||
"author": "",
|
||||
|
|
@ -27,6 +28,6 @@
|
|||
"@types/react-dom": "^18.0.2",
|
||||
"browserslist": "^4.19.3",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# ice.js example miniapp
|
||||
|
||||
## feature list
|
||||
|
||||
### App
|
||||
|
||||
- dataLoader
|
||||
- miniappManifest
|
||||
- miniappLifecycles
|
||||
|
||||
### Pages
|
||||
|
||||
- index
|
||||
- Link component
|
||||
- history
|
||||
- useAppData
|
||||
- useData
|
||||
- second
|
||||
- useSearchParams
|
||||
- page config
|
||||
- page lifecycles
|
||||
- third/index
|
||||
- html tags
|
||||
- use json
|
||||
- use png
|
||||
- fourth
|
||||
- define
|
||||
- process env
|
||||
- miniapp native components
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { defineAppConfig, defineDataLoader } from 'ice';
|
||||
import { defineMiniappConfig } from '@ice/plugin-miniapp/runtime';
|
||||
|
||||
export const dataLoader = defineDataLoader(() => {
|
||||
return new Promise((resolve) => {
|
||||
|
|
@ -17,17 +18,35 @@ export const miniappManifest = {
|
|||
},
|
||||
routes: [
|
||||
'index',
|
||||
'about',
|
||||
'second/profile',
|
||||
'second',
|
||||
'third/index',
|
||||
'third/test',
|
||||
'fourth',
|
||||
],
|
||||
};
|
||||
|
||||
export const miniappLifecycles = defineMiniappConfig(() => {
|
||||
return {
|
||||
onLaunch(options) {
|
||||
console.log('[App] on launch', options);
|
||||
},
|
||||
onShow(options) {
|
||||
console.log('[App] on show', options);
|
||||
},
|
||||
onShareAppMessage(options) {
|
||||
// Only works in ali miniapp
|
||||
console.log('[App] onShareAppMessage', options);
|
||||
return {
|
||||
title: 'test',
|
||||
path: 'pages/index',
|
||||
desc: '呵呵',
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default defineAppConfig(() => {
|
||||
return {
|
||||
app: {
|
||||
strict: true,
|
||||
errorBoundary: true,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import { defineDataLoader } from 'ice';
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<view className="title">About</view>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'About',
|
||||
};
|
||||
}
|
||||
|
||||
export const dataLoader = defineDataLoader((options) => {
|
||||
// options comes from onLoad in miniapp page config
|
||||
console.log('about page options.pathname', options.pathname);
|
||||
console.log('about page options.query', options.query);
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
name: 'About',
|
||||
});
|
||||
}, 1 * 100);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
declare const ASSETS_VERSION: string;
|
||||
|
||||
export default function Fourth() {
|
||||
console.log('[Fourth] ASSETS_VERSION', ASSETS_VERSION);
|
||||
return (
|
||||
<>
|
||||
<view>Fourth Page</view>
|
||||
<button>我是 button 组件</button>
|
||||
{/* @ts-ignore */}
|
||||
<progress percent={50}>我是 progress 组件</progress>
|
||||
<switch type={'switch'}>我是 switch 组件</switch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,61 +1,28 @@
|
|||
import './index.scss';
|
||||
import { useAppData, useConfig, useData, Link, useSearchParams, history, defineDataLoader } from 'ice';
|
||||
import json from '../test.json';
|
||||
import url from './ice.png';
|
||||
import { useAppData, useData, defineDataLoader, history, Link } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
console.log('process.env', process.env.ICE_APP_ID);
|
||||
export default function Index() {
|
||||
const appData = useAppData();
|
||||
console.log('🚀 ~ file: index.tsx ~ line 6 ~ Home ~ appData', appData);
|
||||
const config = useConfig();
|
||||
console.log('🚀 ~ file: index.tsx ~ line 8 ~ Home ~ config', config);
|
||||
const data = useData();
|
||||
console.log('🚀 ~ file: index.tsx ~ line 10 ~ Home ~ data', data);
|
||||
console.log('json', json);
|
||||
const [params] = useSearchParams();
|
||||
console.log('🚀 ~ file: index.tsx ~ line 15 ~ Home ~ params', params);
|
||||
// @ts-ignore
|
||||
console.log('ASSETS_VERSION', ASSETS_VERSION);
|
||||
function onClick() {
|
||||
console.log('123');
|
||||
}
|
||||
console.log('[Index] use app data', appData);
|
||||
console.log('[Index] use data', data);
|
||||
return (
|
||||
<>
|
||||
<view className="title" onClick={() => { console.log(123123); }}>Home Page</view>
|
||||
{/* @ts-ignore */}
|
||||
<image mode="aspectFit" src="https://v3.ice.work/img/logo.png" />
|
||||
<view className="data">
|
||||
<view>foo: </view>
|
||||
<view>users:</view>
|
||||
<view>userInfo: </view>
|
||||
{/* @ts-ignore */}
|
||||
<image src="https://v3.ice.work/img/logo.png" />
|
||||
{/* @ts-ignore */}
|
||||
<image src={url} />
|
||||
<view onClick={() => { history.push('/?hello=computer'); }}>history 跳转本页</view>
|
||||
<view onClick={() => { history.push('/about?hello=computer'); }}>history 跳转 about 页</view>
|
||||
<view onClick={() => { history.push('/second/profile?hello=computer'); }}>history 跳转 second/profile 页</view>
|
||||
<view onClick={() => { history.push('/third'); }}>history 跳转 third/index 页</view>
|
||||
<view onClick={() => { history.push('/third/test'); }}>history 跳转 third/test 页</view>
|
||||
<Link to="/?hello=world">Link 标签跳转本页</Link>
|
||||
<Link to="/about">Link 标签跳转 about 页</Link>
|
||||
<Link to="/third">Link 标签跳转 third/index 页</Link>
|
||||
<Link to="/third/test">Link 标签跳转 third/test 页</Link>
|
||||
<div onClick={onClick}>嘻嘻,我是 div 标签</div>
|
||||
<view onClick={onClick}>嘻嘻,我是 view 标签</view>
|
||||
<view>Index Page</view>
|
||||
<view onClick={() => { history.push('/second?name=chris'); }}>history 跳转 second 页面</view>
|
||||
<view onClick={() => { history.push('/third'); }}>history 跳转 third/index 页面</view>
|
||||
<Link to="/fourth">Link 标签跳转 fourth 页面</Link>
|
||||
</view>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
};
|
||||
}
|
||||
|
||||
export const dataLoader = defineDataLoader((options) => {
|
||||
// options comes from onLoad in miniapp page config
|
||||
console.log('index page options.pathname', options.pathname);
|
||||
console.log('index page options.query', options.query);
|
||||
console.log('[Index] data loader options', options);
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
// import './index.scss';
|
||||
import { useState } from 'react';
|
||||
import { useConfig, useSearchParams, usePageLifecycle } from 'ice';
|
||||
|
||||
export default function Second() {
|
||||
const config = useConfig();
|
||||
console.log('[Second] use config', config);
|
||||
const [params] = useSearchParams();
|
||||
console.log('[Second] use search params', params);
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
usePageLifecycle('onLoad', (options) => {
|
||||
console.log('[Second] page onLoad', options);
|
||||
});
|
||||
usePageLifecycle('onReady', () => {
|
||||
console.log('[Second] page onReady');
|
||||
});
|
||||
usePageLifecycle('onShow', () => {
|
||||
console.log('[Second] page onShow');
|
||||
});
|
||||
usePageLifecycle('onHide', () => {
|
||||
console.log('[Second] page onHide');
|
||||
});
|
||||
usePageLifecycle('onShareAppMessage', (options) => {
|
||||
console.log('[Second] onShareAppMessage', options);
|
||||
return {
|
||||
title: '123',
|
||||
path: 'pages/index',
|
||||
};
|
||||
});
|
||||
usePageLifecycle('onShareTimeline', (options) => {
|
||||
console.log('[Second] onShareTimeline', options);
|
||||
return {
|
||||
title: '456',
|
||||
};
|
||||
});
|
||||
|
||||
return (<view>
|
||||
<view>Second Page</view>
|
||||
<view>{count}</view>
|
||||
<view onClick={() => { setCount(count + 1); }}>+</view>
|
||||
</view>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
nativeEvents: [
|
||||
'onShareAppMessage',
|
||||
'onShareTimeline',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.profile {
|
||||
font-size: 50rpx;
|
||||
color: red;
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import styles from './profile.module.css';
|
||||
|
||||
export default function Profile() {
|
||||
return (
|
||||
<>
|
||||
<view className={styles.profile}>second profile</view>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Second profile',
|
||||
};
|
||||
}
|
||||
|
|
@ -1,7 +1,14 @@
|
|||
import url from '../ice.png';
|
||||
import json from './test.json';
|
||||
|
||||
export default function Third() {
|
||||
console.log('[Third] get json', json);
|
||||
return (
|
||||
<>
|
||||
<view className="title">Third</view>
|
||||
<view className="title">Third Page</view>
|
||||
<div>我是 div 标签</div>
|
||||
<span>我是 span 标签</span>
|
||||
<img src={url} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
export default function Test() {
|
||||
return (
|
||||
<>
|
||||
<view className="title">Third test</view>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -12,3 +12,14 @@ declare module '*.module.scss' {
|
|||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
|
||||
declare module '*.json' {
|
||||
const value: Record<string, any>;
|
||||
export default value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { defineConfig } from '@ice/app';
|
|||
|
||||
export default defineConfig(() => ({
|
||||
ssr: true,
|
||||
ssg: true,
|
||||
define: {
|
||||
'process.env.NODE_ENV': JSON.stringify(true),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ export default defineConfig(() => ({
|
|||
})],
|
||||
server: {
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
},
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@
|
|||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@
|
|||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
ssg: false,
|
||||
}));
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@examples/with-antd5",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "ice start",
|
||||
"build": "ice build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ice/app": "workspace:*",
|
||||
"@ice/runtime": "workspace:*",
|
||||
"antd": "^5.0.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-intl": "^6.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { defineAppConfig } from 'ice';
|
||||
|
||||
export default defineAppConfig(() => ({
|
||||
app: {
|
||||
rootId: 'app',
|
||||
},
|
||||
}));
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||
|
||||
function Document() {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="description" content="ICE Demo" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<Meta />
|
||||
<Title />
|
||||
<Links />
|
||||
</head>
|
||||
<body>
|
||||
<Main />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default Document;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
export const messages: Record<string, any> = {
|
||||
en: {
|
||||
changeLanguageTitle: 'Change locale:',
|
||||
indexTitle: 'Index',
|
||||
},
|
||||
'zh-cn': {
|
||||
changeLanguageTitle: '修改语言:',
|
||||
indexTitle: '首页',
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { DatePicker, Pagination } from 'antd';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div>
|
||||
<h2><FormattedMessage id="indexTitle" /></h2>
|
||||
<Pagination defaultCurrent={1} total={50} showSizeChanger />
|
||||
<DatePicker />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { Outlet } from 'ice';
|
||||
import { useState } from 'react';
|
||||
import { IntlProvider, FormattedMessage } from 'react-intl';
|
||||
import { ConfigProvider, Radio } from 'antd';
|
||||
import type { RadioChangeEvent } from 'antd';
|
||||
import enUS from 'antd/locale/en_US';
|
||||
import zhCN from 'antd/locale/zh_CN';
|
||||
import type { Locale } from 'antd/es/locale';
|
||||
|
||||
import * as dayjs from 'dayjs';
|
||||
import { messages } from '@/locales';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
|
||||
export default function Layout() {
|
||||
const [locale, setLocale] = useState<Locale>(enUS);
|
||||
|
||||
const changeLocale = (e: RadioChangeEvent) => {
|
||||
const localeValue = e.target.value;
|
||||
setLocale(localeValue);
|
||||
if (localeValue) {
|
||||
dayjs.locale('zh-cn');
|
||||
} else {
|
||||
dayjs.locale('en');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main>
|
||||
<IntlProvider locale={locale.locale} messages={messages[locale.locale]}>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<span style={{ marginRight: 16 }}><FormattedMessage id="changeLanguageTitle" /></span>
|
||||
<Radio.Group value={locale} onChange={changeLocale}>
|
||||
<Radio.Button key="en" value={enUS}>
|
||||
English
|
||||
</Radio.Button>
|
||||
<Radio.Button key="cn" value={zhCN}>
|
||||
中文
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<ConfigProvider locale={locale}>
|
||||
<Outlet />
|
||||
</ConfigProvider>
|
||||
</IntlProvider>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="@ice/app/types" />
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"lib": ["DOM", "ESNext", "DOM.Iterable"],
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"ice": [".ice"]
|
||||
}
|
||||
},
|
||||
"include": ["src", ".ice"],
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { useData, defineDataLoader, Await } from 'ice';
|
||||
import styles from './index.module.css';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className={styles.title}>With dataLoader</h2>
|
||||
<Await resolve={data} fallback={<p>Loading item info...</p>} errorElement={<p>Error loading!</p>}>
|
||||
{(itemInfo) => {
|
||||
return <p>Item id is <span id="itemId">{itemInfo.id}</span></p>;
|
||||
}}
|
||||
</Await>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
};
|
||||
}
|
||||
|
||||
export const dataLoader = defineDataLoader(async () => {
|
||||
const promise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
id: 1233,
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
return await promise;
|
||||
}, { defer: true });
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import { useData, defineDataLoader, Await } from 'ice';
|
||||
import styles from './index.module.css';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className={styles.title}>With dataLoader</h2>
|
||||
<Await resolve={data[0]} fallback={<p>Loading item info...</p>} errorElement={<p>Error loading!</p>}>
|
||||
{(itemInfo) => {
|
||||
return <p>Item id is {itemInfo.id}</p>;
|
||||
}}
|
||||
</Await>
|
||||
<Await resolve={data[1]} fallback={<p>Loading item info...</p>} errorElement={<p>Error loading!</p>}>
|
||||
{(itemInfo) => {
|
||||
return <p>Item price is {itemInfo.price}</p>;
|
||||
}}
|
||||
</Await>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
};
|
||||
}
|
||||
|
||||
export const dataLoader = defineDataLoader([
|
||||
async () => {
|
||||
const promise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
id: 1233,
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
return await promise;
|
||||
},
|
||||
async () => {
|
||||
const promise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
price: 9.99,
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
return await promise;
|
||||
},
|
||||
], { defer: true });
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import { useData, defineDataLoader, defineServerDataLoader, Await } from 'ice';
|
||||
import styles from './index.module.css';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className={styles.title}>With dataLoader</h2>
|
||||
<Await resolve={data} fallback={<p>Loading item info...</p>} errorElement={<p>Error loading!</p>}>
|
||||
{(itemInfo) => {
|
||||
return <p>Item id is {itemInfo.id}</p>;
|
||||
}}
|
||||
</Await>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function pageConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
};
|
||||
}
|
||||
|
||||
export const dataLoader = defineDataLoader(async () => {
|
||||
const promise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
id: 1233,
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
return await promise;
|
||||
}, { defer: true });
|
||||
|
||||
export const serverDataLoader = defineServerDataLoader(async () => {
|
||||
const promise = new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
id: 1233,
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
return await promise;
|
||||
});
|
||||
|
|
@ -16,4 +16,5 @@ export default defineConfig({
|
|||
locales: ['af'],
|
||||
}),
|
||||
],
|
||||
ssg: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,16 +12,17 @@
|
|||
"dependencies": {
|
||||
"@alifd/next": "^1.25.49",
|
||||
"@ice/runtime": "workspace:*",
|
||||
"moment": "^2.29.4",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"moment": "^2.29.4"
|
||||
"react-intl": "^6.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"@ice/app": "workspace:*",
|
||||
"@ice/plugin-css-assets-local": "workspace:*",
|
||||
"@ice/plugin-fusion": "workspace:*",
|
||||
"@ice/plugin-moment-locales": "workspace:*"
|
||||
"@ice/plugin-moment-locales": "workspace:*",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
export const messages: Record<string, any> = {
|
||||
en: {
|
||||
buttonText: 'Button',
|
||||
},
|
||||
'zh-cn': {
|
||||
buttonText: '按钮',
|
||||
},
|
||||
};
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
import { Button } from '@alifd/next';
|
||||
import { Button, DatePicker } from '@alifd/next';
|
||||
import '@alifd/next/dist/next.css';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h1>with fusion</h1>
|
||||
<Button type="primary">Button</Button>
|
||||
<DatePicker />
|
||||
<Button type="primary">
|
||||
<FormattedMessage id="buttonText" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { Outlet } from 'ice';
|
||||
import { useState } from 'react';
|
||||
import { ConfigProvider, Radio } from '@alifd/next';
|
||||
import enUS from '@alifd/next/lib/locale/en-us';
|
||||
import zhCN from '@alifd/next/lib/locale/zh-cn';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { messages } from '@/locales';
|
||||
|
||||
const localeMap = new Map([
|
||||
['en', enUS],
|
||||
['zh-cn', zhCN],
|
||||
]);
|
||||
|
||||
export default function Layout() {
|
||||
const [locale, setLocale] = useState('en');
|
||||
const list = [
|
||||
{
|
||||
value: 'en',
|
||||
label: 'English',
|
||||
},
|
||||
{
|
||||
value: 'zh-cn',
|
||||
label: '中文',
|
||||
},
|
||||
];
|
||||
|
||||
function changeLocale(value: string) {
|
||||
setLocale(value);
|
||||
}
|
||||
return (
|
||||
<main>
|
||||
<IntlProvider locale={locale} messages={messages[locale]}>
|
||||
<Radio.Group
|
||||
dataSource={list}
|
||||
shape="button"
|
||||
value={locale}
|
||||
onChange={changeLocale}
|
||||
/>
|
||||
<ConfigProvider locale={localeMap.get(locale)}>
|
||||
<Outlet />
|
||||
</ConfigProvider>
|
||||
</IntlProvider>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { defineConfig } from '@ice/app';
|
||||
import i18n from '@ice/plugin-i18n';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
i18n({
|
||||
locales: ['zh-CN', 'en-US'],
|
||||
defaultLocale: 'zh-CN',
|
||||
autoRedirect: true,
|
||||
}),
|
||||
],
|
||||
ssr: true,
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@examples/with-i18n",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "ice start",
|
||||
"build": "ice build",
|
||||
"serve": "tsx server.mts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ice/runtime": "workspace:*",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-intl": "^6.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ice/app": "workspace:*",
|
||||
"@ice/plugin-i18n": "workspace:*",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"express": "^4.17.3",
|
||||
"tslib": "^2.5.0",
|
||||
"tsx": "^3.12.1"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import express from 'express';
|
||||
import { renderToHTML } from './build/server/index.mjs';
|
||||
|
||||
const app = express();
|
||||
const port = 4000;
|
||||
const basename = '/app';
|
||||
|
||||
app.use(express.static('build', {}));
|
||||
|
||||
app.use(async (req, res) => {
|
||||
const { statusCode, statusText, headers, value: body } = await renderToHTML({ req, res }, { basename });
|
||||
res.statusCode = statusCode;
|
||||
res.statusMessage = statusText;
|
||||
Object.entries((headers || {}) as Record<string, string>).forEach(([name, value]) => {
|
||||
res.setHeader(name, value);
|
||||
});
|
||||
if (body && req.method !== 'HEAD') {
|
||||
res.end(body);
|
||||
} else {
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`App listening on http://localhost:${port}${basename}`);
|
||||
});
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { defineAppConfig } from 'ice';
|
||||
import { defineI18nConfig } from '@ice/plugin-i18n/types';
|
||||
|
||||
export default defineAppConfig(() => ({
|
||||
router: {
|
||||
basename: '/app',
|
||||
},
|
||||
}));
|
||||
|
||||
export const i18nConfig = defineI18nConfig(() => ({
|
||||
// disabledCookie: true,
|
||||
}));
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||
|
||||
function Document() {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="description" content="ICE Demo" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<Meta />
|
||||
<Title />
|
||||
<Links />
|
||||
</head>
|
||||
<body>
|
||||
<Main />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default Document;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export const messages: Record<string, any> = {
|
||||
'en-US': {
|
||||
buttonText: 'Normal Button',
|
||||
},
|
||||
'zh-CN': {
|
||||
buttonText: '普通按钮',
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { Link } from 'ice';
|
||||
|
||||
export default function BlogA() {
|
||||
return (
|
||||
<>
|
||||
<h2>Blog A</h2>
|
||||
<ul>
|
||||
<li><Link to="/">Index</Link></li>
|
||||
<li><Link to="/blog">Blog</Link></li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { Link } from 'ice';
|
||||
|
||||
export default function Blog() {
|
||||
return (
|
||||
<>
|
||||
<h2>Blog</h2>
|
||||
<ul>
|
||||
<li><Link to="/">Index</Link></li>
|
||||
<li><Link to="/blog/a">Blog A</Link></li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { Link } from 'ice';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h1>I18n Example</h1>
|
||||
<Link to="/blog">Blog</Link>
|
||||
<br />
|
||||
<button style={{ marginTop: 20 }} id="button">
|
||||
<FormattedMessage id="buttonText" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import { Outlet, useLocale, getAllLocales, getDefaultLocale, Link, useLocation } from 'ice';
|
||||
import { IntlProvider as ReactIntlProvider } from 'react-intl';
|
||||
import { messages } from '@/locales';
|
||||
|
||||
export default function Layout() {
|
||||
const location = useLocation();
|
||||
const [activeLocale, setLocale] = useLocale();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<p><b>Current locale: </b>{activeLocale}</p>
|
||||
<p><b>Default locale: </b>{getDefaultLocale()}</p>
|
||||
<p><b>Configured locales: </b>{JSON.stringify(getAllLocales())}</p>
|
||||
|
||||
<b>Choose language: </b>
|
||||
<ul>
|
||||
{
|
||||
getAllLocales().map((locale: string) => {
|
||||
return (
|
||||
<li key={locale}>
|
||||
<Link
|
||||
to={location.pathname}
|
||||
onClick={() => setLocale(locale)}
|
||||
// state={{ locale }}
|
||||
>
|
||||
{locale}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
<ReactIntlProvider locale={activeLocale} messages={messages[activeLocale]}>
|
||||
<Outlet />
|
||||
</ReactIntlProvider>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"compileOnSave": false,
|
||||
"buildOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "build",
|
||||
"module": "esnext",
|
||||
"target": "es6",
|
||||
"jsx": "react-jsx",
|
||||
"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"]
|
||||
}
|
||||
},
|
||||
"include": ["src", ".ice", "ice.config.*"],
|
||||
"exclude": ["build", "public"]
|
||||
}
|
||||
|
|
@ -19,6 +19,6 @@
|
|||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
export default function A() {
|
||||
return <div>111</div>;
|
||||
}
|
||||
|
|
@ -19,6 +19,6 @@
|
|||
"devDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.2",
|
||||
"webpack": "^5.73.0"
|
||||
"webpack": "^5.80.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,4 @@ export const staticDataLoader = defineStaticDataLoader(() => {
|
|||
return {
|
||||
price: '0.00',
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { defineConfig } from '@ice/app';
|
|||
import store from '@ice/plugin-store';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
ssg: false,
|
||||
plugins: [
|
||||
store({
|
||||
resetPageState: true,
|
||||
|
|
|
|||
|
|
@ -19,4 +19,8 @@ export const dataLoader = defineDataLoader(() => {
|
|||
});
|
||||
});
|
||||
|
||||
export default defineAppConfig(() => ({}));
|
||||
export default defineAppConfig(() => ({
|
||||
router: {
|
||||
type: 'hash',
|
||||
},
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -21,16 +21,18 @@
|
|||
"cov": "vitest run --coverage",
|
||||
"test": "vitest",
|
||||
"changeset": "changeset",
|
||||
"version": "changeset version && pnpm install --frozen-lockfile false",
|
||||
"install:frozen": "pnpm install --frozen-lockfile false",
|
||||
"version": "changeset version && pnpm install:frozen",
|
||||
"release": "changeset publish",
|
||||
"release:beta": "changeset pre enter beta && pnpm run version && pnpm build && pnpm release && changeset pre exit"
|
||||
"release:beta": "changeset pre enter beta && pnpm run version && pnpm build && pnpm release && changeset pre exit",
|
||||
"release:snapshot": "changeset version --snapshot canary && pnpm install:frozen && pnpm build && pnpm release --tag canary --no-git-tag --snapshot"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@applint/spec": "^1.2.3",
|
||||
"@changesets/cli": "^2.26.0",
|
||||
"@commitlint/cli": "^16.3.0",
|
||||
"@ice/bundles": "workspace:^0.1.0",
|
||||
"@ice/bundles": "workspace:*",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@types/eslint": "^8.4.5",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
# Changelog
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 57219848: update webpack version
|
||||
- 5dd3c86e: fix: update version of @ice/swc-plugin-keep-export(0.1.4-2)
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@ice/bundles",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.10",
|
||||
"license": "MIT",
|
||||
"author": "ICE",
|
||||
"description": "Basic dependencies for ice.",
|
||||
|
|
@ -17,14 +17,14 @@
|
|||
"dependencies": {
|
||||
"@swc/core": "1.3.19",
|
||||
"@ice/swc-plugin-remove-export": "0.1.2",
|
||||
"@ice/swc-plugin-keep-export": "0.1.4",
|
||||
"@ice/swc-plugin-keep-export": "0.1.4-2",
|
||||
"@ice/swc-plugin-node-transform": "0.1.0-8",
|
||||
"ansi-html-community": "^0.0.8",
|
||||
"html-entities": "^2.3.2",
|
||||
"core-js": "3.29.1",
|
||||
"caniuse-lite": "^1.0.30001431",
|
||||
"chokidar": "3.5.3",
|
||||
"esbuild": "^0.16.5",
|
||||
"esbuild": "^0.17.16",
|
||||
"events": "3.3.0",
|
||||
"jest-worker": "27.5.1",
|
||||
"less": "4.1.2",
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
"terser-webpack-plugin": "5.3.5",
|
||||
"typescript": "^4.6.4",
|
||||
"trusted-cert": "1.1.3",
|
||||
"webpack": "5.76.2",
|
||||
"webpack": "5.80.0",
|
||||
"webpack-bundle-analyzer": "4.5.0",
|
||||
"webpack-dev-server": "4.11.1",
|
||||
"unplugin": "0.9.5",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,31 @@
|
|||
# Changelog
|
||||
|
||||
## 3.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- f62560f9: feat: refactor runtime about router
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8f97e538: chore: bump build-scripts version to unify esbuild version
|
||||
- 1c3d3fec: feat: support add routes definition
|
||||
- 9de09ee8: feat: support version check between @ice/app and @ice/runtime
|
||||
- da7c733c: fix: wrap data loader in function expression to avoid rewrite global scope
|
||||
- ddee1c3e: support miniapp native events
|
||||
- 5dd3c86e: refactor: use swc plugin for remove code
|
||||
- 467dc56b: fix: only create esbuild context when dev
|
||||
- 1c3d3fec: fix: routeSpecifier is not unique
|
||||
- 7b04ca7e: fix: remove all exports of components when render mode is csr
|
||||
- 57219848: support miniapp native lifecycle events
|
||||
- 13770d53: fix: compatible with runtime absolute path on win32 platform
|
||||
- a878225f: fix: dataLoader is sent repeatedly in PHA
|
||||
- Updated dependencies
|
||||
- @ice/runtime@1.2.0
|
||||
- @ice/bundles@0.1.10
|
||||
- @ice/route-manifest@1.2.0
|
||||
- @ice/webpack-config@1.0.14
|
||||
|
||||
## 3.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
|
@ -8,12 +34,7 @@
|
|||
- 0d549779: fix: read the same task target
|
||||
- b226e356: fix: bump @swc/helpers to 0.5.1
|
||||
- 6e9c822a: fix: server compiler define config
|
||||
- Updated dependencies [28de278f]
|
||||
- Updated dependencies [6e9c822a]
|
||||
- Updated dependencies [b226e356]
|
||||
- Updated dependencies [5d5fb334]
|
||||
- Updated dependencies [bb07fd91]
|
||||
- Updated dependencies [0d549779]
|
||||
- Updated dependencies
|
||||
- @ice/webpack-config@1.0.13
|
||||
- @ice/bundles@0.1.9
|
||||
- @ice/runtime@1.1.7
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@ice/app",
|
||||
"version": "3.1.7",
|
||||
"version": "3.2.0",
|
||||
"description": "provide scripts and configuration used by web framework ice",
|
||||
"type": "module",
|
||||
"main": "./esm/index.js",
|
||||
|
|
@ -18,7 +18,8 @@
|
|||
"!esm/**/*.map",
|
||||
"templates",
|
||||
"openChrome.applescript",
|
||||
"*.d.ts"
|
||||
"*.d.ts",
|
||||
"scripts"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=14.19.0",
|
||||
|
|
@ -26,7 +27,8 @@
|
|||
},
|
||||
"scripts": {
|
||||
"watch": "tsc -w",
|
||||
"build": "tsc"
|
||||
"build": "tsc",
|
||||
"postinstall": "node ./scripts/postinstall.mjs"
|
||||
},
|
||||
"author": "ice-admin",
|
||||
"license": "MIT",
|
||||
|
|
@ -34,18 +36,14 @@
|
|||
"bugs": "https://github.com/alibaba/ice/issues",
|
||||
"homepage": "https://v3.ice.work",
|
||||
"dependencies": {
|
||||
"@babel/generator": "7.18.10",
|
||||
"@babel/parser": "7.18.10",
|
||||
"@babel/traverse": "7.18.10",
|
||||
"@babel/types": "7.18.10",
|
||||
"@ice/bundles": "0.1.9",
|
||||
"@ice/route-manifest": "1.1.1",
|
||||
"@ice/runtime": "^1.1.7",
|
||||
"@ice/webpack-config": "1.0.13",
|
||||
"@ice/bundles": "0.1.10",
|
||||
"@ice/route-manifest": "1.2.0",
|
||||
"@ice/runtime": "^1.2.0",
|
||||
"@ice/webpack-config": "1.0.14",
|
||||
"@swc/helpers": "0.5.1",
|
||||
"@types/express": "^4.17.14",
|
||||
"address": "^1.1.2",
|
||||
"build-scripts": "^2.1.0",
|
||||
"build-scripts": "^2.1.1-0",
|
||||
"chalk": "^4.0.0",
|
||||
"commander": "^9.0.0",
|
||||
"consola": "^2.15.3",
|
||||
|
|
@ -54,7 +52,6 @@
|
|||
"dotenv": "^16.0.0",
|
||||
"dotenv-expand": "^8.0.3",
|
||||
"ejs": "^3.1.6",
|
||||
"estree-walker": "^3.0.2",
|
||||
"fast-glob": "^3.2.11",
|
||||
"find-up": "^5.0.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
|
|
@ -79,13 +76,13 @@
|
|||
"@types/multer": "^1.4.7",
|
||||
"@types/temp": "^0.9.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"esbuild": "^0.16.5",
|
||||
"esbuild": "^0.17.16",
|
||||
"jest": "^29.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-router": "^6.8.2",
|
||||
"react-router": "6.11.1",
|
||||
"sass": "^1.50.0",
|
||||
"unplugin": "^0.9.0",
|
||||
"webpack": "^5.76.2",
|
||||
"webpack": "^5.80.0",
|
||||
"webpack-dev-server": "^4.7.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { createRequire } from 'module';
|
||||
import fs from 'fs';
|
||||
import semver from 'semver';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
// Only change this when you release a version which break the usage of runtime generation.
|
||||
const RUNTIME_VALID_VERSION = '>=1.2.0';
|
||||
try {
|
||||
// @ice/runtime has defined package.json exports, so we can use require.resolve to get the package.json path.
|
||||
const packageJsonPath = require.resolve('@ice/runtime/package.json');
|
||||
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
const version = semver.valid(semver.coerce(pkg.version));
|
||||
if (!semver.satisfies(version, RUNTIME_VALID_VERSION)) {
|
||||
console.log(`Detect @ice/runtime version is ${pkg.version}, Please update @ice/runtime to ${RUNTIME_VALID_VERSION}`);
|
||||
// Break the process while @ice/runtime version is not valid.
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore errors while @ice/runtime is not installed.
|
||||
}
|
||||
|
|
@ -144,27 +144,28 @@ const build = async (
|
|||
if (ssg) {
|
||||
renderMode = 'SSG';
|
||||
}
|
||||
const { serverEntry } = await serverCompileTask.get();
|
||||
serverEntryRef.current = serverEntry;
|
||||
const routeType = appConfig?.router?.type;
|
||||
const {
|
||||
outputPaths = [],
|
||||
} = await generateEntry({
|
||||
rootDir,
|
||||
outputDir,
|
||||
entry: serverEntry,
|
||||
// only ssg need to generate the whole page html when build time.
|
||||
documentOnly: !ssg,
|
||||
renderMode,
|
||||
routeType: appConfig?.router?.type,
|
||||
distType,
|
||||
routeManifest,
|
||||
});
|
||||
// This depends on orders.
|
||||
output.paths = [...outputPaths];
|
||||
|
||||
if (routeType === 'memory' && userConfig?.routes?.injectInitialEntry) {
|
||||
injectInitialEntry(routeManifest, outputDir);
|
||||
const { serverEntry } = await serverCompileTask.get() || {};
|
||||
if (serverEntry) {
|
||||
serverEntryRef.current = serverEntry;
|
||||
const routeType = appConfig?.router?.type;
|
||||
const {
|
||||
outputPaths = [],
|
||||
} = await generateEntry({
|
||||
rootDir,
|
||||
outputDir,
|
||||
entry: serverEntry,
|
||||
// only ssg need to generate the whole page html when build time.
|
||||
documentOnly: !ssg,
|
||||
renderMode,
|
||||
routeType: appConfig?.router?.type,
|
||||
distType,
|
||||
routeManifest,
|
||||
});
|
||||
// This depends on orders.
|
||||
output.paths = [...outputPaths];
|
||||
if (routeType === 'memory' && userConfig?.routes?.injectInitialEntry) {
|
||||
injectInitialEntry(routeManifest, outputDir);
|
||||
}
|
||||
}
|
||||
|
||||
await applyHook('after.build.compile', {
|
||||
|
|
|
|||
|
|
@ -39,25 +39,34 @@ export const TARGETS = [
|
|||
|
||||
export const RUNTIME_EXPORTS = [
|
||||
{
|
||||
specifier: ['Link', 'Outlet', 'useParams', 'useSearchParams', 'useLocation', 'useNavigate'],
|
||||
specifier: [
|
||||
'Link',
|
||||
'Outlet',
|
||||
'useParams',
|
||||
'useSearchParams',
|
||||
'useLocation',
|
||||
'useData',
|
||||
'useConfig',
|
||||
'useNavigate',
|
||||
],
|
||||
source: '@ice/runtime/router',
|
||||
},
|
||||
{
|
||||
specifier: [
|
||||
'defineAppConfig',
|
||||
'useAppData',
|
||||
'useData',
|
||||
'useConfig',
|
||||
'history',
|
||||
'KeepAliveOutlet',
|
||||
'useMounted',
|
||||
'ClientOnly',
|
||||
'withSuspense',
|
||||
'useSuspenseData',
|
||||
'Await',
|
||||
'defineDataLoader',
|
||||
'defineServerDataLoader',
|
||||
'defineStaticDataLoader',
|
||||
'usePageLifecycle',
|
||||
],
|
||||
source: '@ice/runtime',
|
||||
},
|
||||
];
|
||||
];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,12 @@ import type { Config } from '@ice/webpack-config/types';
|
|||
import type { AppConfig } from '@ice/runtime/types';
|
||||
import webpack from '@ice/bundles/compiled/webpack/index.js';
|
||||
import fg from 'fast-glob';
|
||||
import type { DeclarationData, PluginData, ExtendsPluginAPI, TargetDeclarationData } from './types';
|
||||
import type {
|
||||
DeclarationData,
|
||||
PluginData,
|
||||
ExtendsPluginAPI,
|
||||
TargetDeclarationData,
|
||||
} from './types/index.js';
|
||||
import { DeclarationType } from './types/index.js';
|
||||
import Generator from './service/runtimeGenerator.js';
|
||||
import { createServerCompiler } from './service/serverCompiler.js';
|
||||
|
|
@ -19,7 +24,7 @@ import test from './commands/test.js';
|
|||
import getWatchEvents from './getWatchEvents.js';
|
||||
import { setEnv, updateRuntimeEnv, getCoreEnvKeys } from './utils/runtimeEnv.js';
|
||||
import getRuntimeModules from './utils/getRuntimeModules.js';
|
||||
import { generateRoutesInfo, getRoutesDefination } from './routes.js';
|
||||
import { generateRoutesInfo, getRoutesDefinition } from './routes.js';
|
||||
import * as config from './config.js';
|
||||
import { RUNTIME_TMP_DIR, WEB, RUNTIME_EXPORTS, SERVER_ENTRY } from './constant.js';
|
||||
import createSpinner from './utils/createSpinner.js';
|
||||
|
|
@ -167,6 +172,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
getRouteManifest: () => routeManifest.getNestedRoute(),
|
||||
getFlattenRoutes: () => routeManifest.getFlattenRoute(),
|
||||
getRoutesFile: () => routeManifest.getRoutesFile(),
|
||||
addRoutesDefinition: routeManifest.addRoutesDefinition.bind(routeManifest),
|
||||
excuteServerEntry,
|
||||
context: {
|
||||
webpack,
|
||||
|
|
@ -183,7 +189,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
|
||||
// get plugins include built-in plugins and custom plugins
|
||||
const resolvedPlugins = await ctx.resolvePlugins() as PluginData[];
|
||||
const runtimeModules = getRuntimeModules(resolvedPlugins);
|
||||
const runtimeModules = getRuntimeModules(resolvedPlugins, rootDir);
|
||||
|
||||
const { getAppConfig, init: initAppConfigCompiler } = getAppExportConfig(rootDir);
|
||||
const { getRoutesConfig, getDataloaderConfig, init: initRouteConfigCompiler } = getRouteExportConfig(rootDir);
|
||||
|
|
@ -212,8 +218,9 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
|
||||
const coreEnvKeys = getCoreEnvKeys();
|
||||
|
||||
const routesInfo = await generateRoutesInfo(rootDir, routesConfig);
|
||||
const routesInfo = await generateRoutesInfo(rootDir, routesConfig, routeManifest.getRoutesDefinitions());
|
||||
routeManifest.setRoutes(routesInfo.routes);
|
||||
|
||||
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader');
|
||||
const csr = !userConfig.ssr && !userConfig.ssg;
|
||||
|
||||
|
|
@ -230,7 +237,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
const iceRuntimePath = '@ice/runtime';
|
||||
// Only when code splitting use the default strategy or set to `router`, the router will be lazy loaded.
|
||||
const lazy = [true, 'chunks', 'page'].includes(userConfig.codeSplitting);
|
||||
const { routeImports, routeDefination } = getRoutesDefination(routesInfo.routes, lazy);
|
||||
const { routeImports, routeDefinition } = getRoutesDefinition(routesInfo.routes, lazy);
|
||||
// add render data
|
||||
generator.setRenderData({
|
||||
...routesInfo,
|
||||
|
|
@ -250,21 +257,25 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
jsOutput: distType.includes('javascript'),
|
||||
dataLoader: userConfig.dataLoader,
|
||||
routeImports,
|
||||
routeDefination,
|
||||
routeDefinition,
|
||||
});
|
||||
dataCache.set('routes', JSON.stringify(routesInfo));
|
||||
dataCache.set('hasExportAppData', hasExportAppData ? 'true' : '');
|
||||
|
||||
// Render exports files if route component export dataLoader / pageConfig.
|
||||
renderExportsTemplate({
|
||||
...routesInfo,
|
||||
hasExportAppData,
|
||||
}, generator.addRenderFile, {
|
||||
rootDir,
|
||||
runtimeDir: RUNTIME_TMP_DIR,
|
||||
templateDir: path.join(templateDir, 'exports'),
|
||||
dataLoader: Boolean(userConfig.dataLoader),
|
||||
});
|
||||
renderExportsTemplate(
|
||||
{
|
||||
...routesInfo,
|
||||
hasExportAppData,
|
||||
},
|
||||
generator.addRenderFile,
|
||||
{
|
||||
rootDir,
|
||||
runtimeDir: RUNTIME_TMP_DIR,
|
||||
templateDir: path.join(templateDir, 'exports'),
|
||||
dataLoader: Boolean(userConfig.dataLoader),
|
||||
},
|
||||
);
|
||||
|
||||
if (typeof userConfig.dataLoader === 'object' && userConfig.dataLoader.fetcher) {
|
||||
const {
|
||||
|
|
@ -293,6 +304,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
|||
rootDir,
|
||||
task: platformTaskConfig,
|
||||
server,
|
||||
csr,
|
||||
});
|
||||
addWatchEvent([
|
||||
/src\/?[\w*-:.$]+$/,
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
import * as fs from 'fs';
|
||||
import type { Plugin } from 'esbuild';
|
||||
import { parse, type ParserOptions } from '@babel/parser';
|
||||
import babelTraverse from '@babel/traverse';
|
||||
import babelGenerate from '@babel/generator';
|
||||
import removeTopLevelCode from '../utils/babelPluginRemoveCode.js';
|
||||
import formatPath from '../utils/formatPath.js';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
// @ts-ignore @babel/traverse is not a valid export in esm
|
||||
const traverse = babelTraverse.default || babelTraverse;
|
||||
// @ts-ignore @babel/generate is not a valid export in esm
|
||||
const generate = babelGenerate.default || babelGenerate;
|
||||
|
||||
const removeCodePlugin = (keepExports: string[], transformInclude: (id: string) => boolean): Plugin => {
|
||||
const parserOptions: ParserOptions = {
|
||||
sourceType: 'module',
|
||||
plugins: [
|
||||
'jsx',
|
||||
'importMeta',
|
||||
'topLevelAwait',
|
||||
'classProperties',
|
||||
'classPrivateMethods',
|
||||
],
|
||||
};
|
||||
return {
|
||||
name: 'esbuild-remove-top-level-code',
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /\.(js|jsx|ts|tsx)$/ }, async ({ path: id }) => {
|
||||
if (!transformInclude(formatPath(id))) {
|
||||
return;
|
||||
}
|
||||
const source = await fs.promises.readFile(id, 'utf-8');
|
||||
let isTS = false;
|
||||
if (id.match(/\.(ts|tsx)$/)) {
|
||||
isTS = true;
|
||||
parserOptions.plugins.push('typescript', 'decorators-legacy');
|
||||
}
|
||||
try {
|
||||
const ast = parse(source, parserOptions);
|
||||
traverse(ast, removeTopLevelCode(keepExports));
|
||||
const contents = generate(ast).code;
|
||||
return {
|
||||
contents,
|
||||
loader: isTS ? 'tsx' : 'jsx',
|
||||
};
|
||||
} catch (error) {
|
||||
logger.debug('Remove top level code error.', `\nFile id: ${id}`, `\n${error.stack}`);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default removeCodePlugin;
|
||||
|
|
@ -2,7 +2,7 @@ import * as path from 'path';
|
|||
import type { Context } from 'build-scripts';
|
||||
import type { Config } from '@ice/webpack-config/types';
|
||||
import type { WatchEvent } from './types/plugin.js';
|
||||
import { generateRoutesInfo, getRoutesDefination } from './routes.js';
|
||||
import { generateRoutesInfo, getRoutesDefinition } from './routes.js';
|
||||
import type Generator from './service/runtimeGenerator';
|
||||
import getGlobalStyleGlobPattern from './utils/getGlobalStyleGlobPattern.js';
|
||||
import renderExportsTemplate from './utils/renderExportsTemplate.js';
|
||||
|
|
@ -30,7 +30,7 @@ const getWatchEvents = (options: Options): WatchEvent[] => {
|
|||
async (eventName: string) => {
|
||||
if (eventName === 'add' || eventName === 'unlink' || eventName === 'change') {
|
||||
const routesRenderData = await generateRoutesInfo(rootDir, routesConfig);
|
||||
const { routeImports, routeDefination } = getRoutesDefination(routesRenderData.routes, lazyRoutes);
|
||||
const { routeImports, routeDefinition } = getRoutesDefinition(routesRenderData.routes, lazyRoutes);
|
||||
const stringifiedData = JSON.stringify(routesRenderData);
|
||||
if (cache.get('routes') !== stringifiedData) {
|
||||
cache.set('routes', stringifiedData);
|
||||
|
|
@ -38,9 +38,9 @@ const getWatchEvents = (options: Options): WatchEvent[] => {
|
|||
if (eventName !== 'change') {
|
||||
// Specify the route files to re-render.
|
||||
generator.renderFile(
|
||||
path.join(templateDir, 'routes.ts.ejs'),
|
||||
path.join(rootDir, targetDir, 'routes.ts'),
|
||||
{ routeImports, routeDefination },
|
||||
path.join(templateDir, 'routes.tsx.ejs'),
|
||||
path.join(rootDir, targetDir, 'routes.tsx'),
|
||||
{ routeImports, routeDefinition },
|
||||
);
|
||||
// Keep generate route manifest for avoid breaking change.
|
||||
generator.renderFile(
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
import * as path from 'path';
|
||||
import { formatNestedRouteManifest, generateRouteManifest } from '@ice/route-manifest';
|
||||
import type { NestedRouteManifest } from '@ice/route-manifest';
|
||||
import type { NestedRouteManifest, DefineExtraRoutes } from '@ice/route-manifest';
|
||||
import type { UserConfig } from './types/userConfig.js';
|
||||
import { getFileExports } from './service/analyze.js';
|
||||
import formatPath from './utils/formatPath.js';
|
||||
|
||||
export async function generateRoutesInfo(rootDir: string, routesConfig: UserConfig['routes'] = {}) {
|
||||
export async function generateRoutesInfo(
|
||||
rootDir: string,
|
||||
routesConfig: UserConfig['routes'] = {},
|
||||
routesDefinitions: DefineExtraRoutes[] = [],
|
||||
) {
|
||||
const routeManifest = generateRouteManifest(
|
||||
rootDir,
|
||||
routesConfig.ignoreFiles,
|
||||
routesConfig.defineRoutes,
|
||||
[routesConfig.defineRoutes, ...routesDefinitions],
|
||||
routesConfig.config,
|
||||
);
|
||||
|
||||
|
|
@ -51,9 +55,9 @@ export default {
|
|||
};
|
||||
}
|
||||
|
||||
export function getRoutesDefination(nestRouteManifest: NestedRouteManifest[], lazy = false, depth = 0) {
|
||||
export function getRoutesDefinition(nestRouteManifest: NestedRouteManifest[], lazy = false, depth = 0) {
|
||||
const routeImports: string[] = [];
|
||||
const routeDefination = nestRouteManifest.reduce((prev, route, currentIndex) => {
|
||||
const routeDefinition = nestRouteManifest.reduce((prev, route) => {
|
||||
const { children, path: routePath, index, componentName, file, id, layout, exports } = route;
|
||||
|
||||
const componentPath = id.startsWith('__') ? file : `@/pages/${file}`.replace(new RegExp(`${path.extname(file)}$`), '');
|
||||
|
|
@ -62,27 +66,47 @@ export function getRoutesDefination(nestRouteManifest: NestedRouteManifest[], la
|
|||
if (lazy) {
|
||||
loadStatement = `import(/* webpackChunkName: "p_${componentName}" */ '${formatPath(componentPath)}')`;
|
||||
} else {
|
||||
const routeSpecifier = `route_${depth}_${currentIndex}`;
|
||||
const routeSpecifier = id.replace(/[./-]/g, '_').replace(/[:*]/g, '$');
|
||||
routeImports.push(`import * as ${routeSpecifier} from '${formatPath(componentPath)}';`);
|
||||
loadStatement = routeSpecifier;
|
||||
}
|
||||
const component = `Component: () => WrapRouteComponent({
|
||||
routeId: '${id}',
|
||||
isLayout: ${layout},
|
||||
routeExports: ${lazy ? 'componentModule' : loadStatement},
|
||||
})`;
|
||||
const loader = `loader: createRouteLoader({
|
||||
routeId: '${id}',
|
||||
requestContext,
|
||||
renderMode,
|
||||
module: ${lazy ? 'componentModule' : loadStatement},
|
||||
})`;
|
||||
const routeProperties: string[] = [
|
||||
`path: '${formatPath(routePath || '')}',`,
|
||||
`load: () => ${loadStatement},`,
|
||||
`async lazy() {
|
||||
${lazy ? `const componentModule = await ${loadStatement}` : ''};
|
||||
return {
|
||||
${lazy ? '...componentModule' : `...${loadStatement}`},
|
||||
${component},
|
||||
${loader},
|
||||
};
|
||||
},`,
|
||||
// Empty errorElement to avoid default ui provided by react-router.
|
||||
'errorElement: <RouteErrorComponent />,',
|
||||
`componentName: '${componentName}',`,
|
||||
`index: ${index},`,
|
||||
`id: '${id}',`,
|
||||
'exact: true,',
|
||||
`exports: ${JSON.stringify(exports)},`,
|
||||
];
|
||||
].filter(Boolean);
|
||||
|
||||
if (layout) {
|
||||
routeProperties.push('layout: true,');
|
||||
}
|
||||
if (children) {
|
||||
const res = getRoutesDefination(children, lazy, depth + 1);
|
||||
const res = getRoutesDefinition(children, lazy, depth + 1);
|
||||
routeImports.push(...res.routeImports);
|
||||
routeProperties.push(`children: [${res.routeDefination}]`);
|
||||
routeProperties.push(`children: [${res.routeDefinition}]`);
|
||||
}
|
||||
prev += formatRoutesStr(depth, routeProperties);
|
||||
return prev;
|
||||
|
|
@ -90,7 +114,7 @@ export function getRoutesDefination(nestRouteManifest: NestedRouteManifest[], la
|
|||
|
||||
return {
|
||||
routeImports,
|
||||
routeDefination,
|
||||
routeDefinition,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { filterAlias, getRuntimeDefination } from './serverCompiler.js';
|
|||
interface InitOptions {
|
||||
rootDir: string;
|
||||
server: UserConfig['server'];
|
||||
csr: boolean;
|
||||
task: TaskConfig<Config>;
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +87,7 @@ class ServerRunner extends Runner {
|
|||
task,
|
||||
server,
|
||||
rootDir,
|
||||
csr,
|
||||
}: InitOptions) {
|
||||
const transformPlugins = getCompilerPlugins(rootDir, {
|
||||
...task.config,
|
||||
|
|
@ -94,6 +96,8 @@ class ServerRunner extends Runner {
|
|||
polyfill: false,
|
||||
swcOptions: {
|
||||
nodeTransform: true,
|
||||
// Remove all exports except pageConfig when ssr and ssg both are false.
|
||||
keepExports: csr ? ['pageConfig'] : null,
|
||||
compilationConfig: {
|
||||
jsc: {
|
||||
// https://node.green/#ES2020
|
||||
|
|
@ -269,7 +273,6 @@ class ServerRunner extends Runner {
|
|||
const bundlePath = await runtimeMeta.bundle(id);
|
||||
return { externalize: bundlePath };
|
||||
}
|
||||
|
||||
return {
|
||||
code: await transformJsxRuntime(code),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import * as path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import type { ServerCompiler } from '../types/plugin.js';
|
||||
import removeTopLevelCode from '../esbuild/removeTopLevelCode.js';
|
||||
import { getCache, setCache } from '../utils/persistentCache.js';
|
||||
import { getFileHash } from '../utils/hash.js';
|
||||
import dynamicImport from '../utils/dynamicImport.js';
|
||||
|
|
@ -15,7 +14,7 @@ type GetOutfile = (entry: string, exportNames: string[]) => string;
|
|||
interface CompileConfig {
|
||||
entry: string;
|
||||
rootDir: string;
|
||||
transformInclude: (id: string) => boolean;
|
||||
transformInclude?: (id: string) => boolean;
|
||||
needRecompile?: (entry: string, options: string[]) => Promise<boolean | string>;
|
||||
getOutfile?: GetOutfile;
|
||||
}
|
||||
|
|
@ -48,13 +47,19 @@ class Config {
|
|||
format: 'esm',
|
||||
outfile,
|
||||
plugins: [
|
||||
removeTopLevelCode(keepExports, transformInclude),
|
||||
// External node builtin modules, such as `fs`, it will be imported by weex document.
|
||||
externalBuiltinPlugin(),
|
||||
],
|
||||
].filter(Boolean),
|
||||
sourcemap: false,
|
||||
logLevel: 'silent', // The main server compiler process will log it.
|
||||
}, {});
|
||||
}, {
|
||||
swc: {
|
||||
keepExports: {
|
||||
value: keepExports,
|
||||
include: transformInclude,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!error) {
|
||||
this.status = 'RESOLVED';
|
||||
return outfile;
|
||||
|
|
@ -197,8 +202,6 @@ export const getRouteExportConfig = (rootDir: string) => {
|
|||
entry: routeConfigFile,
|
||||
rootDir,
|
||||
getOutfile: getRouteConfigOutfile,
|
||||
// Only remove top level code for route component file.
|
||||
transformInclude: (id) => id.includes('src/pages'),
|
||||
needRecompile: async (entry) => {
|
||||
let cached = false;
|
||||
try {
|
||||
|
|
@ -218,8 +221,6 @@ export const getRouteExportConfig = (rootDir: string) => {
|
|||
entry: loadersConfigFile,
|
||||
rootDir,
|
||||
getOutfile: getdataLoadersConfigOutfile,
|
||||
// Only remove top level code for route component file.
|
||||
transformInclude: (id) => id.includes('src/pages'),
|
||||
needRecompile: async (entry) => {
|
||||
let cached = false;
|
||||
const cachedKey = `loader_config_file_${process.env.__ICE_VERSION__}`;
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ export default class Generator {
|
|||
const renderExt = '.ejs';
|
||||
const realTargetPath = path.isAbsolute(targetPath)
|
||||
? targetPath : path.join(this.rootDir, this.targetDir, targetPath);
|
||||
// example: templatePath = 'routes.ts.ejs'
|
||||
// example: templatePath = 'routes.tsx.ejs'
|
||||
const realTemplatePath = path.isAbsolute(templatePath)
|
||||
? templatePath : path.join(this.templateDir, templatePath);
|
||||
const { ext } = path.parse(templatePath);
|
||||
|
|
|
|||
|
|
@ -224,7 +224,14 @@ export function createServerCompiler(options: Options) {
|
|||
logger.debug('[esbuild]', `start compile for: ${JSON.stringify(buildOptions.entryPoints)}`);
|
||||
|
||||
try {
|
||||
const esbuildResult = await esbuild.build(buildOptions);
|
||||
let esbuildResult: esbuild.BuildResult;
|
||||
let context: esbuild.BuildContext;
|
||||
if (dev) {
|
||||
context = await esbuild.context(buildOptions);
|
||||
esbuildResult = await context.rebuild();
|
||||
} else {
|
||||
esbuildResult = await esbuild.build(buildOptions);
|
||||
}
|
||||
|
||||
logger.debug('[esbuild]', `time cost: ${new Date().getTime() - startTime}ms`);
|
||||
|
||||
|
|
@ -243,6 +250,7 @@ export function createServerCompiler(options: Options) {
|
|||
|
||||
return {
|
||||
...esbuildResult,
|
||||
context,
|
||||
serverEntry,
|
||||
};
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ async function webpackCompiler(options: {
|
|||
[IMPORT_META_TARGET]: JSON.stringify(target),
|
||||
[IMPORT_META_RENDERER]: JSON.stringify('server'),
|
||||
},
|
||||
incremental: command === 'start',
|
||||
});
|
||||
webpackConfig.plugins.push(serverCompilerPlugin);
|
||||
}
|
||||
|
|
@ -104,7 +103,7 @@ async function webpackCompiler(options: {
|
|||
}),
|
||||
);
|
||||
const debounceCompile = debounce(() => {
|
||||
serverCompilerPlugin?.buildResult?.rebuild();
|
||||
serverCompilerPlugin?.buildResult?.context.rebuild();
|
||||
console.log('Document updated, try to reload page for latest html content.');
|
||||
}, 200);
|
||||
watch.addEvent([
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export interface TargetDeclarationData {
|
|||
declarationType?: DeclarationType;
|
||||
}
|
||||
|
||||
export type RenderData = Record<string, unknown>;
|
||||
export type RenderData = Record<string, any>;
|
||||
type RenderDataFunction = (renderDataFunction: RenderData) => RenderData;
|
||||
export interface TemplateOptions {
|
||||
template: string;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type webpack from '@ice/bundles/compiled/webpack';
|
|||
import type { _Plugin, CommandArgs, TaskConfig } from 'build-scripts';
|
||||
import type { Configuration, Stats, WebpackOptionsNormalized } from '@ice/bundles/compiled/webpack';
|
||||
import type { esbuild } from '@ice/bundles';
|
||||
import type { NestedRouteManifest } from '@ice/route-manifest';
|
||||
import type { DefineExtraRoutes, NestedRouteManifest } from '@ice/route-manifest';
|
||||
import type { Config } from '@ice/webpack-config/types';
|
||||
import type { AppConfig, AssetsManifest } from '@ice/runtime/types';
|
||||
import type ServerCompileTask from '../utils/ServerCompileTask.js';
|
||||
|
|
@ -37,11 +37,14 @@ type ServerCompilerBuildOptions = Pick<
|
|||
'plugins' |
|
||||
'logLevel' |
|
||||
'sourcemap' |
|
||||
'metafile' |
|
||||
'incremental'
|
||||
'metafile'
|
||||
>;
|
||||
|
||||
export type ServerBuildResult = Partial<esbuild.BuildResult & { serverEntry: string; error: any }>;
|
||||
export type ServerBuildResult =
|
||||
Partial<
|
||||
esbuild.BuildResult &
|
||||
{ serverEntry: string; error: any; context: esbuild.BuildContext<esbuild.BuildOptions> }
|
||||
>;
|
||||
|
||||
export interface CompilerOptions {
|
||||
swc?: Config['swcOptions'];
|
||||
|
|
@ -158,6 +161,7 @@ export interface ExtendsPluginAPI {
|
|||
getRouteManifest: () => Routes;
|
||||
getFlattenRoutes: () => string[];
|
||||
getRoutesFile: () => string[];
|
||||
addRoutesDefinition: (defineRoutes: DefineExtraRoutes) => void;
|
||||
dataCache: Map<string, string>;
|
||||
createLogger: CreateLogger;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,128 +0,0 @@
|
|||
import type { NodePath } from '@babel/traverse';
|
||||
import * as t from '@babel/types';
|
||||
|
||||
const removeUnreferencedCode = (nodePath: NodePath<t.Program>) => {
|
||||
let hasRemoved = false;
|
||||
|
||||
// Update bindings removed in enter hooks.
|
||||
nodePath.scope.crawl();
|
||||
for (const [, binding] of Object.entries(nodePath.scope.bindings)) {
|
||||
if (!binding.referenced && binding.path.node) {
|
||||
const nodeType = binding.path.node.type;
|
||||
if (['VariableDeclarator', 'ImportSpecifier', 'FunctionDeclaration'].includes(nodeType)) {
|
||||
if (nodeType === 'ImportSpecifier' && (binding.path.parentPath.node as t.ImportDeclaration)?.specifiers.length === 1) {
|
||||
binding.path.parentPath.remove();
|
||||
} else if (nodeType === 'VariableDeclarator') {
|
||||
if (binding.identifier === binding.path.node.id) {
|
||||
binding.path.remove();
|
||||
} else {
|
||||
if (binding.path.node.id.type === 'ArrayPattern') {
|
||||
binding.path.node.id.elements = binding.path.node.id.elements.filter((element) =>
|
||||
(element !== binding.identifier && (element as t.RestElement)?.argument !== binding.identifier));
|
||||
if (binding.path.node.id.elements.length === 0) {
|
||||
binding.path.remove();
|
||||
}
|
||||
} else if (binding.path.node.id.type === 'ObjectPattern') {
|
||||
binding.path.node.id.properties = binding.path.node.id.properties.filter((property) => {
|
||||
const { value, key } = property as t.ObjectProperty;
|
||||
const argument = (property as t.RestElement)?.argument;
|
||||
return value !== binding.identifier && argument !== binding.identifier &&
|
||||
(key?.type !== 'Identifier' || (key as t.Identifier)?.name !== binding.identifier.name);
|
||||
});
|
||||
if (binding.path.node.id.properties.length === 0) {
|
||||
binding.path.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.path.remove();
|
||||
}
|
||||
hasRemoved = true;
|
||||
} else if (['ImportDefaultSpecifier'].includes(nodeType)) {
|
||||
binding.path.parentPath.remove();
|
||||
hasRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasRemoved) {
|
||||
// Remove code until there is no more to removed.
|
||||
removeUnreferencedCode(nodePath);
|
||||
}
|
||||
};
|
||||
|
||||
const keepExportCode = (identifier: t.Identifier, keepExports: string[]) => {
|
||||
return keepExports.some((exportString) => {
|
||||
return t.isIdentifier(identifier, { name: exportString });
|
||||
});
|
||||
};
|
||||
|
||||
const removeTopLevelCode = (keepExports: string[] = []) => {
|
||||
return {
|
||||
ExportNamedDeclaration: {
|
||||
enter(nodePath: NodePath<t.ExportNamedDeclaration>) {
|
||||
const { node } = nodePath;
|
||||
// Exp: export function pageConfig() {}
|
||||
const isFunctionExport = t.isFunctionDeclaration(node.declaration) &&
|
||||
keepExportCode(node.declaration.id, keepExports);
|
||||
// Exp: export const pageConfig = () => {}
|
||||
const isVariableExport = t.isVariableDeclaration(node.declaration) &&
|
||||
keepExportCode(node.declaration.declarations![0]?.id as t.Identifier, keepExports);
|
||||
// Exp: export { pageConfig };
|
||||
if (node.specifiers && node.specifiers.length > 0) {
|
||||
nodePath.traverse({
|
||||
ExportSpecifier(nodePath: NodePath<t.ExportSpecifier>) {
|
||||
if (!keepExportCode(nodePath.node.exported as t.Identifier, keepExports)) {
|
||||
nodePath.remove();
|
||||
}
|
||||
},
|
||||
});
|
||||
node.specifiers = node.specifiers.filter(specifier =>
|
||||
keepExportCode(specifier.exported as t.Identifier, keepExports));
|
||||
} else if (!isFunctionExport && !isVariableExport) {
|
||||
// Remove named export expect defined in keepExports.
|
||||
nodePath.remove();
|
||||
}
|
||||
},
|
||||
},
|
||||
ExportDefaultDeclaration: {
|
||||
enter(nodePath: NodePath<t.ExportDefaultDeclaration>) {
|
||||
// Remove default export declaration.
|
||||
if (!keepExports.includes('default')) {
|
||||
nodePath.remove();
|
||||
}
|
||||
},
|
||||
},
|
||||
ExpressionStatement: {
|
||||
enter(nodePath: NodePath<t.ExpressionStatement>) {
|
||||
// Remove top level call expression.
|
||||
if (nodePath.parentPath.isProgram()) {
|
||||
if (t.isCallExpression(nodePath.node.expression) || t.isAssignmentExpression(nodePath.node.expression)) {
|
||||
nodePath.remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
ImportDeclaration: {
|
||||
enter(nodePath: NodePath<t.ImportDeclaration>) {
|
||||
// Remove import statement without specifiers.
|
||||
if (nodePath.node.specifiers.length === 0) {
|
||||
nodePath.remove();
|
||||
}
|
||||
},
|
||||
},
|
||||
'IfStatement|TryStatement|WhileStatement|DoWhileStatement': {
|
||||
// Remove statement even if it's may cause variable changed.
|
||||
enter(nodePath: NodePath<t.IfStatement | t.TryStatement | t.WhileStatement>) {
|
||||
// TODO: check expression statement if it is changed top level variable referenced by pageConfig
|
||||
nodePath.remove();
|
||||
},
|
||||
},
|
||||
Program: {
|
||||
exit(nodePath: NodePath<t.Program>) {
|
||||
removeUnreferencedCode(nodePath);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default removeTopLevelCode;
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
import * as path from 'path';
|
||||
import { RUNTIME_TMP_DIR } from '../constant.js';
|
||||
import type { PluginData } from '../types/plugin.js';
|
||||
import formatPath from './formatPath.js';
|
||||
|
||||
export interface RuntimeModule {
|
||||
staticRuntime: boolean;
|
||||
|
|
@ -6,10 +9,18 @@ export interface RuntimeModule {
|
|||
name: string;
|
||||
}
|
||||
|
||||
function getRuntimeModules(plugins: PluginData[]) {
|
||||
function getRuntimeModules(plugins: PluginData[], rootDir: string) {
|
||||
return plugins
|
||||
.filter(({ runtime }) => !!runtime)
|
||||
.map(({ name, runtime, staticRuntime }) => ({ name, path: runtime, staticRuntime }));
|
||||
.map(({ name, runtime, staticRuntime }) => {
|
||||
return {
|
||||
name,
|
||||
path: path.isAbsolute(runtime)
|
||||
? formatPath(path.relative(path.join(rootDir, RUNTIME_TMP_DIR), runtime)) // Be compatible with win32.
|
||||
: runtime,
|
||||
staticRuntime,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export default getRuntimeModules;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ interface Options {
|
|||
userConfig: UserConfig;
|
||||
outputDir: string;
|
||||
serverEntry: string;
|
||||
incremental: boolean;
|
||||
serverCompileTask: ExtendsPluginAPI['serverCompileTask'];
|
||||
ensureRoutesConfig: () => Promise<void>;
|
||||
runtimeDefineVars: Record<string, string>;
|
||||
|
|
@ -25,7 +24,6 @@ function getServerCompilerPlugin(serverCompiler: ServerCompiler, options: Option
|
|||
serverCompileTask,
|
||||
ensureRoutesConfig,
|
||||
runtimeDefineVars,
|
||||
incremental,
|
||||
} = options;
|
||||
const entryPoint = getServerEntry(rootDir, serverEntry);
|
||||
const { ssg, ssr, server: { format } } = userConfig;
|
||||
|
|
@ -43,7 +41,6 @@ function getServerCompilerPlugin(serverCompiler: ServerCompiler, options: Option
|
|||
outExtension: { '.js': isEsm ? '.mjs' : '.cjs' },
|
||||
metafile: true,
|
||||
logLevel: 'silent', // The server compiler process will log it in debug.
|
||||
incremental,
|
||||
},
|
||||
{
|
||||
// The server bundle will external all the dependencies when the format type is esm,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ function injectInitialEntry(routeManifest: RouteManifest, outputDir: string) {
|
|||
const routePaths = routeManifest.getFlattenRoute();
|
||||
const routeItems = routeManifest.getNestedRoute();
|
||||
routePaths.forEach((routePath) => {
|
||||
const routeAsset = getRouteAsset(routeItems, routePath);
|
||||
const routeAsset = getRouteAsset(routeItems as unknown as RouteItem[], routePath);
|
||||
// Inject `initialPath` when router type is memory.
|
||||
const routeAssetPath = path.join(outputDir, 'js', routeAsset);
|
||||
if (fse.existsSync(routeAssetPath)) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import type { NestedRouteManifest } from '@ice/route-manifest';
|
||||
import type { NestedRouteManifest, DefineExtraRoutes } from '@ice/route-manifest';
|
||||
import getRoutePath, { getRoutesFile } from './getRoutePaths.js';
|
||||
|
||||
export default class RouteManifest {
|
||||
private routeManifest: NestedRouteManifest[];
|
||||
private routesDefinitions: DefineExtraRoutes[];
|
||||
|
||||
constructor() {
|
||||
this.routeManifest = null;
|
||||
this.routesDefinitions = [];
|
||||
}
|
||||
|
||||
getNestedRoute() {
|
||||
|
|
@ -26,4 +28,12 @@ export default class RouteManifest {
|
|||
getRoutesFile() {
|
||||
return getRoutesFile(this.getNestedRoute());
|
||||
}
|
||||
}
|
||||
|
||||
public addRoutesDefinition(defineRoutes: DefineExtraRoutes) {
|
||||
this.routesDefinitions.push(defineRoutes);
|
||||
}
|
||||
|
||||
public getRoutesDefinitions() {
|
||||
return this.routesDefinitions;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export default class DataLoaderPlugin {
|
|||
const { outputFiles, error } = await this.serverCompiler(
|
||||
{
|
||||
target: 'es6', // should not set to esnext, https://github.com/alibaba/ice/issues/5830
|
||||
format: 'iife',
|
||||
entryPoints: [filePath],
|
||||
write: false,
|
||||
logLevel: 'silent', // The main server compile process will log it.
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ export default class ServerCompilerPlugin {
|
|||
this.isCompiling = false;
|
||||
await this.compileTask(compilation);
|
||||
|
||||
const compilerTask = this.buildResult?.rebuild
|
||||
? this.buildResult.rebuild()
|
||||
const compilerTask = this.buildResult?.context.rebuild
|
||||
? this.buildResult.context.rebuild()
|
||||
.then((result) => {
|
||||
return {
|
||||
// Pass original buildResult, because it's returned serverEntry.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { runClientApp, getAppConfig } from '<%- iceRuntimePath %>';
|
|||
import { commons, statics } from './runtimeModules';
|
||||
import * as app from '@/app';
|
||||
<% if (enableRoutes) { -%>
|
||||
import routes from './routes';
|
||||
import createRoutes from './routes';
|
||||
<% } -%>
|
||||
<%- runtimeOptions.imports %>
|
||||
<% if(dataLoaderImport.imports) {-%><%-dataLoaderImport.imports%><% } -%>
|
||||
|
|
@ -16,25 +16,39 @@ const getRouterBasename = () => {
|
|||
// Otherwise chunk of route component will pack @ice/jsx-runtime and depend on framework bundle.
|
||||
const App = <></>;
|
||||
|
||||
const render = (customOptions = {}) => {
|
||||
<% if(!dataLoaderImport.imports) {-%>
|
||||
let dataLoaderFetcher = (options) => {
|
||||
window.fetch(options.url, options);
|
||||
}
|
||||
|
||||
let dataLoaderDecorator = (dataLoader) => {
|
||||
return dataLoader;
|
||||
}
|
||||
<% } -%>
|
||||
|
||||
const render = (customOptions: Record<string, any> = {}) => {
|
||||
const appProps = {
|
||||
app,
|
||||
runtimeModules: {
|
||||
commons,
|
||||
statics,
|
||||
},
|
||||
<% if (enableRoutes) { %>routes,<% } %>
|
||||
<% if (enableRoutes) { %>createRoutes,<% } %>
|
||||
basename: getRouterBasename(),
|
||||
hydrate: <%- hydrate %>,
|
||||
memoryRouter: <%- memoryRouter || false %>,
|
||||
<% if(dataLoaderImport.imports) {-%>dataLoaderFetcher,<% } -%>
|
||||
dataLoaderFetcher,
|
||||
dataLoaderDecorator,
|
||||
...customOptions,
|
||||
<% if (runtimeOptions.exports) { -%>
|
||||
runtimeOptions: {
|
||||
<%- runtimeOptions.exports %>
|
||||
...(customOptions.runtimeOptions || {}),
|
||||
<% if (runtimeOptions.exports) { -%>
|
||||
<%- runtimeOptions.exports %>
|
||||
<% } -%>
|
||||
<% if (locals.customRuntimeOptions) { -%>
|
||||
...<%- JSON.stringify(customRuntimeOptions) %>,
|
||||
<% } -%>
|
||||
...customOptions.runtimeOptions,
|
||||
},
|
||||
<% } -%>
|
||||
};
|
||||
return runClientApp(appProps);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import Document from '@/document';
|
|||
import type { RenderMode, DistType } from '@ice/runtime';
|
||||
// @ts-ignore
|
||||
import assetsManifest from 'virtual:assets-manifest.json';
|
||||
import routes from './routes';
|
||||
import createRoutes from './routes';
|
||||
import routesConfig from './routes-config.bundle.mjs';
|
||||
<% if(dataLoaderImport.imports) {-%><%-dataLoaderImport.imports%><% } -%>
|
||||
<%- runtimeOptions.imports %>
|
||||
|
|
@ -47,7 +47,7 @@ interface RenderOptions {
|
|||
export async function renderToHTML(requestContext, options: RenderOptions = {}) {
|
||||
const { renderMode = 'SSR' } = options;
|
||||
setRuntimeEnv(renderMode);
|
||||
|
||||
|
||||
const mergedOptions = mergeOptions(options);
|
||||
return await runtime.renderToHTML(requestContext, mergedOptions);
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ export async function renderToHTML(requestContext, options: RenderOptions = {})
|
|||
export async function renderToResponse(requestContext, options: RenderOptions = {}) {
|
||||
const { renderMode = 'SSR' } = options;
|
||||
setRuntimeEnv(renderMode);
|
||||
|
||||
|
||||
const mergedOptions = mergeOptions(options);
|
||||
return runtime.renderToResponse(requestContext, mergedOptions);
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ function mergeOptions(options) {
|
|||
return {
|
||||
app,
|
||||
assetsManifest,
|
||||
routes,
|
||||
createRoutes,
|
||||
runtimeModules,
|
||||
Document,
|
||||
serverOnlyBasename,
|
||||
|
|
@ -92,10 +92,13 @@ function mergeOptions(options) {
|
|||
routesConfig,
|
||||
distType,
|
||||
serverData,
|
||||
<% if (runtimeOptions.exports) { -%>
|
||||
runtimeOptions: {
|
||||
<% if (runtimeOptions.exports) { -%>
|
||||
<%- runtimeOptions.exports %>
|
||||
<% } -%>
|
||||
<% if (locals.customRuntimeOptions) { _%>
|
||||
...<%- JSON.stringify(customRuntimeOptions) %>,
|
||||
<% } _%>
|
||||
},
|
||||
<% } -%>
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
<%- routeImports.length ? routeImports.join('\n') + '\n\n' : ''; -%>
|
||||
export default [
|
||||
<%- routeDefination %>
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { createRouteLoader, WrapRouteComponent, RouteErrorComponent } from '@ice/runtime';
|
||||
<%- routeImports.length ? routeImports.join('\n') + '\n\n' : ''; -%>
|
||||
export default ({
|
||||
requestContext,
|
||||
renderMode,
|
||||
}) => ([
|
||||
<%- routeDefinition %>
|
||||
]);
|
||||
|
|
@ -20,7 +20,11 @@ const loaders = {
|
|||
<% if(!dataLoaderImport.imports) {-%>
|
||||
let dataLoaderFetcher = (options) => {
|
||||
window.fetch(options.url, options);
|
||||
}
|
||||
}
|
||||
|
||||
let dataLoaderDecorator = (dataLoader) => {
|
||||
return dataLoader;
|
||||
}
|
||||
<% } -%>
|
||||
|
||||
// Only init static runtime in data-loader.
|
||||
|
|
@ -32,6 +36,7 @@ const staticRuntimeModules = [
|
|||
|
||||
dataLoader.init(loaders, {
|
||||
fetcher: dataLoaderFetcher,
|
||||
decorator: dataLoaderDecorator,
|
||||
runtimeModules: staticRuntimeModules,
|
||||
appExport: app,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
const a = 1;
|
||||
export default a;
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
const pageConfig = () => {};
|
||||
const getData = () => {};
|
||||
export {
|
||||
pageConfig,
|
||||
getData,
|
||||
};
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
export const getData = () => {};
|
||||
export const pageConfig = () => {};
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
const a = {};
|
||||
a.test = 1;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export default function Bar() {}
|
||||
export function pageConfig() {}
|
||||
export function getData() {}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
let a = 1;
|
||||
if (true) {
|
||||
a = 2;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
function a() {}
|
||||
a();
|
||||
console.log('test', window.a);
|
||||
const b = [];
|
||||
b.map(() => {});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue