项目配置
TvT.js 目前选用的是 Vite 构建,原则上是支持 Webpack 构建的,具体将在后期放开。
编译时配置
我们约定 .fes.js
文件为项目编译需要编译时配置文件,可以引入 node
端依赖项,不要引入 浏览器端
依赖项。
WARNING
此文件.fes.js
中引入的第三方包,请确认第三方包包含 commonjs
的构建方法。若其不包含则会在编译中报错:equire() of ES Module *** from */.fes.js not supported
。 若需要给其增加 commonjs
的构建方法,详情请查看稍后章节:常见问题
import { join } from 'path';
import { defineBuildConfig } from '@fesjs/fes';
import { templateCompilerOptions } from '@tresjs/core';
import UnoCSS from 'unocss/vite';
export default defineBuildConfig({
publicPath: './',
mock: { // mock 配置
prefix: '/v2',
},
proxy: { // 代理 配置
'/v2': {
target: 'https://api.douban.com/',
changeOrigin: true,
},
},
access: { // 默认的 fes.js access 插件配置
roles: {
admin: ['*'],
manager: ['/'],
},
},
layout: { // 默认的 fes.js layout 插件配置
navigation: null,
},
enums: {
status: [['0', '无效的'], ['1', '有效的']]// 默认的 fes.js enums 插件配置
},
// ---Vite 专属配置 start----
viteVuePlugin: {
...templateCompilerOptions,
},
viteOption: {
base: "./",
plugins: [
UnoCSS({}),
],
},
// ......
// ---Vite 专属配置 end---
alias: { PLS: join(__dirname, './src/plugins') },
});
Vite 专属配置
viteOption
类型:
object
Vite 的配置,详情请看 Vite Config
viteVuePlugin
类型:
object
自定义 @vitejs/plugin-vue 的配置。
viteVueJsx
类型:
object
自定义 @vitejs/plugin-vue-jsx 的配置。
viteLegacy
类型:
object
自定义 @vitejs/plugin-legacy 的配置。
viteHtml
类型:
object
自定义 vite-plugin-html 的配置。
TIP
- 项目中除了
.fes.js
还有.fes.predev.js
,在预览模式
下,会增加.fes.predev.js
配置后再与.fes.js
做deep merge
后形成最终配置。 - 在项目中可以自行添加环境配置,类似:
FES_ENV=aaa fes dev
,这时候会命中.fes.aaa.js
这份环境配置文件。 - 详细配置可参考
运行时配置
我们 约定 src/app.jsx
为运行时配置文件。运行时配置和配置的区别是他跑在浏览器端,因此我们可以在这里写函数、引入浏览器端依赖项等等,注意不要引入 node 端依赖项。
运行时为啥需要配置?
Fes.js 框架跟传统开发模式不一样。传统开发模式中用户编写 entry 文件,而 Fes.js 中 entry 文件由框架生成,用户就不必要编写胶水代码。内置插件和其他插件提供的一些运行时功能提供用户或者其他插件自定义。
例如:
plugin-access 插件定义运行时配置项:
api.addRuntimePluginKey(() => 'access');
plugin-access 插件读取配置项:
const runtimeConfig = plugin.applyPlugins({
key: 'access',
type: ApplyPluginsType.modify,
initialValue: {},
});
而用户则只需要配置:
// app.js
import { defineRuntimeConfig } from '@fesjs/fes';
export default defineRuntimeConfig({
access: memo => ({
...memo
unAccessHandler({
router, to, from, next
}) {
// 处理逻辑
},
noFoundHandler({
router, to, from, next
}) {
// 处理逻辑
},
}),
});
配置智能提示
配置可以单独导出,也可以通过 defineRuntimeConfig
工具函数获取类型提示。
方式一(推荐,有类型提示):
// app.jsx
import { defineRuntimeConfig } from '@fesjs/fes';
export default defineRuntimeConfig({
access: memo => ({
...memo
unAccessHandler({
router, to, from, next
}) {
// 处理逻辑
},
noFoundHandler({
router, to, from, next
}) {
// 处理逻辑
},
}),
// ...其他配置项
});
方式二:
// app.jsx
export const access = memo => ({
...memo
unAccessHandler({
router, to, from, next
}) {
// 处理逻辑
},
noFoundHandler({
router, to, from, next
}) {
// 处理逻辑
},
});
Fes.js配置项
beforeRender
beforeRender(lastOpts)
在渲染之前执行,执行action
过程中显示 loading
配置的组件,执行结果作为参数 initialState
传给 modifyClientRenderOpts
。
示例:
// app.jsx
import { access } from '@fesjs/fes';
import PageLoading from '@/components/PageLoading';
import UserCenter from '@/components/UserCenter';
export function beforeRender(lastOpts) {
return {
...lastOpts,
loading: <PageLoading />,
action() {
const { setRole } = access;
return new Promise((resolve) => {
setTimeout(() => {
setRole('admin');
resolve({
userName: 'harrywan',
});
}, 1000);
});
},
};
}
patchRoutes
patchRoutes({routes })
WARNING
准备删除此API,推荐使用modifyRoute
修改路由。
比如在最前面添加一个 /foo 路由:
export function patchRoutes({ routes }) {
routes.unshift({
path: '/foo',
component: require('@/extraRoutes/foo').default,
});
}
TIP
直接修改 routes
, 不需要返回
modifyRoute
modifyRoute({base, createHistory, routes})
修改路由配置信息。
比如在最前面添加一个 /foo 路由:
export function modifyRoute(memo) {
return {
...memo,
routes: [
{
path: '/foo',
component: require('@/extraRoutes/foo').default,
},
...memo.routes
]
}
}
比如修改 base:
export function modifyRoute(memo) {
return {
...memo,
base: window.location.href
}
}
比如改为使用createMemoryHistory:
export function modifyRoute(memo) {
return {
...memo,
createHistory: createMemoryHistory
}
}
modifyClientRenderOpts
modifyClientRenderOpts(lastOpts)
修改 clientRender
参数。参数是一个对象:
- routes,路由配置信息
- rootElement, 渲染的根节点,默认是
#app
,可通过配置mountElementId
修改。 - initialState, 初始化数据,
beforeRender
运行得到的数据。
比如在微前端里动态修改渲染根节点:
let isSubApp = false;
export function modifyClientRenderOpts(lastOpts) {
return {
...lastOpts,
rootElement: isSubApp ? 'sub-root' : lastOpts.rootElement,
};
}
rootContainer
rootContainer(LastRootContainer, args)
修改交给 Vue 渲染时的根组件,默认是 <RouterView></RouterView>
。
- LastRootContainer,上一个插件修改后的结果。
- args,包含:
- routes,全量路由配置
- plugin,运行时插件机制
比如在可以包一层 DIV:
export function rootContainer(container) {
return () => {
return (
<div>
<RouterView></RouterView>
</div>
);
};
}
onAppCreated
onAppCreated({app})
创建 app 实例后触发。
比如用于安装 Vue 插件:
import { createRouter } from 'vue-router';
export function onAppCreated({ app }) {
const router = createRouter();
app.use(router);
}
render
render(oldRender: Function)
覆写 render。
比如用于渲染之前做权限校验。
onRouterCreated
onRouterCreated({router})
生成 router 时触发。
比如用于收集切换路由的记录:
export function onRouterCreated({ router }) {
router.afterEach((to, from) => {
console.log(to);
});
}