mirror of https://github.com/alibaba/ice.git
文档 (#203)
* feat: docs directory * docs: 调整结构 * chore: lock * feat: update docs * docs: update assets doc * 新增文档 for 介绍 and 环境变量 (#307) * docs: add about * docs: add docs for env * docs: update about * docs: config (#306) * docs: router (#304) * docs: router * feat: getconfig * docs: get data * docs: ssg * docs: ssr * docs: document * docs: page * docs: enable ssr * fix: title * Doc/rax compat (#303) * docs: add docs of rax-compat * docs: modify doc of rax compat * Docs: app entry (#301) * docs: app entry * docs: app entry * docs: mock (#245) * docs: mock * chore: typo * chore: title * docs: styles (#244) * docs: style * chore: acss title * Docs: contributing (#243) * docs: contributing * chore: typo * chore: update contributing docs * fix: typo * chore: add putteteer install * docs: quick start (#235) * docs: quick start * chore: update IDE * chore: update docs * docs: app directory (#236) * docs: directory * chore: document desc * docs: update website * docs: update about * docs: update docs * chore: update prism * chore: update docs * chore: update Co-authored-by: luhc228 <luhengchang228@126.com> Co-authored-by: ClarkXia <xiawenwu41@gmail.com> Co-authored-by: 逆葵 <xianyong.yxy@alibaba-inc.com> Co-authored-by: ZeroLing <zhuoling.lcl@alibaba-inc.com> Co-authored-by: ZeroLing <i@zeroling.com> Co-authored-by: 水澜 <shuilan.cj@taobao.com> Co-authored-by: 染陌同学 <answershuto@gmail.com> Co-authored-by: luhc228 <44047106+luhc228@users.noreply.github.com>
This commit is contained in:
parent
e02776c610
commit
8dec98d0e8
|
|
@ -43,7 +43,8 @@ jobs:
|
|||
# 部署到 GitHub Pages
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||
if: github.ref == 'refs/heads/master'
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/release-next'
|
||||
with:
|
||||
BRANCH: gh-pages
|
||||
FOLDER: website/build
|
||||
repositoryName: ice-lab/site-v3
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
# 参与贡献
|
||||
|
||||
## 环境准备
|
||||
|
||||
1. 保证 Node.js 版本是 Node.js 14 以上。推荐安装 Node.js 16+ 版本,会大大提升本地调试速度
|
||||
2. ICE 仓库是 `monorepo`,并使用 `pnpm workspace`。因此需要安装 [pnpm](https://pnpm.io/) 包管理工具
|
||||
3. 在项目根目录下执行 `pnpm setup` 后会安装依赖和编译代码
|
||||
|
||||
> 如果在安装 puppeteer 的时候过慢,可以参考此 [issue](https://github.com/puppeteer/puppeteer/issues/6833#issuecomment-863488626) 进行配置 chromium 缓存。
|
||||
|
||||
## 目录说明
|
||||
|
||||
```markdown
|
||||
ice-next
|
||||
├── examples # 存档各种示例代码
|
||||
├── packages # 存放 npm 包
|
||||
| ├── bundles # 依赖预编译,锁定框架三方依赖版本,框架中的依赖需要从此包导入模块
|
||||
| ├── ice # 工程代码,包括创建 service、构建任务、Webpack 和 esbuild 的打包编译逻辑等
|
||||
| ├── plugin-auth # Auth 插件
|
||||
| ├── route-manifest # 根据约定式路由生成路由配置
|
||||
| ├── runtime # 运行时代码,包括 Client/Server 入口、Document、路由组件等
|
||||
| ├── types # 公共 TS 依赖
|
||||
| └── webpack-config # 存放 Webpack 默认的配置项
|
||||
├── scripts # 执行脚本
|
||||
├── tests # 测试用例
|
||||
| ├── integration
|
||||
| └── utils
|
||||
└── website # ICE 官方文档
|
||||
```
|
||||
|
||||
补充说明:
|
||||
|
||||
1. `packages` 目录下以 `plugin-xxx` 命名的都是插件包,插件的开发规范可以参考[文档]()
|
||||
2. `packages/types` 是用于存放公共的 TS 类型声明,以在其他 `package` 中进行复用
|
||||
|
||||
## 调试
|
||||
|
||||
### 启动 watch 命令
|
||||
|
||||
此命令用于监听 `packages` 目录下代码变更,并增量编译代码。
|
||||
|
||||
```bash
|
||||
pnpm watch
|
||||
```
|
||||
|
||||
### 跑 example
|
||||
|
||||
`examples` 目录下存放了各种用于测试的 demo,并且自动 Link 到 `packages` 目录下的代码。只需执行以下命令即可开始调试:
|
||||
|
||||
```bash
|
||||
# 进入某个 example
|
||||
$ cd examples/basic-project
|
||||
# 调试 example
|
||||
$ pnpm start
|
||||
```
|
||||
|
||||
`packages` 目录下的 `npm` 包在进行代码编译时会生成 `SourceMap`,结合 IDE 可以很方便进行断点调试。以 VS Code 为例:
|
||||
|
||||
1. 选择 `JavaScript Debug Terminal` 进入 Debug 模式:
|
||||

|
||||
|
||||
2. 进入某个 `example` 目录并执行 `pnpm start` 开始调试
|
||||
|
||||
3. 在某一行设置一个断点,当代码执行到此行时,将会停止执行并可查看各个变量的值
|
||||

|
||||
|
||||
## 测试
|
||||
|
||||
ICE 使用 [vitest](https://vitest.dev/) 进行单元测试和集成测试。执行以下命令可快速运行项目中的测试用例:
|
||||
|
||||
```bash
|
||||
# 执行一次测试并生成代码覆盖率
|
||||
$ pnpm test
|
||||
# 启用 Test Watch 模式
|
||||
$ pnpm test:watch
|
||||
# 只跑部分测试用例
|
||||
$ pnpm test basic-project.test.ts
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
ICE 的文档使用了 [docusaurus](https://docusaurus.io/) 进行搭建。执行以下命令即可开始文档的开发:
|
||||
|
||||
```bash
|
||||
# 进入到 website 目录
|
||||
$ cd websites
|
||||
# 安装依赖
|
||||
$ yarn install
|
||||
# 本地预览
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
## 发布
|
||||
|
||||
```bash
|
||||
# 发布 alpha 版本
|
||||
$ pnpm publish:alpha
|
||||
# 发布 beta 版本
|
||||
$ pnpm publish:beta
|
||||
```
|
||||
|
|
@ -15948,7 +15948,6 @@ packages:
|
|||
- '@swc/core'
|
||||
- esbuild
|
||||
- uglify-js
|
||||
dev: true
|
||||
|
||||
/webpack/5.73.0_@swc+core@1.2.168:
|
||||
resolution: {integrity: sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 3.0.0 版本发布
|
||||
order: 1
|
||||
---
|
||||
|
|
@ -1,15 +1,6 @@
|
|||
module.exports = {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: '参考',
|
||||
items: [
|
||||
{
|
||||
to: 'https://iceteam.gitee.io',
|
||||
label: '国内镜像站点',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '社区',
|
||||
items: [
|
||||
|
|
@ -21,6 +12,10 @@ module.exports = {
|
|||
label: '阿里内部钉钉群',
|
||||
href: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group-inside.JPG',
|
||||
},
|
||||
{
|
||||
to: 'https://iceteam.gitee.io',
|
||||
label: '国内镜像站点',
|
||||
},
|
||||
{
|
||||
label: 'GitHub Issue',
|
||||
href: 'https://github.com/alibaba/ice/issues',
|
||||
|
|
@ -31,16 +26,12 @@ module.exports = {
|
|||
title: '生态',
|
||||
items: [
|
||||
{
|
||||
label: '微前端 icestark',
|
||||
href: 'http://micro-frontends.ice.work',
|
||||
label: '微前端 ICESTARK',
|
||||
href: 'https://micro-frontends.ice.work/',
|
||||
},
|
||||
{
|
||||
label: 'ahooks',
|
||||
href: 'https://ahooks.js.org/',
|
||||
},
|
||||
{
|
||||
label: 'Formily',
|
||||
href: 'https://v2.formilyjs.org/',
|
||||
label: '包开发 ICE PKG',
|
||||
href: 'https://pkg.ice.work/',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -51,18 +42,14 @@ module.exports = {
|
|||
label: '淘系前端',
|
||||
href: 'https://fed.taobao.org/',
|
||||
},
|
||||
{
|
||||
label: 'Rax',
|
||||
href: 'https://rax.js.org',
|
||||
},
|
||||
{
|
||||
label: 'AppWorks',
|
||||
href: 'https://appworks.site',
|
||||
},
|
||||
{
|
||||
label: 'Kraken',
|
||||
href: 'https://openkraken.com/',
|
||||
},
|
||||
// {
|
||||
// label: 'Kraken',
|
||||
// href: 'https://openkraken.com/',
|
||||
// },
|
||||
{
|
||||
label: 'Midway',
|
||||
href: 'https://midwayjs.org/',
|
||||
|
|
|
|||
|
|
@ -14,32 +14,32 @@ module.exports = {
|
|||
position: 'right',
|
||||
label: '指南',
|
||||
},
|
||||
// {
|
||||
// position: 'right',
|
||||
// label: '示例',
|
||||
// to: '/docs/examples/tailwind',
|
||||
// },
|
||||
{
|
||||
position: 'right',
|
||||
label: '插件',
|
||||
to: '/docs/plugin/develop/start',
|
||||
},
|
||||
{
|
||||
position: 'right',
|
||||
label: '示例',
|
||||
to: '/docs/examples/antd',
|
||||
label: '博客',
|
||||
to: '/blog',
|
||||
},
|
||||
{
|
||||
label: '生态',
|
||||
position: 'right',
|
||||
items: [
|
||||
{
|
||||
label: '微前端 icestark',
|
||||
label: '微前端 ICESTARK',
|
||||
to: 'http://micro-frontends.ice.work/',
|
||||
},
|
||||
{
|
||||
label: '包开发 ICE PKG',
|
||||
to: 'https://pkg.ice.work/',
|
||||
},
|
||||
{
|
||||
label: '可视化工具 AppWorks',
|
||||
to: 'https://appworks.site/',
|
||||
},
|
||||
{
|
||||
label: '自定义物料开发',
|
||||
to: 'https://appworks.site/materials/about.html',
|
||||
},
|
||||
{
|
||||
label: '前端环境 AppToolkit',
|
||||
to: 'https://github.com/appworks-lab/toolkit#readme',
|
||||
|
|
@ -52,11 +52,11 @@ module.exports = {
|
|||
items: [
|
||||
{
|
||||
to: 'https://fusion.design/pc/doc/component/102',
|
||||
label: 'fusion 组件',
|
||||
label: 'Fusion 组件',
|
||||
},
|
||||
{
|
||||
to: 'https://ant.design',
|
||||
label: 'antd 组件',
|
||||
label: 'Antd 组件',
|
||||
},
|
||||
{
|
||||
to: 'https://iceteam.gitee.io',
|
||||
|
|
@ -66,16 +66,12 @@ module.exports = {
|
|||
label: '社区钉钉群',
|
||||
to: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group.png',
|
||||
},
|
||||
{
|
||||
label: '阿里内部钉钉群',
|
||||
to: 'https://iceworks.oss-cn-hangzhou.aliyuncs.com/assets/images/ice-group-inside.JPG',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/alibaba/ice',
|
||||
href: 'https://github.com/ice-lab/ice-next',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,34 +9,22 @@ const getDocsFromDir = require('../scripts/getDocsFromDir');
|
|||
module.exports = {
|
||||
docs: [
|
||||
'guide/about',
|
||||
// 'guide/start',
|
||||
// 'guide/upgrade',
|
||||
'guide/start',
|
||||
// 'guide/practice',
|
||||
{
|
||||
type: 'category',
|
||||
label: '基础指南',
|
||||
label: 'ICE 指南',
|
||||
collapsed: false,
|
||||
items: getDocsFromDir('guide/basic'),
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '进阶指南',
|
||||
label: '进阶',
|
||||
collapsed: false,
|
||||
items: getDocsFromDir('guide/advanced'),
|
||||
},
|
||||
],
|
||||
plugin: [
|
||||
{
|
||||
type: 'category',
|
||||
label: '插件开发',
|
||||
collapsed: false,
|
||||
items: getDocsFromDir('plugin/develop'),
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: '官方插件',
|
||||
collapsed: false,
|
||||
items: getDocsFromDir('plugin/list'),
|
||||
},
|
||||
'guide/plugin',
|
||||
'guide/upgrade',
|
||||
],
|
||||
examples: getDocsFromDir('examples'),
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: 使用 antd 组件
|
||||
order: 1
|
||||
order: 2
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 开发 Electron 应用
|
||||
order: 5
|
||||
---
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Module Federation
|
||||
order: 4
|
||||
---
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: 使用 fusion 组件
|
||||
order: 2
|
||||
order: 3
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 代码质量
|
||||
order: 4
|
||||
---
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: 使用 Tailwind CSS
|
||||
order: 3
|
||||
order: 1
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,71 @@
|
|||
---
|
||||
title: 关于飞冰
|
||||
title: 关于
|
||||
order: 1
|
||||
---
|
||||
|
||||
About ICE 3.0
|
||||

|
||||
|
||||
飞冰 (ICE) 是一套基于 React 的前端解决方案,核心应用研发框架提供了基础的构建、路由、调试等基础能力以及微前端、一体化等领域能力,同时结合可视化操作、物料复用等方案降低研发门槛。
|
||||
|
||||
## 特性 🎉
|
||||
- 🐒 开箱即用:TypeScript/Webpack5/CSS Modules/Mock/SSR,各种方案 All in One
|
||||
- 🦊 贴合业务的最佳实践:目录规范、代码规范、路由方案、状态管理、数据请求等
|
||||
- 🐯 多种应用模式:支持服务端渲染 SSR 以及静态构建 SSG
|
||||
- 🐦 强大的插件能力:官方所有能力都通过插件实现,业务可以通过插件扩展各种能力
|
||||
- 🐘 丰富的领域方案:微前端 ICESTARK、一体化方案等
|
||||
|
||||
在应用框架之上,我们还提供了 NPM 包开发工具 [ICE PKG](https://pkg.ice.work):
|
||||
|
||||
- 提供 React 组件开发、Node.js 模块开发、前端通用库等[多场景需求](https://pkg.ice.work/scenarios/component)
|
||||
- 组件开发提供基础研发范式,提供组件文档、示例、预览等功能,[查看文档](https://pkg.ice.work/guide/preview)
|
||||
- 更多场景可以通过插件的方式完成定制,查看[插件开发](https://pkg.ice.work/reference/plugins-development)
|
||||
|
||||
你也可以搭配 VS Code 插件 AppWorks 享受到更多功能:
|
||||
|
||||
- 通过大量的官方模板(fusion/antd)可视化创建项目,[查看更多](https://appworks.site/materialCenter/react.html)
|
||||
- 基于 VS Code 插件可视化的调试、管理依赖、拼装区块等,[查看文档](https://appworks.site)
|
||||
- 业务可以根据规范定制自己的物料体系(含项目模板),[查看物料开发文档](https://appworks.site/materials/about.html)
|
||||
- ……
|
||||
|
||||
## 常见问题 📝
|
||||
|
||||
### 与直接使用 Webpack 相比,使用 ICE 有什么优势?
|
||||
|
||||
Webpack 只提供了基础的构建能力,ICE 在此基础上扩展了很多能力:
|
||||
|
||||
- 默认集成好的框架能力,无需再引入繁冗的构建插件和配置
|
||||
- 不止是构建,更有面向业务领域的最佳实践,如路由、目录组织、状态管理等
|
||||
- 让很多业务接入成本高的能力可以开箱即用,如 SSR/SSG、微前端、一体化,基于原始的 Webpack 建设这些能力需要付出很高成本
|
||||
- 通过插件化让以上这些能力可以被扩展以及跨项目复用,尽可能保证不同项目的一致性
|
||||
|
||||
### 我正在使用 icejs (ICE 2),需要升级到 ICE 吗?
|
||||
|
||||
ICE 相比之前的版本,增加了更多对移动端能力的优化和适配。升级或不升级都是可行的,原先的 icejs 依然是可用的,而且我们会保证 Bugfix 的持续迭代。如果你的页面会同时运行在移动端和桌面端,使用 ICE 可能会是更好的选择,亦或者是你对 ICE 提供的更新的构建工具链、更优更多的解决方案感兴趣,你都可以选择升级到 ICE。
|
||||
|
||||
### 使用飞冰(ICE)是否需要具备一定的前端基础?
|
||||
|
||||
毫无疑问是需要的,我们在努力降低前端开发的门槛,但一些基础的前端知识还是需要具备的,比如 JavaScript 的基础语法、前后端如何通信等。为了便于快速入门前端知识,我们整理了一份 [前端基础知识](https://ice.work/docs/resource/front-basic),希望能帮助到开发者。
|
||||
|
||||
### 资深前端同学是否适合使用飞冰?
|
||||
适合,面向前端场景飞冰团队有大量的最佳实践,无论是构建、规范、状态管理还是微前端都可以开箱即用。
|
||||
|
||||
### 飞冰的浏览器兼容策略是怎样的?
|
||||
|
||||
应用框架 ICE 默认使用的是 React 18,你可以查看 React 18 官方说明[对 JavaScript 环境的要求](https://zh-hans.reactjs.org/docs/javascript-environment-requirements.html)。如果你支持旧的浏览器和设备,可能需要引入对应的 Polyfill。
|
||||
|
||||
此外,飞冰官方 React 物料默认使用 React 16+ 进行开发,所以通常情况下这些物料在 ICE 中是可以正常运行的,如果你遇到任何问题,也可以通过 [Issue](https://github.com/alibaba/ice/issues) 或其它方式反馈给我们。
|
||||
|
||||
### 飞冰可以使用哪些 UI 组件?
|
||||
|
||||
飞冰的应用框架和工具都不耦合 UI 组件,因此开发者可以选择任意的 React UI 组件使用,比如 Fusion/Antd 等。
|
||||
|
||||
### 飞冰跟低代码方案有什么关系?
|
||||
|
||||
低代码方案一般指以可视化拖拽搭建为主,少量地方使用代码辅助,此类方案往往是面向具体领域而非通用场景的,飞冰是面向通用领域的,以源码研发为主,通过框架、物料、GUI 操作等能力降低研发门槛,因此飞冰并不是通俗意义的低代码方案。
|
||||
|
||||
## 联系我们 🧼
|
||||
|
||||
- 反馈/建议:https://github.com/alibaba/ice/issues/new
|
||||
- 答疑钉钉群:
|
||||
|
||||
<img src="https://ice.alicdn.com/assets/images/qrcode.png" width="300px" align="left"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 权限
|
||||
order: 7
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: 构建部署
|
||||
order: 10
|
||||
---
|
||||
|
||||
About ICE.0
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 一体化
|
||||
order: 8
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 国际化
|
||||
order: 6
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 微前端
|
||||
order: 9
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 单元测试
|
||||
order: 8
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
title: 应用入口
|
||||
order: 4
|
||||
---
|
||||
|
||||
ICE 通过应用配置的方式渲染整个应用,开发者可以根据提供的配置定制应用。
|
||||
|
||||
## 应用配置文件
|
||||
|
||||
框架以 `src/app.ts` 作为应用配置文件:
|
||||
|
||||
```tsx
|
||||
import { defineAppConfig } from 'ice';
|
||||
|
||||
export default defineAppConfig({
|
||||
app: {
|
||||
strict: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
> 推荐通过 `defineAppConfig()` 的方式导出应用配置,以获得良好的类型提示。
|
||||
|
||||
## 配置项
|
||||
|
||||
应用入口的配置项,支持应用常用的相关配置。
|
||||
|
||||
### app
|
||||
|
||||
#### `rootId`
|
||||
根节点 id
|
||||
|
||||
- 类型:`string`
|
||||
- 默认值 `ice-container`
|
||||
|
||||
#### `strict`
|
||||
是否开启 React 的严格模式 (React.StrictMode)
|
||||
|
||||
- 类型 `boolean`
|
||||
- 默认值 `false`
|
||||
|
||||
#### `errorBoundary`
|
||||
是否启用内置的错误边界捕获能力
|
||||
- 类型 `boolean`
|
||||
- 默认值 `false`
|
||||
|
||||
### router
|
||||
|
||||
#### `type`
|
||||
路由类型
|
||||
|
||||
- 类型 `string`,可选值为 `hash` 或 `browser`
|
||||
- 默认为 `browser`
|
||||
|
||||
#### `basename`
|
||||
路由 basename
|
||||
- 类型 `string`
|
||||
- 默认值 `/`
|
||||
|
||||
## 运行时拓展
|
||||
|
||||
应用入口除了支持定义应用配置之外,同时也承担运行时扩展的能力,比如权限配置:
|
||||
|
||||
```js
|
||||
import { defineAppConfig } from 'ice';
|
||||
import { defineAuthConfig } from '@ice/plugin-auth/esm/types';
|
||||
|
||||
// 导出 auth 相关的能力,该能力由 @ice/plugin-auth 插件提供
|
||||
export const auth = defineAuthConfig(() => {
|
||||
return {
|
||||
initialAuth: {
|
||||
admin: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default defineAppConfig({
|
||||
app: {
|
||||
strict: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
[//]: # (更多运行时插件能力,请参考[官方插件](/plugin/list/auth)。)
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
title: 静态资源
|
||||
order: 7
|
||||
---
|
||||
|
||||
ICE 内置了大量规则处理静态资源,一般情况下开发者无需设置资源的处理方式,而对于一些特殊的处理规则框架同样给出了便捷方式和指引
|
||||
|
||||
# 基础规则
|
||||
|
||||
框架内置了针对以下资源的处理:
|
||||
|
||||
- 字体文件:`.woff`、`.woff2`、`.ttf`、`.eot`
|
||||
- sgv 文件 `.svg`
|
||||
- 图片资源 `.png`、`.jpg`、`.webp`、`.jpeg`、`.gif`
|
||||
|
||||
上述资源默认通过资源地址加载,推荐将这些资源放在 `src/assets` 目录下:
|
||||
|
||||
```shell
|
||||
src
|
||||
├── assets/
|
||||
│ ├── logo.png
|
||||
│ └── bg.png // Favicon
|
||||
```
|
||||
|
||||
此时即可在代码中使用这些资源:
|
||||
|
||||
```jsx
|
||||
import logoUrl from '@/assets/logo.png';
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<img src={logoUrl} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
如果资源尺寸小于 8kb,则进行 base64 转码并内联到脚本或样式文件中。
|
||||
|
||||
# 指定处理规则
|
||||
|
||||
对于内置规则不满足特定场景的情况下,框架提供了便捷的方式对资源进行处理
|
||||
|
||||
## URL 引入
|
||||
|
||||
除基础规则中指定资源外,如果还希望通过资源地址的方式进行资源处理的,可以通过如下方式进行指定:
|
||||
|
||||
```jsx
|
||||
import workletURL from 'extra-scalloped-border/worklet.js?url'
|
||||
CSS.paintWorklet.addModule(workletURL);
|
||||
```
|
||||
|
||||
`?url` 等同于为指定资源指定 url-loader
|
||||
|
||||
## 文件内容引入
|
||||
|
||||
通过 `?raw` 后缀声明将资源作为字符串引入:
|
||||
|
||||
```jsx
|
||||
import txtContent from './text.txt?raw';
|
||||
```
|
||||
|
||||
`?raw` 等同于为指定资源指定 raw-loader
|
||||
|
||||
## Worker 引入
|
||||
|
||||
脚本可以通过指定后缀引入为 web worker:
|
||||
|
||||
```jsx
|
||||
import Worker from './worker.js?worker'
|
||||
```
|
||||
|
||||
`?worker` 等同于为指定资源指定 worker-loader
|
||||
|
||||
```jsx
|
||||
import Worker from './worker.js?sharedworker'
|
||||
```
|
||||
|
||||
`?sharedworker` 等同于为指定资源指定 worker-loader,并指定 worker 类型为 SharedWorker
|
||||
|
||||
```jsx
|
||||
import Worker from './worker.js?worker&inline'
|
||||
```
|
||||
|
||||
`?worker&inline`等同于为指定资源指定 worker-loader,并指定配置 `{ inline: 'fallback' }`
|
||||
|
||||
# public 目录
|
||||
|
||||
`public/` 目录作为框架默认的静态资源目录,不被构建工具进行编译的资源都可以放在该目录下。
|
||||
|
||||
比如 `favicon.svg` 文件,我们并不希望该文件名编译(默认静态资源文件名在编译后会生成独立 hash,`favicon.svg` 希望保持原有文件名),在使用时直接在 html 模版中进行引用:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
</head>
|
||||
</html>
|
||||
```
|
||||
|
||||
另外像不被源码引入的资源也存放在 public 目录下,比如设置 externals 后的 umd 链接,在不使用 CDN 的情况下,同样可以直接放在 `public` 目录下。
|
||||
|
||||
`public` 目录中的资源在开发时能直接通过 `/` 根路径访问到,并且打包时会被完整复制到目标目录的根目录下。
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
---
|
||||
title: 构建配置
|
||||
order: 13
|
||||
---
|
||||
|
||||
ICE 支持常用的构建配置项,所有的配置项在 `ice.config.mts` 中设置。
|
||||
|
||||
## 配置文件
|
||||
|
||||
### 构建配置文件
|
||||
|
||||
为了获取良好的类型提示,ICE 推荐以 `ice.config.mts` 作为配置文件:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
publicPath: '/',
|
||||
});
|
||||
```
|
||||
|
||||
### 兼容性配置
|
||||
|
||||
构建的兼容性配置推荐配置在 `.browserslistrc` 文件中:
|
||||
|
||||
```js
|
||||
chrome 55
|
||||
```
|
||||
|
||||
更多配置请参考 [browserslist 文档](https://github.com/browserslist/browserslist#readme)
|
||||
|
||||
## 配置项
|
||||
|
||||
### alias
|
||||
|
||||
- 类型:`Record<string, string | false>`
|
||||
- 默认值:`{}`
|
||||
|
||||
在 icejs 默认配置了 { "@": "./src/" } 的规则,因此项目大多数时候不需要配置,配置完成后则可以更加简单的导入模块了:
|
||||
|
||||
```diff
|
||||
-import CustomTips from '../../../components/CustomTips';
|
||||
+import CustomTips from '@/components/CustomTips';
|
||||
```
|
||||
|
||||
如果需要配置别名对 import 路径进行映射:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
alias: {
|
||||
pages: './src/pages',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### define
|
||||
|
||||
- 类型:`Record<string, string | boolean>`
|
||||
- 默认值:`{}`
|
||||
|
||||
配置运行时变量。
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
define: {
|
||||
ASSETS_VERSION: '0.1.0',
|
||||
'process.env.TEST': true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
在代码中直接使用对应定义的变量:
|
||||
|
||||
```js
|
||||
console.log(ASSETS_VERSION);
|
||||
console.log(process.env.TEST);
|
||||
```
|
||||
|
||||
对于运行时变量,ICE 更加推荐通过[环境变量](./env.md)的方式注入。
|
||||
|
||||
### publicPath
|
||||
|
||||
- 类型:`string`
|
||||
- 默认值:`/`
|
||||
|
||||
配置 Webpack 的 [output.publicPath](https://webpack.js.org/configuration/output/#output-publicpath) 属性,仅在运行 build 命令时生效。
|
||||
|
||||
### devPublicPath
|
||||
|
||||
- 类型:`string`
|
||||
- 默认值:`/`
|
||||
|
||||
同 publicPath 仅在执行 start 时生效。
|
||||
|
||||
### hash
|
||||
|
||||
类型:`boolean | string`
|
||||
默认值:`false`
|
||||
|
||||
如果希望构建后的资源带 hash 版本,可以将 hash 设置为 `true`,也可以设置为 `contenthash` 按文件内容生成 hash 值:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
hash: 'contenthash',
|
||||
});
|
||||
```
|
||||
|
||||
### externals
|
||||
|
||||
类型:`Record<string, string>`
|
||||
默认值:`{}`
|
||||
|
||||
设置哪些模块不打包,转而通过 `<script>` 或其他方式引入,比如:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
externals: {
|
||||
react: 'React',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
对应在 `document.ts` 或者页面模版里添加 CDN 文件:
|
||||
|
||||
```diff
|
||||
import { Main, Scripts } from 'ice';
|
||||
|
||||
function Document() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Main />
|
||||
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/cjs/react.production.min.js"></script>
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default Document;
|
||||
```
|
||||
|
||||
### outputDir
|
||||
|
||||
类型:`string`
|
||||
默认值:`build`
|
||||
|
||||
构建产物输出目录,默认为 `build` 目录
|
||||
|
||||
### proxy
|
||||
|
||||
- 类型:`object`
|
||||
- 默认值:`{}`
|
||||
|
||||
配置 dev 开发阶段的代理功能
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://jsonplaceholder.typicode.com/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: { '^/api' : '' },
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### minify
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`true`
|
||||
|
||||
压缩产物,目前默认仅在 build 阶段生效
|
||||
|
||||
### dropLogLevel
|
||||
|
||||
- 类型:`'trace'|'debug'|'log'|'warn'|'error'`
|
||||
- 默认值:`null`,不移除任何 console 代码
|
||||
|
||||
压缩代码时移除 console.* 相关代码,比如配置了 log 则会移除 console.trace
|
||||
、console.debug、console.log 代码。
|
||||
|
||||
### compileDependencies
|
||||
|
||||
- 类型:`array|boolean`
|
||||
- 默认值:`[]`
|
||||
|
||||
默认情况下为了保证 dev 开发阶段的体验,`node_modules` 下文件不会进行编译,而考虑到 build 阶段对代码体积的极致优化以及兼容性保证,将会对 `node_modules` 下内容也进行编译。
|
||||
如果希望修正默认行为可以进行如下配置,设置为 `true`,不管 dev 还是 build 阶段均编译 `node_modules`:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
compileDependencies: true,
|
||||
});
|
||||
```
|
||||
|
||||
如果明确知道哪些依赖需要进行编译也可以通过正则方式进行设置:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
compileDependencies: [/@alifd\/next/, /need-compile/],
|
||||
});
|
||||
```
|
||||
|
||||
### ssr
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`false`
|
||||
|
||||
是否开启 SSR 能力,更多 SSR 相关内容参考 [SSR 文档](./ssr)。
|
||||
|
||||
### ssg
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`true`
|
||||
|
||||
是否开启 SSG 能力,更多 SSG 相关内容参考 [SSG 文档](./ssg)。
|
||||
|
||||
### server
|
||||
|
||||
- 类型:`{ format: 'esm' | 'cjs'; bundle: boolean }`
|
||||
- 默认值:`{ format: 'esm', bundle: false }`
|
||||
|
||||
SSR / SSG 产物标准,推荐以 ESM 标准进行执行,如果希望打包成一个 cjs 模块,可以进行如下设置:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
format: 'cjs',
|
||||
bundle: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### routes
|
||||
|
||||
- 类型:`{ignoreFiles: string[]; defineRoutes: (route) => void}`
|
||||
- 默认值:`{}`
|
||||
|
||||
定制路由地址,对于约定式路由不满足的场景,可以通过 `routes` 方式进行自定义:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
routes: {
|
||||
// 忽略 pages 下的 components 目录
|
||||
ignoreFiles: ['**/components/**'],
|
||||
defineRoutes: (route) => {
|
||||
// 将 /about-me 路由访问内容指定为 about.tsx
|
||||
route('/about-me', 'about.tsx');
|
||||
|
||||
// 为 /product 路由添加 layout.tsx 作为 layout,并渲染 products.tsx 内容
|
||||
route('/', 'layout.tsx', () => {
|
||||
route('/product', 'products.tsx');
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### sourceMap
|
||||
|
||||
- 类型:`boolean | string`
|
||||
- 默认值:`development` 模式:默认为 'cheap-module-source-map',支持通过 `false` 关闭,不支持设置为其他枚举值。`production` 模式:默认 `false`。
|
||||
|
||||
### tsChecker
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`false`
|
||||
|
||||
默认关闭 TypeScript 类型检测,如需开启配置为 `true` 即可。
|
||||
|
||||
### eslint
|
||||
|
||||
- 类型:`boolean | object`
|
||||
- 默认值:`undefined`
|
||||
|
||||
配置说明:
|
||||
- `false`:不检测 eslint 错误
|
||||
- `true`:将 eslint 错误展示在预览页面上
|
||||
- `object`: 仅 Webpack 模式支持,表现等同于 true,支持配置 [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin) 的更多参数
|
||||
|
||||
### mock
|
||||
|
||||
- 类型:`boolean`
|
||||
- 默认值:`true`
|
||||
|
||||
默认开启 mock 服务,如需关闭配置为 `false` 即可。
|
||||
|
||||
### webpack
|
||||
|
||||
- 类型:`(config: WebpackConfig, taskConfig: TaskConfig) => WebpackConfig`
|
||||
- 默认值:`true`
|
||||
|
||||
ICE 默认基于 webpack 进行构建,在上述提供的构建配置无法满足的情况下,用户可以定制 webpack 配置:
|
||||
|
||||
```js
|
||||
import { defineConfig } from '@ice/app';
|
||||
import SpeedMeasurePlugin from 'speed-measure-webpack-plugin';
|
||||
|
||||
export default defineConfig({
|
||||
webpack: (webpackConfig) => {
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
// 添加 webpack 插件
|
||||
webpackConfig.plugins?.push(new SpeedMeasurePlugin());
|
||||
}
|
||||
return webpackConfig;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
> ICE 对 webpack 构建配置进行了定制,并借助 esbuild 等工具提升用户开发体验,直接修改 webpack 配置的方式并不推荐。
|
||||
> 如有定制需求欢迎👏 PR 或反馈:https://github.com/alibaba/ice/issues
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
title: 开发环境
|
||||
order: 1
|
||||
---
|
||||
|
||||
## Node.js
|
||||
|
||||
开发前端应用前需要安装 [Node.js](https://nodejs.org),并确保 node 版本是 14.x 或以上。推荐使用 [nvm](https://github.com/nvm-sh/nvm) 或者 [fnm](https://github.com/Schniz/fnm) 来管理 node 版本,进行安装。下面以在 mac 下安装 nvm 为例:
|
||||
|
||||
```bash
|
||||
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
|
||||
# 安装 node 14 版本
|
||||
$ nvm install 14
|
||||
# 使用 node 14
|
||||
$ nvm use 14
|
||||
# 验证 node 是否安装成功
|
||||
$ node -v
|
||||
v14.19.3
|
||||
```
|
||||
|
||||
在国内使用 npm 安装依赖可能会比较慢。建议使用国内镜像源进行加速:
|
||||
|
||||
```bash
|
||||
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
|
||||
# 验证 cnpm 安装是否成功
|
||||
$ cnpm -v
|
||||
```
|
||||
|
||||
### 包管理工具
|
||||
|
||||
安装 Node.js 后,默认会包含 npm。除此以外,还有其他的包管理工具:
|
||||
|
||||
- [pnpm](https://pnpm.io/)(推荐)
|
||||
- [cnpm](https://www.npmjs.com/package/cnpm)(推荐)
|
||||
- [yarn](https://yarnpkg.com/)
|
||||
|
||||
安装 pnpm 示例如下:
|
||||
|
||||
```bash
|
||||
$ npm i pnpm -g --register=https://registry.npmmirror.com/
|
||||
# 验证 pnpm 安装是否成功
|
||||
$ pnpm -v
|
||||
7.1.7
|
||||
```
|
||||
|
||||
如果经常需要切换 npm 镜像源,推荐使用 [nrm](https://github.com/Pana/nrm) 进行管理:
|
||||
|
||||
```bash
|
||||
$ npm install -g nrm
|
||||
# 验证 nrm 是否安装成功
|
||||
$ nrm --version
|
||||
# 查看所有镜像源
|
||||
$ nrm ls
|
||||
# 推荐使用淘宝镜像源
|
||||
nrm use taobao
|
||||
```
|
||||
|
||||
### IDE
|
||||
|
||||
推荐使用 IDE 进行前端应用开发和调试,会有更好的调试体验。目前比较流行的 IDE 有:
|
||||
|
||||
- [Visual Studio Code](https://code.visualstudio.com/)(推荐)
|
||||
- [WebStorm](https://www.jetbrains.com/webstorm/)(推荐)
|
||||
- [Sublime Text](https://www.sublimetext.com/)
|
||||
- [Atom](https://atom.io/)
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
title: 目录结构
|
||||
order: 1
|
||||
---
|
||||
|
||||
ICE 的默认应用目录提供了良好的代码分层结构,约定的目录结构如下:
|
||||
|
||||
```bash
|
||||
├── build // 构建产物目录
|
||||
├── mock // 本地模拟数据
|
||||
│ ├── index.ts
|
||||
├── public // 静态资源目录
|
||||
│ └── favicon.ico // Favicon 图标
|
||||
├── src // 源码目录
|
||||
│ ├── components // 自定义业务组件
|
||||
│ ├── pages // 路由页面组件
|
||||
| | ├── about.tsx
|
||||
| | ├── home.tsx
|
||||
| | └── layout.tsx // 全局布局组件
|
||||
│ ├── global.css // 全局样式
|
||||
│ ├── document.tsx // HTML 模板
|
||||
│ └── app.ts // 应用入口
|
||||
├── .env // 环境变量配置文件
|
||||
├── ice.config.mts // 构建配置
|
||||
├── package.json
|
||||
└── tsconfig.json // TypeScript 配置文件
|
||||
```
|
||||
|
||||
## package.json
|
||||
|
||||
声明应用所需要的各种依赖或者插件,以及配置信息(比如名称、版本、许可证等元数据)。
|
||||
|
||||
## ice.config.mts
|
||||
|
||||
应用的构建配置文件。详见 [构建配置](./config)。
|
||||
|
||||
## .env
|
||||
|
||||
配置环境变量。详见 [环境变量](./env)。
|
||||
|
||||
## tsconfig.json
|
||||
|
||||
TypeScript 编译所需的配置文件。
|
||||
|
||||
## mock 目录
|
||||
|
||||
存放 mock 文件,用于本地模拟请求数据服务。详见 [Mock](./mock)。
|
||||
|
||||
## public 目录
|
||||
|
||||
用于存放静态资源(如 `favicon.ico`)的目录,此目录下所有的文件会被复制到构建产物目录中。
|
||||
|
||||
## src 目录
|
||||
|
||||
用于存放源码的目录
|
||||
|
||||
### app.ts
|
||||
|
||||
项目的入口文件,用于对应用进行全局运行时配置,包括路由、添加 Provider 等。详见[应用入口](/docs/guide/basic/app)。
|
||||
|
||||
### document.tsx
|
||||
|
||||
HTML 模板,使用 JSX 语法来描述,与 `index.html` 类似用于生成 HTML 产物。详见 [Document](/docs/guide/basic/document)。
|
||||
|
||||
### global.[css|scss|less]
|
||||
|
||||
全局的样式配置,框架默认会引入该文件。详见[样式方案](/docs/guide/basic/style)
|
||||
|
||||
### pages 目录
|
||||
|
||||
存放路由组件的目录。ICE 使用约定式路由,会自动根据文件生成路由规则,详见[路由](/docs/guide/basic/router)。
|
||||
|
||||
### components 目录
|
||||
|
||||
项目通用的组件目录,推荐的目录形式如下:
|
||||
|
||||
```bash
|
||||
src
|
||||
├── components
|
||||
| └── Guide
|
||||
| ├── index.module.css
|
||||
| └── index.tsx
|
||||
```
|
||||
|
||||
组件通常会在路由组件中被引入。
|
||||
|
||||
## 其它
|
||||
|
||||
- build 目录
|
||||
- 运行 `npm build` 后的构建产物目录,可修改构建配置修改输出路径。
|
||||
- .ice 目录
|
||||
- 运行 ICE 项目时默认生成的临时目录,该目录不需要进行 `git` 提交。
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
title: 定制 HTML
|
||||
order: 12
|
||||
---
|
||||
|
||||
ICE 使用 JSX 维护页面的 HTML 模板结构,其入口位于 `src/document.tsx`。
|
||||
|
||||
## 初始模板
|
||||
|
||||
`Document` 的初始模板如下:
|
||||
|
||||
```jsx
|
||||
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;
|
||||
```
|
||||
|
||||
默认引入了以下组件:
|
||||
|
||||
- `Meta`:页面的元信息
|
||||
- `Title` 页面的标题信息
|
||||
- `Links` 页面面依赖的 CSS 资源及其他 `link` 标签
|
||||
- `Scripts` 页面依赖的 JS 资源
|
||||
- `Main` 页面渲染的容器节点
|
||||
|
||||
这些组件,配合各路由组件的 `getConfig()` 配置,可以实现不同页面 HTML 模板的差异化渲染。
|
||||
|
||||
## 内容定制
|
||||
|
||||
像开发其他 JSX 组件一样,可以在 `Document` 组件内插入自定义的其他 HTML 内容。例如:
|
||||
|
||||
```jsx
|
||||
<body>
|
||||
<div>hello</div>
|
||||
<Main />
|
||||
<Scripts />
|
||||
<script src="xxx.js" />
|
||||
</body>
|
||||
```
|
||||
|
||||
注意: 在 `Scripts` 前插入外部资源,会阻塞主 Bundle 的解析执行,影响页面性能。
|
||||
|
||||
另外,在 JSX 中添加内联的 `style` 或 `script` 需要结合 `dangerouslySetInnerHTML` 的方式,示例如下:
|
||||
|
||||
```jsx
|
||||
<style dangerouslySetInnerHTML={{__html: `
|
||||
p {
|
||||
color: red;
|
||||
font-size: 20px;
|
||||
}
|
||||
`}}>
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" dangerouslySetInnerHTML={{__html: `
|
||||
console.log("Hello World!")
|
||||
`}}>
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
---
|
||||
title: 环境变量
|
||||
order: 13
|
||||
---
|
||||
|
||||
ICE 内置通过环境变量实现给构建或运行时传递参数的功能。
|
||||
|
||||
- 使用 `.env` 文件来配置环境变量
|
||||
- 配置 `ICE_` 开头的环境变量则会同时暴露到运行时环境中
|
||||
|
||||
## 如何配置环境变量
|
||||
|
||||
### 命令行环境变量
|
||||
|
||||
例如需要修改 ICE 本地开发服务的端口号,可以在命令行中使用环境变量:
|
||||
|
||||
```shell
|
||||
$ cross-env PORT=9999 npm start
|
||||
```
|
||||
|
||||
> 示例中使用了 cross-env 来兼容不容操作系统的环境变量配置方式。
|
||||
|
||||
### 使用 `.env` 文件
|
||||
|
||||
ICE 内置了加载 `.env` 文件的支持,在该文件中设置的环境变量会被自动加载到 `process.env` 上。
|
||||
|
||||
`.env` 文件的示例:
|
||||
|
||||
```shell
|
||||
DEV_PORT=3000
|
||||
FOO=bar
|
||||
```
|
||||
|
||||
如果有部分环境变量的配置在本地有差异,你可以配置在 `.env.local` 文件中去覆盖 `.env` 中的配置。如在之前的 `.env` 的基础上, 你想本地开发覆盖之前 3000 端口, 而使用 9999 端口,示例如下:
|
||||
|
||||
```shell
|
||||
# The .env.local should not be committed.
|
||||
DEV_PORT=9999
|
||||
```
|
||||
|
||||
此外你也可以在 `.env.${mode}` 和 `.env.${mode}.local` 文件中指定不同模式下的环境变量。`${mode}` 的取值是 `development` 或 `production`。
|
||||
|
||||
需要注意的是:
|
||||
1. 这几个文件的优先级由低至高分别是
|
||||
- `.env`
|
||||
- `.env.local`
|
||||
- `.env.${mode}`
|
||||
- `.env.${mode}.local`
|
||||
2. 一般不建议将 `.local` 结尾的文件加入版本管理 (如 Git) 中。
|
||||
|
||||
## 使用环境变量
|
||||
|
||||
在 ICE 中,环境变量的使用场景分构建时与运行时两种类型。
|
||||
|
||||
特别注意:环境变量在使用时的类型都是 `string`,特别是设置为 `true` 或 `false` 时需要注意判断为字符串类型:
|
||||
|
||||
```js
|
||||
// ICE_DISABLE_FOO=false
|
||||
if (process.env.ICE_DISABLE_FOO === 'false') {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 构建时
|
||||
|
||||
默认情况下,所有设置的环境变量都会被注入到构建环境,你可以在 `ice.config.mts` 文件或其它构建插件中通过 `process.env` 变量访问。
|
||||
|
||||
```js
|
||||
const port = process.env.PORT;
|
||||
// ...
|
||||
```
|
||||
|
||||
### 运行时
|
||||
|
||||
默认情况下环境变量是不能在运行时访问的,如若需要在浏览器环境中访问,可以在设置环境变量时增加前缀:`ICE_`,如:
|
||||
|
||||
```shell
|
||||
# File .env
|
||||
ICE_APP_ID=123456
|
||||
```
|
||||
|
||||
在运行时代码中访问:
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
|
||||
export default function AppID() {
|
||||
return <h1>AppId is {process.env.ICE_APP_ID}.</h1>
|
||||
}
|
||||
```
|
||||
|
||||
## 内置的环境变量
|
||||
|
||||
ICE 会内置一些环境变量方便使用,通常由 `ICE_CORE_` 开头,如下:
|
||||
|
||||
### ICE_CORE_MODE
|
||||
|
||||
用于 ICE 的运行模式,可能是 `development` 或 `production`。
|
||||
|
||||
### ICE_CORE_ROUTER
|
||||
|
||||
用于标识框架是否启用路由,可能是 `true` 或 `false`。
|
||||
|
||||
### ICE_CORE_ERROR_BOUNDARY
|
||||
|
||||
用于标识框架是否启用错误边界,可能是 `true` 或 `false`。
|
||||
|
||||
### ICE_CORE_INITIAL_DATA
|
||||
|
||||
用于标识框架是否启用初始数据,可能是 `true` 或 `false`。
|
||||
|
||||
### ICE_CORE_DEV_PORT
|
||||
|
||||
用于标识 ICE 的开发服务器端口号。
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
title: 数据模拟 Mock
|
||||
order: 7
|
||||
---
|
||||
在前后端分离的开发中,Mock 数据是前端开发中很重要的一个环节,前端可以不必强依赖后端接口,只需要约定好对应的数据接口,前端可以通过 Mock 模拟数据先行开发,在后端接口开发完成后,只需要切换对应的接口地址即可,可以保证项目的同步开发。
|
||||
|
||||
ICE 提供了开箱即用的 Mock 方案,支持 CRUD 等操作,在启动本地调试时会自动启用 Mock 服务。
|
||||
|
||||
## 目录约定
|
||||
|
||||
只需要在项目目录下新建 `/mock` 目录,并增加 `js` 或 `ts` 文件作为 `mock` 服务文件。比如有以下的目录结构:
|
||||
|
||||
```markdown
|
||||
├── mock
|
||||
| ├── index.ts
|
||||
| └── user.ts
|
||||
├── src
|
||||
└── package.json
|
||||
```
|
||||
|
||||
`mock` 目录下的 `index.ts` 和 `user.ts` 会被识别为 Mock 服务文件。
|
||||
|
||||
## 编写 Mock 接口
|
||||
|
||||
在 mock 服务文件中写入以下代码:
|
||||
|
||||
```ts title="./mock/user.ts"
|
||||
export default {
|
||||
'GET /api/users': [
|
||||
{ name: 'foo', id: 0 },
|
||||
{ name: 'bar', id: 1 },
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
启动调试服务后,假设启动的端口是 `3333`,直接在浏览器里访问 <http://127.0.0.1:3333/api/users> 即可看到接口返回数据。
|
||||
|
||||
### 请求方法
|
||||
|
||||
默认支持 `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS` 请求方法。示例代码如下:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
// 当 HTTP 请求方法是 GET,可以省略请求方法
|
||||
'/api/users': [{ name: 'foo', id: 1 }, { name: 'bar', id: 2 }],
|
||||
// 等同于上面的写法
|
||||
'GET /api/users': [{ name: 'foo', id: 1 }, { name: 'bar', id: 2 }],
|
||||
|
||||
'POST /api/user': { users: [1, 2] },
|
||||
|
||||
'DELETE /api/users/1': { name: 'foo' },
|
||||
}
|
||||
```
|
||||
|
||||
### 返回值
|
||||
|
||||
返回值支持 `String`、`Array`、`Object` 类型。比如:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
// 返回值是 String 类型
|
||||
'GET /api/name': 'foo',
|
||||
// 返回值 Array 类型
|
||||
'POST /api/users': [
|
||||
{ name: 'foo', id: 0 },
|
||||
{ name: 'bar', id: 1 },
|
||||
],
|
||||
// 返回值是 Object 类型
|
||||
'DELETE /api/users/1': { name: 'bar', id: 1 },
|
||||
}
|
||||
```
|
||||
|
||||
除此以外,还可以使用函数的形式来计算返回值,这在需要动态返回接口数据时很有用,如:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
'POST /api/users/:id': (req, res) => {
|
||||
const { id } = req.params;
|
||||
res.send({ id: id });
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 关闭 Mock
|
||||
|
||||
当后端接口开发完成以后。此时可以通过以下命令关闭 Mock 服务:
|
||||
|
||||
```bash
|
||||
# 关闭 Mock 服务
|
||||
$ npm run start -- --no-mock
|
||||
```
|
||||
|
||||
这样我们可以请求到后端返回的数据了。
|
||||
|
||||
## 使用 Mock.js
|
||||
|
||||
[Mock.js](https://github.com/nuysoft/Mock) 是一个随机生成 mock 数据的工具库,可以帮助我们快速生成随机的模拟数据。
|
||||
|
||||
```ts
|
||||
import mockjs from 'mockjs';
|
||||
|
||||
export default {
|
||||
'GET /api/list': (req, res) => {
|
||||
const list = Mock.mock({
|
||||
'list|1-10': [
|
||||
{
|
||||
'id|+1': 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
res.send({
|
||||
status: 'SUCCESS',
|
||||
data: {
|
||||
list,
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
完整的语法请参考 [Mock.js 文档](http://mockjs.com/examples.html)。
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
title: 页面
|
||||
order: 4.1
|
||||
---
|
||||
|
||||
每一张页面,都可以由 `路由组件` 和 `零或多个布局组件` 组装而成。路由组件和布局组件的开发规范基本一致,可以包含以下内容:
|
||||
|
||||
- 默认导出是组件的具体实现,必选。
|
||||
- 导出 `getData()` 方法,约定页面的数据请求,可选。
|
||||
- 导出 `getConfig()` 方法,约定页面的 `Title`、`Meta` 等信息,可选。
|
||||
|
||||
## 组件
|
||||
|
||||
对应路由组件或布局组件在页面中需要渲染的内容。
|
||||
|
||||
```tsx title="src/pages/index.tsx"
|
||||
import { useData } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## getData()
|
||||
|
||||
获取页面初始数据的方法,详见[数据请求](./request.md)。
|
||||
|
||||
## getConfig()
|
||||
|
||||
获取页面运行时配置的方法,页面主体内容之外的,其他需要通用 HTML 模板上差异化显示的内容,可以通过导出 `getConfig` 方法来声明。
|
||||
|
||||
支持的页面级配置包含:
|
||||
|
||||
#### title
|
||||
|
||||
标题会显示在文档上,可以通过 `title` 属性来设置。 示例:
|
||||
|
||||
```tsx
|
||||
export function getConfig() {
|
||||
return {
|
||||
title: 'Home',
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### metas
|
||||
|
||||
Meta 信息会显示在文档上,可以通过 `meta` 属性来设置。 示例:
|
||||
|
||||
```tsx
|
||||
export function getConfig() {
|
||||
return {
|
||||
metas: [
|
||||
{ charset: 'utf-8' },
|
||||
{
|
||||
title: 'Something cool',
|
||||
description: 'This becomes the nice preview on search results.',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### links
|
||||
|
||||
页面级需要额外插入的 `<link />` 标签,会被插入 `<head>` 标签内,先于页面自身的 Bundle 加载,是阻塞型的。
|
||||
|
||||
> 框架提供了这个能力,但不推荐使用,除非确有需要前置加载。
|
||||
|
||||
```tsx
|
||||
export function getConfig() {
|
||||
return {
|
||||
links: [
|
||||
{
|
||||
rel: 'icon',
|
||||
href: '/favicon.png',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
rel: 'stylesheet',
|
||||
href: 'https://example.com/some/styles.css',
|
||||
},
|
||||
]
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
推荐,在页面组件内延迟加载,以达到更好的性能体验。
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<link rel="stylesheet" href="https://example.com/some/styles.css" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### scripts
|
||||
|
||||
页面级需要前置加载的脚本资源,会被插入在主 Bundle 前,但是会阻塞渲染。通常用于加载全局 JS SDK 或 Polyfill。
|
||||
|
||||
```tsx
|
||||
export function getConfig() {
|
||||
return {
|
||||
scripts: [
|
||||
{
|
||||
src: 'https://example.com/some/index.js',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
推荐在页面组件内按需异步加载,以达到更好的性能体验。
|
||||
@TODO 补充推荐的方式示例
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
title: 页面数据请求
|
||||
order: 6
|
||||
---
|
||||
|
||||
在 ICE 中,推荐为页面组件定义 `getData()` 方法,来发起页面的数据请求。在 `getData()` 中定义的数据请求,会和页面的资源加载并行发起,以达到更好的性能体验。
|
||||
|
||||
示例:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import { useData } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export async function getData() {
|
||||
const data = await fetch('https://example.com/api/xxx');
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
传统的做法,一般是在 useEffect 中发起数据请求,数据请求依赖于页面的 Bundle 加载、解析、执行,整个过程是串行的。
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export default function Home() {
|
||||
const [data, setData] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
const data = await fetch('https://example.com/api/xxx');
|
||||
|
||||
setData(data);
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
相比之下,`getData()` 变数据请求从串行到并行,天然带来了更好的性能体验,是框架推荐的数据方法。
|
||||
|
||||
## 入参
|
||||
|
||||
`getData()` 的入参包含:
|
||||
|
||||
- `pathname`: `string`, 当前页面的路径名。
|
||||
- `query`: `object`, 当前页面的 `query` 信息,会被提前解析。
|
||||
|
||||
```tsx
|
||||
export async function getData(params) {
|
||||
console.log(params.pathname);
|
||||
console.log(params.query);
|
||||
|
||||
const data = await fetch('https://example.com/api/xxx');
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
## useData()
|
||||
|
||||
在路由组件里使用 `getData()` 返回的数据,需配合 `useData()` 使用。 示例:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import { useData } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>{JSON.stringify(data)}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
title: 路由
|
||||
order: 4
|
||||
---
|
||||
|
||||
一个应用,通常包含多张页面,每张页面对应不同的地址。在 ICE 中,采用了约定式路由,会根据项目的目录结构自动生成应用的路由信息。
|
||||
|
||||
## 路由组件
|
||||
|
||||
路由组件,是每一个页面的入口文件,通过 `export default` 导出其具体实现,例如:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>Hello ICE</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
更多能力,详见[页面](./page.md)。
|
||||
|
||||
## 路由规则
|
||||
|
||||
在 `src/pages` 目录下创建的每一个 `.(js|jsx|tsx)` 文件, 都对应着一个具体的路由。如下面的目录结构:
|
||||
|
||||
```
|
||||
/src
|
||||
└── pages
|
||||
└── repo
|
||||
| ├── index.tsx
|
||||
| └── preview.tsx
|
||||
├── about.tsx
|
||||
└── index.tsx
|
||||
```
|
||||
|
||||
对应的路由匹配规则为:
|
||||
|
||||
| URL | 路由组件 |
|
||||
| --------------- |:--------------------------:|
|
||||
| / | pages/index.tsx |
|
||||
| /about | pages/about.tsx |
|
||||
| /repo | pages/repo/index.tsx |
|
||||
| /repo/preview | pages/repo/preview.tsx |
|
||||
|
||||
## 路由跳转
|
||||
|
||||
ICE 通过 `Link` 组件,来提供路由间的跳转能力。基于 `Link` 组件,可以只加载下一个页面相比于当前页面差异化的 Bundle 进行渲染,以达到更好的性能体验。
|
||||
|
||||
```jsx
|
||||
// src/pages/index.tsx
|
||||
import { Link } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<Link to="/about">about ice</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 布局组件
|
||||
|
||||
在 `pages` 目录下,还可以创建一类特殊的组件,来维护全局或一组页面共用的布局, 其文件名约定为 `layout.(js|jsx|tsx)`。
|
||||
|
||||
布局组件和路由组件一样,也通过 `export default` 导出其具体实现。
|
||||
|
||||
```jsx
|
||||
import { Outlet } from 'ice';
|
||||
|
||||
export default function Layout() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Root Layout</h1>
|
||||
<h2>Hello ICE</h2>
|
||||
<Outlet />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
其中, `<Outlet />` 组件对应需要被布局组件嵌套的子组件。
|
||||
|
||||
布局组件:
|
||||
- 如果位于 `pages` 目录的最顶层,则它将作为全局布局,嵌套在所有路由组件外。
|
||||
- 如果位于某个子文件夹,则它将作为页面级布局,嵌套在这个目录下的其他路由组件外。
|
||||
|
||||
如果同时存在 **全局布局组件** 和 **页面级布局组件**,则全局布局组件会嵌套于页面级布局组件之外。
|
||||
|
||||
例如,下面的目录结构:
|
||||
|
||||
```diff
|
||||
/src
|
||||
├── layout.tsx
|
||||
└── pages
|
||||
└── repo
|
||||
+ | ├── layout.tsx 页面级布局组件
|
||||
| ├── index.tsx
|
||||
| └── preview.tsx
|
||||
├── about.tsx
|
||||
+ ├── layout.tsx 全局布局组件
|
||||
└── index.tsx
|
||||
```
|
||||
|
||||
每个路由,对应的 Layout 匹配规则为:
|
||||
|
||||
| URL | 路由组件 | 布局组件 |
|
||||
| --------------- |:--------------------------:|-------------------------------------------:|
|
||||
| / | pages/index.tsx | src/layout.tsx |
|
||||
| /about | pages/about.tsx | src/layout.tsx |
|
||||
| /repo | pages/repo/index.tsx | src/layout.tsx + src/pages/repo/layout.tsx |
|
||||
| /repo/preview | pages/repo/preview.tsx | src/layout.tsx + src/pages/repo/layout.tsx |
|
||||
|
||||
## 动态路由
|
||||
|
||||
路由中包含了动态参数的路由,被称做动态路由。如果文件名或者目录名是以 `$` 开头,则判定这个路由为动态路由。
|
||||
|
||||
> 注意:动态路由仅在 SSR 下生效。
|
||||
|
||||
例如,下面的目录结构:
|
||||
|
||||
```diff
|
||||
/src
|
||||
├── layout.tsx
|
||||
└── pages
|
||||
└── repo
|
||||
+ ├── $id
|
||||
+ | ├── author
|
||||
+ | | └── $name.tsx
|
||||
+ | └── index.tsx
|
||||
├── index.tsx
|
||||
└── preview.tsx
|
||||
```
|
||||
|
||||
对应的路由匹配规则为:
|
||||
|
||||
| URL | 路由组件 |
|
||||
|----------------------|:--------------------------:|
|
||||
| /repo | pages/repo/index.tsx |
|
||||
| /repo/preview | pages/repo/preview.tsx |
|
||||
| /repo/ice | src/pages/repo/$id/index.tsx |
|
||||
| /repo/ice/author/foo | src/pages/repo/$id/author/$name.tsx |
|
||||
|
||||
在动态路由组件中可以通过 `useParams()` 方法拿到当前路由的参数:
|
||||
|
||||
```tsx
|
||||
// src/pages/repo/$id/author/$name.tsx
|
||||
import { useParams } from 'ice';
|
||||
|
||||
export default function() {
|
||||
const { id, name } = useParams();
|
||||
console.log(id); // 'ice'
|
||||
console.log(name); // 'foo'
|
||||
return <div />;
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
title: 构建时渲染 SSG
|
||||
order: 10
|
||||
---
|
||||
|
||||
构建时渲染,简称 SSG (Static Site Generation),是指在构建时提前生成内容 HTML 的渲染模式。
|
||||
|
||||
ICE 默认开启 SSG 能力。SSG 不仅适用于静态站点,也适用于为普通 CSR 应用提前生成静态内容。
|
||||
|
||||
假设有如下路由组件,其内容为:
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import { useData } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>stars: {data?.stars}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
其中,第一个 `div` 中的内容是不依赖于数据。在传统的 CSR 应用中,`<Home />` 组件内容,无论是否依赖数据,都需要等待 JS 加载、解析后渲染。
|
||||
|
||||
利用 SSG,则可以在构建时,就将不依赖于动态数据的部分提前生成到 HTML 中。示例:
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
...
|
||||
</head>
|
||||
<body>
|
||||
<div id="ice-container">
|
||||
<div>Hello ICE</div>
|
||||
<div>stars: </div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### 注意事项
|
||||
|
||||
- 需要在消费 data 时,做好空值判断,避免 data 为 `undefined` 或 `null` 时,产生渲染异常,无法正常构建。
|
||||
- 兼容 Node.js 端。SSG 会在构建时进行,因此代码会运行在 Node.js 侧,因此在消费一些浏览器特有的环境变量时,要做好环境判断。
|
||||
|
||||
### 定制 SSG 的数据源
|
||||
|
||||
如果希望在 SSG 时使用兜底数据,可以通过为路由组件定义 `getStaticData()` 方法。这样在 SSG 时,组件 `useData()` 获取的数据,为 `getStaticData()` 的返回值。
|
||||
|
||||
```tsx
|
||||
// src/pages/index.tsx
|
||||
import { useData } from 'ice';
|
||||
|
||||
export default function Home() {
|
||||
const data = useData();
|
||||
return (
|
||||
<>
|
||||
<div>Hello ICE</div>
|
||||
<div>stars: {data?.stars}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// 浏览器侧的常规数据请求
|
||||
export function getData() {
|
||||
return {
|
||||
stars: 1000,
|
||||
};
|
||||
}
|
||||
|
||||
// 返回用于 SSG 的数据
|
||||
export function getStaticData() {
|
||||
// 浏览器侧的常规数据请求
|
||||
return {
|
||||
stars: 0,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
构建 Client 端的 Bundle 时,会移除 `getStaticData()` 及其相关依赖。
|
||||
|
||||
## 关闭 SSG
|
||||
|
||||
在 `ice.config.mts` 下,按如下配置修改
|
||||
|
||||
```tsx
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
ssg: false,
|
||||
});
|
||||
```
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
title: 服务端渲染 SSR
|
||||
order: 11
|
||||
---
|
||||
|
||||
服务器渲染,简称 SSR (Server Side Rendering),是一种在服务端运行 Node.js 程序动态生成 HTML 的渲染方式。
|
||||
|
||||
SSR 相比传统在浏览器端渲染的模式(CSR),受设备性能和网络情况的影响更小,可以达到更好的性能体验和 SEO 能力。
|
||||
|
||||
## 开启 SSR
|
||||
|
||||
与 SSG 不同的是,ICE 中 SSR 不是默认启用的。
|
||||
|
||||
在 `ice.config.mts` 中,增加如下配置:
|
||||
|
||||
```tsx
|
||||
import { defineConfig } from '@ice/app';
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
ssr: true,
|
||||
});
|
||||
```
|
||||
|
||||
## 数据请求
|
||||
|
||||
开启 SSR 后,路由组件中导出的 `getData()` 方法将会在 Server 端被执行,如果 SSR 渲染成功,在 Client 端将不会再次调用 `getData()`,而会复用 SSR 的结果。当页面在浏览器侧通过路由跳转,或页面降级时,才会在 Client 端调用 `getData()`。
|
||||
|
||||
因此,一般情况下 `getData()` 内的数据请求需要保持同构,在 Server 端和 Client 端都能执行。
|
||||
|
||||
如果确实需要为 Server 端指定不一样的数据请求方式,可以通过定义 `getServerData()` 来实现。当路由组件声明了 `getServerData()`,会在 SSR 优先使用这个方法。
|
||||
|
||||
示例:
|
||||
|
||||
```tsx
|
||||
// Client 端专用的数据请求
|
||||
export async function getData() {
|
||||
const data = await fetch('https://example.com/api/xxx');
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Server 端专用的数据请求
|
||||
export async function getStaticData() {
|
||||
const data = await sendRequestInServer();
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
构建 Client 端的 Bundle 时,会移除 `getServerData()` 及其相关依赖。
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
---
|
||||
title: 样式
|
||||
order: 5
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
ICE 推荐使用原生 CSS + PostCSS 的方案编写样式,不建议使用 `less/sass` 之类的预编译方案,CSS 写法目前扩展支持了 `@import` 以及嵌套写法。
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="css" label="index.css">
|
||||
|
||||
```css
|
||||
@import './theme.css';
|
||||
|
||||
.home {
|
||||
color: red;
|
||||
|
||||
h2 {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="tsx" label="index.tsx">
|
||||
|
||||
```tsx
|
||||
import './index.css';
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<div className="home">
|
||||
<h2>CSS Modules</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
> ICE 同时支持 `less/scss` 预编译器,只要保证文件后缀匹配即可。
|
||||
|
||||
## 全局样式
|
||||
|
||||
对于整个项目的全局样式,统一定义在 `src/global.css` 文件中,框架会默认引入该文件:
|
||||
|
||||
```css
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
```
|
||||
|
||||
## 局部样式
|
||||
|
||||
对于页面级和组件级的样式,我们推荐使用 CSS Modules 的方案,这能很好的解决样式开发中的两个痛点问题:
|
||||
|
||||
1. 全局污染:CSS 使用全局选择器机制来设置样式,优点是方便重写样式。缺点是所有的样式都是全局生效,样式可能被错误覆盖,因此产生了非常丑陋的 !important,甚至 inline !important 等问题。
|
||||
2. 命名混乱:由于全局污染的问题,多人协同开发时为了避免样式冲突,选择器越来越复杂,容易形成不同的命名风格,很难统一,样式变多后,命名将更加混乱。
|
||||
|
||||
具体规范规则如下:
|
||||
|
||||
- 文件名:约定文件名格式如 `xxx.module.css`
|
||||
- 模块化:一个页面或者一个组件对应一个样式文件
|
||||
|
||||
如有以下的目录结构和代码:
|
||||
|
||||
```
|
||||
├── src
|
||||
| ├── pages
|
||||
| | ├── index.module.css
|
||||
| | └── index.tsx
|
||||
```
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="css" label="index.module.css">
|
||||
|
||||
```css
|
||||
.container {
|
||||
background: #fff;
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="tsx" label="index.tsx">
|
||||
|
||||
```tsx
|
||||
import styles from './index.module.css';
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<h2>CSS Modules</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
使用该方案之后,上文中的 `className` 都会被编译为唯一性的名字,避免因为重名 `class` 而产生样式冲突。如果在浏览器里查看这个示例的 DOM 结构,你会发现实际渲染出来是这样的:
|
||||
|
||||
```html
|
||||
<div class="container--WZ5p3kdM"><h2>CSS Modules</h2></div>
|
||||
```
|
||||
|
||||
同时 CSS Modules 支持 less/scss 预编译器:
|
||||
|
||||
```tsx
|
||||
import lessStyles from './index.module.less';
|
||||
import scssStyles from './index.module.scss';
|
||||
|
||||
export default function () {
|
||||
return <div className={lessStyles.title}>
|
||||
Hello World
|
||||
<p className={scssStyles.blue}>I am blue</p>
|
||||
</div>;
|
||||
}
|
||||
```
|
||||
|
||||
更多 CSS Modules 文档请参考:
|
||||
|
||||
- [css-modules 官方文档](https://github.com/css-modules/css-modules)
|
||||
- [CSS Modules 详解及 React 中实践](https://zhuanlan.zhihu.com/p/20495964)
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 如何覆盖全局基础组件(next/antd)样式
|
||||
|
||||
推荐通过 `src/global.css` 覆盖全局样式:
|
||||
|
||||
```css title="src/global.css"
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
/* 覆盖 next 组件的样式 */
|
||||
.next-btn {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
该方式会覆盖应用中所有 `Button` 组件的 `font-size` 属性。
|
||||
|
||||
### 如何覆盖局部基础组件样式
|
||||
|
||||
如果只是想覆盖某个页面/模块里的组件样式,则推荐采用局部覆盖的方式:
|
||||
|
||||
```css title="./pages/Home/index.module.css"
|
||||
.home {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.home :global {
|
||||
/* 仅修改 .home 下的 button 样式 */
|
||||
.next-btn {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果组件本身支持 `style` 属性,也可通过 `style` 属性修改:
|
||||
|
||||
```tsx title="./pages/Home/index.tsx"
|
||||
export default function () {
|
||||
return (
|
||||
<>
|
||||
<Button style={{ fontSize: '16px' }}>OK</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 如何获得 CSS 嵌套的类型提示
|
||||
|
||||
可以在 VSCode 编辑器中需要安装 [PostCSS Language Support 插件](https://marketplace.visualstudio.com/items?itemName=csstools.postcss) 以支持嵌套写法。
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 插件开发
|
||||
order: 6
|
||||
---
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: 实战教程
|
||||
order: 3
|
||||
hide: true
|
||||
---
|
||||
|
||||
@TODO.
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
title: 快速开始
|
||||
order: 2
|
||||
---
|
||||
|
||||
## 创建应用
|
||||
|
||||
在终端执行以下命令:
|
||||
|
||||
```bash
|
||||
$ npx create-ice ice-app --template ice-scaffold-simple
|
||||
```
|
||||
|
||||
看到如下信息说明项目创建成功:
|
||||
|
||||
```bash
|
||||
✔ download npm tarball successfully.
|
||||
info clean package.json...
|
||||
Initialize project successfully.
|
||||
Starts the development server.
|
||||
|
||||
cd ice-app
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## 本地调试
|
||||
|
||||
首先需要安装项目依赖:
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
$ cd ice-app
|
||||
# 安装依赖
|
||||
$ npm install
|
||||
```
|
||||
|
||||
安装依赖完成以后,执行以下命令以启动调试:
|
||||
|
||||
```bash
|
||||
# 启动调试
|
||||
$ npm start
|
||||
```
|
||||
|
||||
此时会自动打开浏览器窗口并访问 <http://localhost:3333>,这时会看到默认页面。
|
||||
|
||||

|
||||
|
||||
## 部署发布
|
||||
|
||||
执行以下命令以构建生产环境产物:
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
$ npm build
|
||||
```
|
||||
|
||||
产物默认生成到 `build` 目录下:
|
||||
|
||||
```markdown
|
||||
./build
|
||||
├── css
|
||||
| └── index.css
|
||||
├── index.html
|
||||
└── js
|
||||
├── framework.js
|
||||
├── index.js
|
||||
└── main.js
|
||||
```
|
||||
|
||||
这时你可以把 `build` 目录部署到服务器上。
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
title: 从 Rax 升级
|
||||
order: 20
|
||||
---
|
||||
|
||||
本文档面向的是使用 Rax App 的开发者,提供升级到 ICE 的方式。React 的社区生态显著优于 Rax,切换到 React 之后可以享受到更多的 React 生态,部分复杂场景(富文本、脑图等)可以大幅度降低成本。
|
||||
|
||||
## 如何升级
|
||||
|
||||
ICE 提供了 [rax-compat](https://github.com/ice-lab/ice-next/tree/master/packages/rax-compat) 以支持 [Rax](https://github.com/alibaba/rax) 到 React 运行时的切换。
|
||||
|
||||
`rax-compat` 通过对 React 的能力的封装,在内部抹平了 Rax 与 React 使用上的一些差异,同时导出了与 Rax 一致的 API 等能力,通过 alias 来将源码中的 rax 用 rax-compat 来替换,即可桥接上 React 的运行时能力。
|
||||
|
||||
## 安装与使用
|
||||
|
||||
用户可以直接通过引入插件 [@ice/plugin-rax-compat](https://www.npmjs.com/package/@ice/plugin-rax-compat) 来完成在 ICE 中运行 Rax 应用。
|
||||
|
||||
```bash
|
||||
$ npm i @ice/plugin-rax-compat --save-dev
|
||||
```
|
||||
|
||||
```js
|
||||
import compatRax from '@ice/plugin-rax-compat';
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
plugins: [
|
||||
// ...
|
||||
compatRax({
|
||||
inlineStyle: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## `rax-compat` 兼容性
|
||||
|
||||
### Rax 核心 API
|
||||
|
||||
@列一下 Rax 核心提供的 API 列表, 也包括之前 rax 1.0 移动到独立包的 API.
|
||||
|
||||
### Appear & Disappear
|
||||
|
||||
@ Rax 这边是直接支持了这个事件。
|
||||
@ 另外需要一篇文档来提供 ICE Appear 事件支持 (用组件支持).
|
||||
|
||||
### 样式的处理
|
||||
|
||||
@ inlineStyle 和 CSS Modules 特殊逻辑的解释。rpx 单位的解释。
|
||||
|
||||
### 差异补充
|
||||
|
||||
@比如 DOM attributes 的处理。
|
||||
|
||||
rax-picture + rax-compat
|
||||
|
||||
@ice/picture + `<Appear />`
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: 开发指南
|
||||
order: 1
|
||||
---
|
||||
|
||||
start
|
||||
|
|
@ -3,9 +3,9 @@ const navbar = require('./config/navbar');
|
|||
const footer = require('./config/footer');
|
||||
|
||||
const config = {
|
||||
title: '飞冰',
|
||||
tagline: '基于 React 的应用研发框架',
|
||||
url: 'https://beta.ice.work',
|
||||
title: '飞冰 ICE ',
|
||||
tagline: ' 基于 React 的应用研发框架',
|
||||
url: 'https://v3.ice.work',
|
||||
baseUrl: '/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'throw',
|
||||
|
|
@ -13,18 +13,27 @@ const config = {
|
|||
organizationName: 'alibaba',
|
||||
projectName: 'ice',
|
||||
themeConfig: {
|
||||
// announcementBar: {
|
||||
// id: 'announcementBar-2',
|
||||
// content: 'icejs 2.0 版本已发布,支持 Webpack 5 和 Vite 两种构建模式,点击 <a href="/docs/guide/upgrade">快速升级</a>',
|
||||
// isCloseable: true,
|
||||
// },
|
||||
announcementBar: {
|
||||
id: 'announcementBar-2',
|
||||
content: 'ICE 3 Beta,不仅是 PC,更适配移动端能力,<a href="/docs/guide/upgrade">快速升级</a>',
|
||||
isCloseable: true,
|
||||
},
|
||||
navbar,
|
||||
footer,
|
||||
prism: {
|
||||
theme: require('prism-react-renderer/themes/oceanicNext'),
|
||||
},
|
||||
// algolia: {
|
||||
// apiKey: '01f284e7e1c13eac3dc14beb6d8b153d',
|
||||
// indexName: 'ice',
|
||||
// },
|
||||
},
|
||||
i18n: {
|
||||
defaultLocale: 'zh-CN',
|
||||
locales: [
|
||||
'zh-CN',
|
||||
],
|
||||
},
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
|
|
@ -50,16 +59,16 @@ const config = {
|
|||
],
|
||||
};
|
||||
|
||||
if (process.env.USE_LOCAL_SEARCH) {
|
||||
// 内部站点无法使用 algolia
|
||||
delete config.themeConfig.algolia;
|
||||
config.plugins.push([
|
||||
require.resolve('@easyops-cn/docusaurus-search-local'),
|
||||
{
|
||||
hashed: true,
|
||||
language: ['en', 'zh'],
|
||||
},
|
||||
]);
|
||||
}
|
||||
// if (process.env.USE_LOCAL_SEARCH) {
|
||||
// 内部站点无法使用 algolia
|
||||
delete config.themeConfig.algolia;
|
||||
config.plugins.push([
|
||||
require.resolve('@easyops-cn/docusaurus-search-local'),
|
||||
{
|
||||
hashed: true,
|
||||
language: ['zh', 'en'],
|
||||
},
|
||||
]);
|
||||
// }
|
||||
|
||||
module.exports = config;
|
||||
module.exports = config;
|
||||
|
|
|
|||
|
|
@ -14,18 +14,23 @@
|
|||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.0-beta.15",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.15",
|
||||
"@docusaurus/theme-search-algolia": "^2.0.0-beta.15",
|
||||
"@easyops-cn/docusaurus-search-local": "^0.19.1",
|
||||
"@docusaurus/core": "^2.0.0-beta.21",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.21",
|
||||
"@docusaurus/theme-search-algolia": "^2.0.0-beta.21",
|
||||
"@easyops-cn/docusaurus-search-local": "^0.28.0",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"clsx": "^1.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^17.0.1",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"glob": "^7.1.7",
|
||||
"gray-matter": "^4.0.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
|
|
@ -37,12 +42,5 @@
|
|||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"glob": "^7.1.7",
|
||||
"gray-matter": "^4.0.3",
|
||||
"nodejieba": "^2.5.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,34 +5,34 @@ module.exports = function (context, options) {
|
|||
const { createData, addRoute } = actions;
|
||||
|
||||
const routes = [
|
||||
{
|
||||
from: '/docs/guide/advance/fusion',
|
||||
to: '/docs/plugin/list/fusion',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/advance/antd',
|
||||
to: '/docs/plugin/list/antd',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/develop/plugin-dev',
|
||||
to: '/docs/plugin/develop/start',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/develop/plugin-build',
|
||||
to: '/docs/plugin/develop/build',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/develop/plugin-runtime',
|
||||
to: '/docs/plugin/develop/runtime',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/develop/plugin-list',
|
||||
to: '/docs/plugin/list/moment-locales',
|
||||
},
|
||||
{
|
||||
from: '/docs/guide/basic/api',
|
||||
to: '/docs/config/about',
|
||||
},
|
||||
// {
|
||||
// from: '/docs/guide/advance/fusion',
|
||||
// to: '/docs/plugin/list/fusion',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/advance/antd',
|
||||
// to: '/docs/plugin/list/antd',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/develop/plugin-dev',
|
||||
// to: '/docs/plugin/develop/start',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/develop/plugin-build',
|
||||
// to: '/docs/plugin/develop/build',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/develop/plugin-runtime',
|
||||
// to: '/docs/plugin/develop/runtime',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/develop/plugin-list',
|
||||
// to: '/docs/plugin/list/moment-locales',
|
||||
// },
|
||||
// {
|
||||
// from: '/docs/guide/basic/api',
|
||||
// to: '/docs/config/about',
|
||||
// },
|
||||
];
|
||||
|
||||
const redirectConfigPath = await createData(
|
||||
|
|
|
|||
|
|
@ -12,15 +12,18 @@ module.exports = function getDocsFromDir(dir) {
|
|||
return (matter(fs.readFileSync(filepath, 'utf-8')).data || {}).order || 100;
|
||||
}
|
||||
|
||||
function isDocHide(filepath) {
|
||||
return (matter(fs.readFileSync(filepath, 'utf-8')).data || {}).hide || false;
|
||||
}
|
||||
|
||||
const docs = glob.sync('*.md', {
|
||||
cwd: docsDir,
|
||||
// ignore: 'README.md',
|
||||
});
|
||||
|
||||
const result = docs
|
||||
.map((doc) => {
|
||||
return path.join(docsDir, doc);
|
||||
})
|
||||
.map((doc) => path.join(docsDir, doc))
|
||||
.filter((doc) => !isDocHide(doc))
|
||||
.sort((a, b) => {
|
||||
const orderA = getMarkdownOrder(a);
|
||||
const orderB = getMarkdownOrder(b);
|
||||
|
|
|
|||
|
|
@ -5,27 +5,27 @@ import styles from './feature.module.css';
|
|||
const data = [
|
||||
{
|
||||
title: '规范',
|
||||
decs: '从目录组织规范到代码风格,集成了结合阿里大量项目实践的研发规范',
|
||||
url: '/docs/guide/basic/structure',
|
||||
},
|
||||
{
|
||||
title: 'Vite',
|
||||
decs: '同时支持 Vite/Webpack 模式,提供极速的调试构建体验',
|
||||
url: '/docs/guide/about',
|
||||
decs: '从目录组织规范到代码风格,集成了结合阿里内部大量项目实践的研发规范',
|
||||
url: '/docs/guide/basic/directory',
|
||||
},
|
||||
{
|
||||
title: '开箱即用',
|
||||
decs: '支持 TypeScript/CSS Modules/PostCSS/... 等工程能力,框架 API 具备良好的类型提示能力',
|
||||
url: '/docs/guide/basic/build',
|
||||
decs: '支持 Webpack5/TypeScript/CSS Modules/PostCSS 等构建能力,框架 API 具备良好的类型提示',
|
||||
url: '/docs/guide/start',
|
||||
},
|
||||
{
|
||||
title: '移动+桌面',
|
||||
decs: '同时支持移动端和桌面端,提供更多针对性的优化',
|
||||
url: '/docs/guide/about',
|
||||
},
|
||||
{
|
||||
title: '最佳实践',
|
||||
decs: '内置数据请求、状态管理、SSR、前端配置、日志输出等最佳实践',
|
||||
url: '/docs/guide/basic/request',
|
||||
decs: '内置数据请求、路由、状态、构建配置、日志输出等最佳实践',
|
||||
url: '/docs/guide/basic/ssg',
|
||||
},
|
||||
{
|
||||
title: '应用模式',
|
||||
decs: '支持 SPA、MPA、微前端、Serverless 一体化等不同研发模式',
|
||||
decs: '支持 SPA、服务端渲染 SSR 以及静态构建 SSG 等不同研发模式',
|
||||
url: '/docs/guide/advanced/mpa',
|
||||
},
|
||||
{
|
||||
|
|
@ -33,12 +33,17 @@ const data = [
|
|||
decs: '通过插件将框架能力进行解耦,同时开发者也可以基于插件扩展框架能力',
|
||||
url: '/docs/plugin/develop/start',
|
||||
},
|
||||
{
|
||||
title: '领域方案',
|
||||
decs: '提供丰富的领域方案,如微前端 ICESTARK、包开发 ICE PKG、Serverless 一体化方案等',
|
||||
url: '/docs/plugin/develop/start',
|
||||
},
|
||||
];
|
||||
|
||||
function Feature() {
|
||||
return (
|
||||
<AreaWrapper
|
||||
title={'基于 React 的应用研发框架 icejs'}
|
||||
title={'基于 React 的应用研发框架 ICE 3'}
|
||||
decs={'开箱即用的研发框架,内置工程配置、状态管理、数据请求、权限管理等最佳实践,让开发者可以更加专注于业务逻辑'}
|
||||
contentStyle={styles.container}
|
||||
isBlock
|
||||
|
|
@ -49,7 +54,7 @@ function Feature() {
|
|||
<h3>{item.title}</h3>
|
||||
<span>{item.decs}</span>
|
||||
<div style={{ flex: 1 }} />
|
||||
<p>{'Documentation >'}</p>
|
||||
<p>{'查看文档 >'}</p>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ function Splash() {
|
|||
<header>
|
||||
<div className={styles.splash}>
|
||||
<div className={styles['title-container']}>
|
||||
<h1 className={styles.title}>飞冰(ICE) 3.0</h1>
|
||||
<h1 className={styles.title}>飞冰 (ICE)</h1>
|
||||
<p className={styles.subtitle}>
|
||||
基于 React 的应用研发框架
|
||||
基于 React 的应用研发框架,开箱即用,同时支持移动端和桌面端
|
||||
</p>
|
||||
<div className={styles.githubStars}>
|
||||
<iframe
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue