docs: 切换使用vitepress (#192)

* sdf

* docs: 优化文档

* fix: webpack 编译失败问题

---------

Co-authored-by: wanchun <445436867@qq.com>
This commit is contained in:
qlin 2023-04-24 14:41:41 +08:00 committed by GitHub
parent 1fb871da09
commit 70db98e617
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 3466 additions and 2548 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ dist
*.log *.log
node_modules node_modules
npm-debug.log npm-debug.log
docs/.vitepress/cache
/packages/fes-template/dist /packages/fes-template/dist
/packages/fes-doc/docs/.vuepress/dist /packages/fes-doc/docs/.vuepress/dist
/packages/fes-template/package-lock.json /packages/fes-template/package-lock.json

2
.npmrc
View File

@ -1,3 +1,3 @@
registry=https://registry.npmmirror.com registry=https://registry.npmmirror.com
auto-install-peers=true auto-install-peers=true
shamefully-hoist=true shamefully-hoist=true

50
docs/.vitepress/config.ts Normal file
View File

@ -0,0 +1,50 @@
import { defineConfig } from 'vitepress';
import { fileURLToPath, URL } from 'node:url';
import { withPwa } from '@vite-pwa/vitepress';
import { navbar, sidebar } from './configs';
const BASE_URL = process.env.BASE ? `/${process.env.BASE}/` : '/';
export default withPwa(
defineConfig({
base: BASE_URL,
title: 'Fes.js',
description: '一个好用的前端应用解决方案',
vite: {
resolve: {
alias: [
{
find: /^.*\/VPHero\.vue$/,
replacement: fileURLToPath(new URL('./theme/components/VPHero.vue', import.meta.url)),
},
],
},
},
head: [['link', { rel: 'icon', href: `/logo.png` }]],
themeConfig: {
socialLinks: [{ icon: 'github', link: 'https://github.com/WeBankFinTech/fes.js' }],
logo: '/logo.png',
nav: navbar.zh,
sidebar: sidebar.zh,
outline: {
label: '本页目录',
},
search: {
provider: 'local',
},
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2020-present Webank',
},
},
pwa: {},
}),
);

View File

@ -1,10 +1,11 @@
import type { NavbarConfig } from '@vuepress/theme-default' // import type { NavbarConfig } from '@vuepress/theme-default'
import { version } from '../../../../package.json' import { version } from '../../../../package.json'
export const zh: NavbarConfig = [ export const zh = [
{ {
text: '指南', text: '指南',
link: '/guide/', link: '/guide/',
activeMatch: '/guide/'
}, },
{ {
text: '编译时配置', text: '编译时配置',
@ -17,6 +18,7 @@ export const zh: NavbarConfig = [
{ {
text: '插件', text: '插件',
link: '/reference/plugin/', link: '/reference/plugin/',
activeMatch: '/plugin/'
}, },
{ {
text: 'CLI', text: 'CLI',
@ -24,7 +26,7 @@ export const zh: NavbarConfig = [
}, },
{ {
text: `v${version}`, text: `v${version}`,
children: [ items: [
{ {
text: 'v2.0', text: 'v2.0',
link: link:
@ -38,11 +40,11 @@ export const zh: NavbarConfig = [
}, },
{ {
text: '了解更多', text: '了解更多',
children: [ items: [
{ {
text: '更新日志', text: '更新日志',
link: link:
'https://github.com/WeBankFinTech/fes.js/blob/next/CHANGELOG.md', 'https://github.com/WeBankFinTech/fes.js/blob/master/CHANGELOG.md',
}, },
{ {
text: 'fes-design', text: 'fes-design',

View File

@ -0,0 +1,169 @@
// import type { SidebarConfig } from '@vuepress/theme-default';
export const zh = {
'/guide/': [
{
text: '开始',
items: [
{
text: '介绍',
link: '/guide/index.md'
},
{
text: '快速上手',
link: '/guide/getting-started.md'
}
],
},
{
text: '基础',
items: [
{
text: '目录结构',
link: '/guide/directory-structure.md'
},{
text: 'Vite 和 Webpack 双构建',
link: '/guide/builder.md'
},{
text: '编译时配置',
link: '/guide/config.md'
},{
text: '运行时配置',
link: '/guide/runtime-config.md'
},{
text: '环境变量',
link: '/guide/env.md'
},{
text: '路由',
link: '/guide/route.md'
},{
text: '插件',
link: '/guide/plugin.md'
},{
text: 'HTML 模板',
link: '/guide/template.md'
},{
text: 'Mock 数据',
link: '/guide/mock.md'
},{
text: '从 2.0.x 迁移到 3.0.x',
link: '/guide/upgrade3.md'
}
],
},
{
text: '样式和资源文件',
items: [
{
text: '使用图片',
link: '/guide/image.md'
},
{
text: '使用 css',
link: '/guide/css.md'
},
{
text: '静态资源',
link: '/guide/public.md'
}
],
},
{
text: '贡献指南',
link: '/guide/contributing.md'
},
{
text: '常见问题',
link: '/guide/faq.md'
},
],
'/reference/plugin/': [
{
text: '介绍',
link: '/reference/plugin/index.md'
},
{
text: 'Plugins',
items: [
{
text: '@fesjs/plugin-access',
link: '/reference/plugin/plugins/access.md'
},
{
text: '@fesjs/plugin-enums',
link: '/reference/plugin/plugins/enums.md'
},
{
text: '@fesjs/plugin-icon',
link: '/reference/plugin/plugins/icon.md'
},
{
text: '@fesjs/plugin-jest',
link: '/reference/plugin/plugins/jest.md'
},
{
text: '@fesjs/plugin-layout',
link: '/reference/plugin/plugins/layout.md'
},
{
text: '@fesjs/plugin-locale',
link: '/reference/plugin/plugins/locale.md'
},
{
text: '@fesjs/plugin-model',
link: '/reference/plugin/plugins/model.md'
},
{
text: '@fesjs/plugin-request',
link: '/reference/plugin/plugins/request.md'
},
{
text: '@fesjs/plugin-vuex',
link: '/reference/plugin/plugins/vuex.md'
},
{
text: '@fesjs/plugin-qiankun',
link: '/reference/plugin/plugins/qiankun.md'
},
{
text: '@fesjs/plugin-windicss',
link: '/reference/plugin/plugins/windicss.md'
},
{
text: '@fesjs/plugin-sass',
link: '/reference/plugin/plugins/sass.md'
},
{
text: '@fesjs/plugin-editor',
link: '/reference/plugin/plugins/editor.md'
},
{
text: '@fesjs/plugin-pinia',
link: '/reference/plugin/plugins/pinia.md'
},
{
text: '@fesjs/plugin-watermark',
link: '/reference/plugin/plugins/watermark.md'
},
{
text: '@fesjs/plugin-login',
link: '/reference/plugin/plugins/login.md'
},
{
text: '@fesjs/plugin-swc',
link: '/reference/plugin/plugins/swc.md'
},
],
},
{
text: '插件开发',
items: [{
text: '插件介绍',
link: '/reference/plugin/dev/index.md'
}, {
text: '插件API',
link: '/reference/plugin/dev/api.md'
}],
},
],
};

View File

@ -0,0 +1,38 @@
<template>
<div class="VPFeatures">
<div class="vp-doc fes-home container">
<slot></slot>
</div>
</div>
</template>
<style scoped>
.VPFeatures {
position: relative;
padding: 0 24px;
margin-top: 32px;
}
@media (min-width: 640px) {
.VPFeatures {
padding: 0 48px;
}
}
@media (min-width: 960px) {
.VPFeatures {
padding: 0 64px;
}
}
.container {
margin: 0 auto;
max-width: 1152px;
}
</style>
<style>
.fes-home img {
height: 320px;
}
</style>

View File

@ -0,0 +1,150 @@
<script setup lang="ts">
import { computed } from 'vue'
import { withBase, useData } from 'vitepress'
const PATHNAME_PROTOCOL_RE = /^pathname:\/\//
const EXTERNAL_URL_RE = /^[a-z]+:/i
function normalizeLink(url: string): string {
if (EXTERNAL_URL_RE.test(url)) {
return url.replace(PATHNAME_PROTOCOL_RE, '')
}
const { site } = useData()
const { pathname, search, hash } = new URL(url, 'http://example.com')
const normalizedPath =
pathname.endsWith('/') || pathname.endsWith('.html')
? url
: url.replace(
/(?:(^\.+)\/)?.*$/,
`$1${pathname.replace(
/(\.md)?$/,
site.value.cleanUrls ? '' : '.html'
)}${search}${hash}`
)
return withBase(normalizedPath)
}
const props = defineProps<{
tag?: string
size?: 'medium' | 'big'
theme?: 'brand' | 'alt' | 'sponsor'
text: string
href?: string
}>()
const classes = computed(() => [
props.size ?? 'medium',
props.theme ?? 'brand'
])
const isExternal = computed(() => props.href && EXTERNAL_URL_RE.test(props.href))
const component = computed(() => {
if (props.tag) {
return props.tag
}
return props.href ? 'a' : 'button'
})
</script>
<template>
<component
:is="component"
class="VPButton"
:class="classes"
:href="href ? normalizeLink(href) : undefined"
:target="isExternal ? '_blank' : undefined"
:rel="isExternal ? 'noreferrer' : undefined"
>
{{ text }}
</component>
</template>
<style scoped>
.VPButton {
display: inline-block;
border: 1px solid transparent;
text-align: center;
font-weight: 600;
white-space: nowrap;
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
}
.VPButton:active {
transition: color 0.1s, border-color 0.1s, background-color 0.1s;
}
.VPButton.medium {
border-radius:4px;
padding: 0 20px;
line-height: 38px;
font-size: 14px;
}
.VPButton.big {
border-radius: 24px;
padding: 0 24px;
line-height: 46px;
font-size: 16px;
}
.VPButton.brand {
border-color: var(--vp-button-brand-border);
color: var(--vp-button-brand-text);
background-color: var(--vp-button-brand-bg);
}
.VPButton.brand:hover {
border-color: var(--vp-button-brand-hover-border);
color: var(--vp-button-brand-hover-text);
background-color: var(--vp-button-brand-hover-bg);
}
.VPButton.brand:active {
border-color: var(--vp-button-brand-active-border);
color: var(--vp-button-brand-active-text);
background-color: var(--vp-button-brand-active-bg);
}
.VPButton.alt {
border-color: var(--vp-button-alt-border);
color: var(--vp-button-alt-text);
background-color: var(--vp-button-alt-bg);
}
.VPButton.alt:hover {
border-color: var(--vp-button-alt-hover-border);
color: var(--vp-button-alt-hover-text);
background-color: var(--vp-button-alt-hover-bg);
}
.VPButton.alt:active {
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
}
.VPButton.sponsor {
border-color: var(--vp-button-sponsor-border);
color: var(--vp-button-sponsor-text);
background-color: var(--vp-button-sponsor-bg);
}
.VPButton.sponsor:hover {
border-color: var(--vp-button-sponsor-hover-border);
color: var(--vp-button-sponsor-hover-text);
background-color: var(--vp-button-sponsor-hover-bg);
}
.VPButton.sponsor:active {
border-color: var(--vp-button-sponsor-active-border);
color: var(--vp-button-sponsor-active-text);
background-color: var(--vp-button-sponsor-active-bg);
}
</style>

View File

@ -0,0 +1,256 @@
<script setup lang="ts">
import { type Ref, inject } from 'vue'
import type { DefaultTheme } from 'vitepress/theme'
import VPButton from './VPButton.vue'
import VPImage from './VPImage.vue'
export interface HeroAction {
theme?: 'brand' | 'alt'
text: string
link: string
}
defineProps<{
name?: string
text?: string
tagline?: string
image?: DefaultTheme.ThemeableImage
actions?: HeroAction[]
}>()
const heroImageSlotExists = inject('hero-image-slot-exists') as Ref<boolean>
</script>
<template>
<div class="VPHero">
<div class="container">
<div v-if="image || heroImageSlotExists" class="image">
<div class="image-container">
<div class="image-bg" />
<slot name="home-hero-image">
<VPImage v-if="image" class="image-src" :image="image" />
</slot>
</div>
</div>
<div class="main">
<slot name="home-hero-info">
<h1 v-if="name" class="name">
<span class="clip">{{ name }}</span>
</h1>
<p v-if="text" class="text">{{ text }}</p>
<p v-if="tagline" class="tagline">{{ tagline }}</p>
</slot>
<div v-if="actions" class="actions">
<div v-for="action in actions" :key="action.link" class="action">
<VPButton
tag="a"
size="medium"
:theme="action.theme"
:text="action.text"
:href="action.link"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.VPHero {
margin-top: calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);
padding: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 42px) 24px 48px;
}
@media (min-width: 640px) {
.VPHero {
padding: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 42px) 48px 64px;
}
}
@media (min-width: 960px) {
.VPHero {
padding: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 42px) 64px 64px;
}
}
.container {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0 auto;
max-width: 1152px;
}
.main {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
z-index: 10;
flex-shrink: 0;
}
.name,
.text {
max-width: 392px;
letter-spacing: -0.4px;
line-height: 40px;
font-size: 32px;
font-weight: 700;
white-space: pre-wrap;
}
.name {
color: #fff;
}
.clip {
background: #fff;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: #fff;
}
@media (min-width: 640px) {
.name,
.text {
max-width: 576px;
line-height: 56px;
font-size: 48px;
}
}
@media (min-width: 960px) {
.name,
.text {
line-height: 64px;
font-size: 56px;
}
}
.tagline {
padding-top: 8px;
max-width: 392px;
line-height: 28px;
font-size: 18px;
font-weight: 500;
white-space: pre-wrap;
color: var(--vp-c-text-2);
}
@media (min-width: 640px) {
.tagline {
padding-top: 12px;
max-width: 576px;
line-height: 32px;
font-size: 20px;
}
}
@media (min-width: 960px) {
.tagline {
line-height: 36px;
font-size: 24px;
}
}
.actions {
display: flex;
flex-wrap: wrap;
margin: -6px;
padding-top: 24px;
}
@media (min-width: 640px) {
.actions {
padding-top: 32px;
}
}
.action {
flex-shrink: 0;
padding: 6px;
}
.image-container {
position: relative;
margin: 0 auto;
height: 320px;
}
@media (min-width: 640px) {
.image-container {
width: 392px;
height: 392px;
}
}
@media (min-width: 960px) {
.image-container {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
}
}
.image-bg {
position: absolute;
top: 50%;
/*rtl:ignore*/
left: 50%;
border-radius: 50%;
width: 192px;
height: 192px;
background-image: var(--vp-home-hero-image-background-image);
filter: var(--vp-home-hero-image-filter);
/*rtl:ignore*/
transform: translate(-50%, -50%);
}
@media (min-width: 640px) {
.image-bg {
width: 256px;
height: 256px;
}
}
@media (min-width: 960px) {
.image-bg {
width: 320px;
height: 320px;
}
}
:deep(.image-src) {
position: absolute;
top: 50%;
/*rtl:ignore*/
left: 50%;
max-width: 192px;
max-height: 192px;
/*rtl:ignore*/
transform: translate(-50%, -50%);
}
@media (min-width: 640px) {
:deep(.image-src) {
max-width: 256px;
max-height: 256px;
}
}
@media (min-width: 960px) {
:deep(.image-src) {
max-width: 320px;
max-height: 320px;
}
}
</style>

View File

@ -0,0 +1,50 @@
<script setup lang="ts">
import type { DefaultTheme } from 'vitepress/theme'
import { withBase } from 'vitepress'
defineProps<{
image: DefaultTheme.ThemeableImage
alt?: string
}>()
</script>
<script lang="ts">
export default {
inheritAttrs: false
}
</script>
<template>
<template v-if="image">
<img
v-if="typeof image === 'string' || 'src' in image"
class="VPImage"
v-bind="typeof image === 'string' ? $attrs : { ...image, ...$attrs }"
:src="withBase(typeof image === 'string' ? image : image.src)"
:alt="alt ?? (typeof image === 'string' ? '' : image.alt || '')"
/>
<template v-else>
<VPImage
class="dark"
:image="image.dark"
:alt="image.alt"
v-bind="$attrs"
/>
<VPImage
class="light"
:image="image.light"
:alt="image.alt"
v-bind="$attrs"
/>
</template>
</template>
</template>
<style scoped>
html:not(.dark) .VPImage.dark {
display: none;
}
.dark .VPImage.light {
display: none;
}
</style>

View File

@ -0,0 +1,8 @@
:root {
--vp-c-brand: #5384ff;
--vp-button-brand-border: #5384ff;
--vp-button-brand-hover-border: #5384ff;
--vp-button-brand-hover-bg: #759dff;
--vp-local-search-highlight-bg: #7da6ff;
--vp-c-brand-light: #747bff;
}

View File

@ -0,0 +1,10 @@
import DefaultTheme from 'vitepress/theme'
import HomeContent from './components/HomeContent.vue'
import './custom.css';
export default {
extends: DefaultTheme,
enhanceApp(ctx) {
ctx.app.component('HomeContent', HomeContent);
}
}

View File

@ -1,94 +0,0 @@
import { defineUserConfig } from '@vuepress/cli';
import { defaultTheme } from '@vuepress/theme-default';
import { docsearchPlugin } from '@vuepress/plugin-docsearch';
import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup';
import { pwaPlugin } from '@vuepress/plugin-pwa';
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'
import { navbar, sidebar } from './configs';
export default defineUserConfig({
base: process.env.BASE ? `/${process.env.BASE}/` : '/',
head: [
['link', { rel: 'manifest', href: '/manifest.webmanifest' }],
['link', { rel: 'icon', href: `/logo.png` }],
],
// site-level locales config
locales: {
'/': {
lang: 'zh-CN',
title: 'Fes.js',
description: '一个好用的前端应用解决方案',
},
},
theme: defaultTheme({
logo: '/logo.png',
repo: 'WeBankFinTech/fes.js',
docsDir: 'docs',
docsBranch: 'next',
// theme-level locales config
locales: {
/**
* English locale config
*
* As the default locale of @vuepress/theme-default is English,
* we don't need to set all of the locale fields
*/
'/': {
navbar: navbar.zh,
selectLanguageName: '简体中文',
selectLanguageText: '选择语言',
selectLanguageAriaLabel: '选择语言',
// sidebar
sidebar: sidebar.zh,
// page meta
editLinkText: '在 GitHub 上编辑此页',
lastUpdatedText: '上次更新',
contributorsText: '贡献者',
// custom containers
tip: '提示',
warning: '注意',
danger: '警告',
// 404 page
notFound: ['这里什么都没有', '我们怎么到这来了?', '这是一个 404 页面', '看起来我们进入了错误的链接'],
backToHome: '返回首页',
// other
openInNewWindow: '在新窗口打开',
},
},
}),
plugins: [
docsearchPlugin({
appId: '4ZF3BCJTP5',
apiKey: '09ff75bbe16bc6e166e103ffb57e10ea',
indexName: 'fesjs',
locales: {
'/': {
placeholder: '搜索文档',
},
},
}),
pwaPlugin(),
pwaPopupPlugin({
locales: {
'/': {
message: '发现新内容可用',
buttonText: '刷新',
},
},
}),
backToTopPlugin()
],
});

View File

@ -1,68 +0,0 @@
import type { SidebarConfig } from '@vuepress/theme-default';
export const zh: SidebarConfig = {
'/guide/': [
{
// isGroup: true,
text: '介绍',
children: ['/guide/README.md', '/guide/getting-started.md'],
},
{
// isGroup: true,
text: '基础',
children: [
'/guide/directory-structure.md',
'/guide/builder.md',
'/guide/config.md',
'/guide/runtime-config.md',
'/guide/env.md',
'/guide/route.md',
'/guide/plugin.md',
'/guide/template.md',
'/guide/mock.md',
'/guide/upgrade3.md',
],
},
{
// isGroup: true,
text: '样式和资源文件',
children: ['/guide/image.md', '/guide/css.md', '/guide/public.md'],
},
'/guide/contributing.md',
'/guide/faq.md',
],
'/reference/config/': ['/reference/config/README.md'],
'/reference/api/': ['/reference/api/README.md'],
'/reference/plugin/': [
'/reference/plugin/README.md',
{
// isGroup: true,
text: 'Plugins',
children: [
'/reference/plugin/plugins/access.md',
'/reference/plugin/plugins/enums.md',
'/reference/plugin/plugins/icon.md',
'/reference/plugin/plugins/jest.md',
'/reference/plugin/plugins/layout.md',
'/reference/plugin/plugins/locale.md',
'/reference/plugin/plugins/model.md',
'/reference/plugin/plugins/request.md',
'/reference/plugin/plugins/vuex.md',
'/reference/plugin/plugins/qiankun.md',
'/reference/plugin/plugins/windicss.md',
'/reference/plugin/plugins/sass.md',
'/reference/plugin/plugins/editor.md',
'/reference/plugin/plugins/pinia.md',
'/reference/plugin/plugins/watermark.md',
'/reference/plugin/plugins/login.md',
'/reference/plugin/plugins/swc.md',
],
},
{
// isGroup: true,
text: '插件开发',
children: ['/reference/plugin/dev/README.md', '/reference/plugin/dev/api.md'],
},
],
'/reference/cli/': ['/reference/cli/README.md'],
};

View File

@ -1,3 +0,0 @@
.page
.page-meta, .page-nav, .theme-default-content:not(.custom)
max-width: 1000px

View File

@ -1,4 +1,4 @@
# 支持 Vite 和 Webpack 双构建 # Vite 和 Webpack 双构建
`Fes.js@3.0.x` 版本支持 Vite 和 Webpack 两种构建方式,不再内置构建方式,需要开发者自行选择: `Fes.js@3.0.x` 版本支持 Vite 和 Webpack 两种构建方式,不再内置构建方式,需要开发者自行选择:

View File

@ -1,5 +1,9 @@
# 贡献指南 # 贡献指南
<script setup>
import { withBase } from 'vitepress'
</script>
## 包概览 ## 包概览
项目仓库借助于 [pnpm 工作区](https://pnpm.io/pnpm-workspace_yaml) 来实现 [ Monorepo](https://en.wikipedia.org/wiki/Monorepo) ,在 `packages` 目录下存放多个互相关联的独立包。 项目仓库借助于 [pnpm 工作区](https://pnpm.io/pnpm-workspace_yaml) 来实现 [ Monorepo](https://en.wikipedia.org/wiki/Monorepo) ,在 `packages` 目录下存放多个互相关联的独立包。
@ -60,7 +64,7 @@ pnpm docs:dev
如果想添加图片,则可以先把图片添加至`/docs/.vuepress/public`,在代码中使用: 如果想添加图片,则可以先把图片添加至`/docs/.vuepress/public`,在代码中使用:
```html ```html
<img :src="$withBase('framework.png')" alt="架构" /> <img :src="withBase('framework.png')" alt="架构" />
``` ```
#### 第三步:查看更新 #### 第三步:查看更新

View File

@ -17,24 +17,20 @@ set PORT=3000 && fes dev
``` ```
如果要同时考虑 OS X 和 Windows可借助三方工具 [cross-env](https://github.com/kentcdodds/cross-env) 如果要同时考虑 OS X 和 Windows可借助三方工具 [cross-env](https://github.com/kentcdodds/cross-env)
<CodeGroup>
<CodeGroupItem title="PNPM" active>
```bash ::: code-group
```sh [pnpm]
pnpm add cross-env --dev pnpm add cross-env --dev
cross-env PORT=3000 fes dev cross-env PORT=3000 fes dev
``` ```
</CodeGroupItem> ```sh [npm]
<CodeGroupItem title="NPM">
```bash
npm i cross-env --save-dev npm i cross-env --save-dev
cross-env PORT=3000 fes dev cross-env PORT=3000 fes dev
``` ```
</CodeGroupItem> :::
</CodeGroup>
### `.env` 文件配置 ### `.env` 文件配置

View File

@ -1,5 +1,9 @@
# 快速上手 # 快速上手
<script setup>
import { withBase } from 'vitepress'
</script>
## 依赖环境 ## 依赖环境
首先得有 [Node.js](https://nodejs.org/),并确保 node 版本是 12.13 或以上。 首先得有 [Node.js](https://nodejs.org/),并确保 node 版本是 12.13 或以上。
@ -41,29 +45,23 @@ cd workspace
##### 步骤 2 在工作空间创建项目 ##### 步骤 2 在工作空间创建项目
<CodeGroup> ::: code-group
<CodeGroupItem title="PNPM" active>
```bash ```bash [pnpm]
# 创建模板 # 创建模板
pnpm create @fesjs/fes-app myapp pnpm create @fesjs/fes-app myapp
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 创建模板 # 创建模板
npx @fesjs/create-fes-app myapp npx @fesjs/create-fes-app myapp
``` ```
</CodeGroupItem> :::
</CodeGroup>
如果项目文件夹 `workspace/myapp` 已经存在,会提示目录已存在: 如果项目文件夹 `workspace/myapp` 已经存在,会提示目录已存在:
<img :src="$withBase('pickTemplateTip.png')" alt="目录已存在提示"> <img :src="withBase('pickTemplateTip.png')" alt="目录已存在提示">
你可以选择: 你可以选择:
@ -71,42 +69,35 @@ npx @fesjs/create-fes-app myapp
- `Merge` 保留原项目文件夹,存在相同文件则用模板文件覆盖当前目录文件。 - `Merge` 保留原项目文件夹,存在相同文件则用模板文件覆盖当前目录文件。
当选择 `Overwrite` 或者 `Merge` 或者项目目录 `workspace/myapp` 不存在,会提示选取一个 `template` 当选择 `Overwrite` 或者 `Merge` 或者项目目录 `workspace/myapp` 不存在,会提示选取一个 `template`
<img :src="$withBase('pickTemplate.png')" alt="选择模板类型"> <img :src="withBase('pickTemplate.png')" alt="选择模板类型">
你可以选默认适用于中后台前端应用的 `PC` 类型,也可以选适用于移动端的 `H5` 类型。 你可以选默认适用于中后台前端应用的 `PC` 类型,也可以选适用于移动端的 `H5` 类型。
##### 步骤 3 安装依赖 ##### 步骤 3 安装依赖
<CodeGroup> ::: code-group
<CodeGroupItem title="PNPM" active>
```bash ```bash [pnpm]
# 进入项目目录 # 进入项目目录
cd myapp cd myapp
# 安装依赖 # 安装依赖
pnpm i pnpm i
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 进入项目目录 # 进入项目目录
cd myapp cd myapp
# 安装依赖 # 安装依赖
npm i npm i
``` ```
</CodeGroupItem> :::
</CodeGroup>
## 启动项目 ## 启动项目
<CodeGroup> ::: code-group
<CodeGroupItem title="PNPM" active>
```bash ```bash [pnpm]
# 开发调试 # 开发调试
pnpm dev pnpm dev
@ -120,11 +111,7 @@ Starting the development server http://localhost:8000 ...
DONE Compiled successfully in 15917ms 11:17:08 AM DONE Compiled successfully in 15917ms 11:17:08 AM
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 开发调试 # 开发调试
npm run dev npm run dev
@ -137,21 +124,19 @@ Starting the development server http://localhost:8000 ...
DONE Compiled successfully in 3662ms 11:17:46 AM DONE Compiled successfully in 3662ms 11:17:46 AM
``` ```
</CodeGroupItem> :::
</CodeGroup>
Fes.js 会在 [http://localhost:8000](http://localhost:8000) 启动一个热重载的开发服务器。当你修改你的 .vue 文件时,浏览器中的内容也会自动更新。 Fes.js 会在 [http://localhost:8000](http://localhost:8000) 启动一个热重载的开发服务器。当你修改你的 .vue 文件时,浏览器中的内容也会自动更新。
<img :src="$withBase('home.png')" alt="home"> <img :src="withBase('home.png')" alt="home">
## 部署发布 ## 部署发布
### 构建 ### 构建
<CodeGroup> ::: code-group
<CodeGroupItem title="PNPM" active>
```bash ```bash [pnpm]
# 构建 # 构建
pnpm build pnpm build
@ -164,11 +149,7 @@ $ fes build
✨ Done in 48.87s. ✨ Done in 48.87s.
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 构建 # 构建
npm run build npm run build
@ -178,8 +159,7 @@ npm run build
Compiled successfully in 45.37s Compiled successfully in 45.37s
``` ```
</CodeGroupItem> :::
</CodeGroup>
构建产物默认生成到 ./dist 下,然后通过 tree 命令查看。 构建产物默认生成到 ./dist 下,然后通过 tree 命令查看。

View File

@ -1,56 +1,61 @@
# 介绍 # 介绍
<script setup>
import { withBase } from 'vitepress'
</script>
## 痛点 ## 痛点
在开发一个前端项目之前,我们可能需要做如下准备工作: 在开发一个前端项目之前,我们可能需要做如下准备工作:
- 搭建开发环境
- 约定代码规范 - 搭建开发环境
- 封装API请求 - 约定代码规范
- 配置路由 - 封装 API 请求
- 实现布局、菜单、导航 - 配置路由
- 实现登录 - 实现布局、菜单、导航
- 权限管理 - 实现登录
- ... - 权限管理
- ...
除了准备工作之外,还会遇到很多相似的业务类型,比如中后台应用大多都是工作台、增删改查、权限、图表等。如果每次项目都完全手动处理一遍,不仅耗费时间,久而久之可能会存在多种技术栈、开发规范,导致开发流程不统一,历史项目越来越难维护。所以我们需要一套完整的解决方案,管理开发到部署整个流程。 除了准备工作之外,还会遇到很多相似的业务类型,比如中后台应用大多都是工作台、增删改查、权限、图表等。如果每次项目都完全手动处理一遍,不仅耗费时间,久而久之可能会存在多种技术栈、开发规范,导致开发流程不统一,历史项目越来越难维护。所以我们需要一套完整的解决方案,管理开发到部署整个流程。
## Fes.js 是什么? ## Fes.js 是什么?
Fes.js 是一个好用的前端应用解决方案。Fes.js 以 Vue 3.0 和路由为基础,同时支持配置式路由和约定式路由,并以此进行功能扩展。配以覆盖编译时和运行时生命周期完善的插件体系,支持各种功能扩展和业务需求。 Fes.js 是一个好用的前端应用解决方案。Fes.js 以 Vue 3.0 和路由为基础,同时支持配置式路由和约定式路由,并以此进行功能扩展。配以覆盖编译时和运行时生命周期完善的插件体系,支持各种功能扩展和业务需求。
它主要具备以下特点: 它主要具备以下特点:
- 🚀 __快速__ 内置了路由、开发、构建等并且提供测试、布局、权限、国际化、状态管理、API请求、数据字典、SvgIcon等插件可以满足大部分日常开发需求。
- 🧨 __简单__ 基于Vue.js 3.0上手简单。贯彻“约定优于配置”思想设计插件上尽可能用约定替代配置同时提供统一的插件配置入口简单简洁又不失灵活。提供一致性的API入口一致化的体验学习起来更轻松。
- 💪 __健壮__ 只需要关心页面内容减少写BUG的机会提供单元测试、覆盖测试能力保障项目质量。 - 🚀 **快速** 内置了路由、开发、构建等并且提供测试、布局、权限、国际化、状态管理、API 请求、数据字典、SvgIcon 等插件,可以满足大部分日常开发需求。
- 🧨 **简单** ,基于 Vue.js 3.0,上手简单。贯彻“约定优于配置”思想,设计插件上尽可能用约定替代配置,同时提供统一的插件配置入口,简单简洁又不失灵活。提供一致性的 API 入口,一致化的体验,学习起来更轻松。
- 📦 __可扩展__ 借鉴Umi实现了完整的生命周期和插件化机制插件可以管理项目的编译时和运行时能力均可以通过插件封装进来在 Fes.js 中协调有序的运行 - 💪 **健壮** ,只需要关心页面内容,减少写 BUG 的机会!提供单元测试、覆盖测试能力保障项目质量
- 📡 __面向未来__ 在满足需求的同时我们也不会停止对新技术的探索。已使用Vue3.0来提升应用性能已使用webpack5提升构建性能和实现微服务未来会探索vite等新技术 - 📦 **可扩展** ,借鉴 Umi 实现了完整的生命周期和插件化机制,插件可以管理项目的编译时和运行时,能力均可以通过插件封装进来,在 Fes.js 中协调有序的运行
- 📡 **面向未来** ,在满足需求的同时,我们也不会停止对新技术的探索。已使用 Vue3.0 来提升应用性能,已使用 webpack5 提升构建性能和实现微服务,未来会探索 vite 等新技术。
## Fes.js 如何工作? ## Fes.js 如何工作?
### 架构 ### 架构
<!-- ![架构](/framework.png "架构") --> <!-- ![架构](/framework.png "架构") -->
<img :src="$withBase('framework.png')" alt="架构"> <img :src="withBase('framework.png')" alt="架构">
Fes.js 把大家常用的技术栈封装成一个个插件进行整理,收敛到一起,让大家只用 Fes.js 就可以完成 80% 的日常工作。 Fes.js 把大家常用的技术栈封装成一个个插件进行整理,收敛到一起,让大家只用 Fes.js 就可以完成 80% 的日常工作。
### 插件和插件集 ### 插件和插件集
<p> <p>
<img :src="$withBase('plugins.png')" alt="插件" title="插件" style="width: 500px" class="medium-zoom-image"> <img :src="withBase('plugins.png')" alt="插件" title="插件" style="width: 500px" class="medium-zoom-image">
</p> </p>
Fes.js 支持插件和插件集,通过这张图应该很好理解到他们的关系,通过插件集我们把插件收敛依赖然后支持不同的业务类型。 Fes.js 支持插件和插件集,通过这张图应该很好理解到他们的关系,通过插件集我们把插件收敛依赖然后支持不同的业务类型。
### .fes 临时文件 ### .fes 临时文件
.fes 临时目录是整个 Fes.js 项目的发动机,你的入口文件、路由等等都在这里,这些是由 fes 内部插件及三方插件生成的。 .fes 临时目录是整个 Fes.js 项目的发动机,你的入口文件、路由等等都在这里,这些是由 fes 内部插件及三方插件生成的。
你通常会在 .fes 下看到以下目录 你通常会在 .fes 下看到以下目录
``` ```
+ .fes + .fes
+ core # 内部插件生成 + core # 内部插件生成
@ -63,8 +68,6 @@ Fes.js 支持插件和插件集,通过这张图应该很好理解到他们的
你可以在这里调试代码,但不要在 .git 仓库里提交他,因为他的临时性,每次启动 fes 时都会被删除并重新生成。 你可以在这里调试代码,但不要在 .git 仓库里提交他,因为他的临时性,每次启动 fes 时都会被删除并重新生成。
## 为什么不是 ...? ## 为什么不是 ...?
### Vue CLI ### Vue CLI
@ -73,4 +76,4 @@ Vue CLI 是基于 Vue.js 进行快速开发的完整系统,提供交互式脚
### UMI ### UMI
UMI 是个很好的选择Fes.js 很多功能是借鉴 UMI 做的。UMI 是基于 React 封装的应用级框架,贯彻着函数式编程的思维。而 Vue 有所不同,虽然 Vue 3.0 向函数式迈了一大步,但大家可能依然喜欢编写 `.vue`文件,而非 `.jsx` 文件。两种思维方式会导致部分API设计上有所差异虽然 UMI 有 `plugin-vue` ,但不太 "vue"。推荐喜欢 React 的同学使用 UMI。 UMI 是个很好的选择Fes.js 很多功能是借鉴 UMI 做的。UMI 是基于 React 封装的应用级框架,贯彻着函数式编程的思维。而 Vue 有所不同,虽然 Vue 3.0 向函数式迈了一大步,但大家可能依然喜欢编写 `.vue`文件,而非 `.jsx` 文件。两种思维方式会导致部分 API 设计上有所差异,虽然 UMI 有 `plugin-vue` ,但不太 "vue"。推荐喜欢 React 的同学使用 UMI。

View File

@ -1,14 +1,20 @@
--- ---
home: true layout: home
title: 首页 title: Fes.js
heroImage: /logo.png
actions: hero:
- text: 快速上手 name: Fes.js
link: /guide/getting-started.html tagline: 一个好用的前端应用解决方案
type: primary image:
- text: 项目简介 src: /logo.png
link: /guide/ alt: VitePress
type: secondary actions:
- text: 快速上手
link: /guide/getting-started.html
theme: brand
- text: 项目简介
link: /guide/
theme: alt
features: features:
- title: Fast - title: Fast
details: Fes.js 内置路由、构建、插件管理提供测试、布局、权限、国际化、状态管理、请求、数据字典、SVG等插件可以满足大部分日常开发需求。 details: Fes.js 内置路由、构建、插件管理提供测试、布局、权限、国际化、状态管理、请求、数据字典、SVG等插件可以满足大部分日常开发需求。
@ -22,16 +28,15 @@ features:
details: 在满足需求的同时,我们也不会停止对新技术的探索。已使用 Vue3.0 来提升应用性能,已使用 webpack5 和 vite 提升构建性能和实现微服务。 details: 在满足需求的同时,我们也不会停止对新技术的探索。已使用 Vue3.0 来提升应用性能,已使用 webpack5 和 vite 提升构建性能和实现微服务。
- title: 令人愉悦 - title: 令人愉悦
details: 我们的主要重点是开发人员体验。我们喜欢 Fes.js并且会不断改进框架所以您也喜欢它期待有吸引力的解决方案描述性的错误消息强大的默认值和详细的文档。如果有问题或疑问我们有用的社区将为您提供帮助。 details: 我们的主要重点是开发人员体验。我们喜欢 Fes.js并且会不断改进框架所以您也喜欢它期待有吸引力的解决方案描述性的错误消息强大的默认值和详细的文档。如果有问题或疑问我们有用的社区将为您提供帮助。
footer: MIT Licensed | Copyright © 2020-present Webank
--- ---
<HomeContent>
## 像数 1, 2, 3 一样容易 ## 像数 1, 2, 3 一样容易
::: code-group
<CodeGroup> ```bash [pnpm]
<CodeGroupItem title="PNPM" active>
```bash
# 创建模板 # 创建模板
pnpm create @fesjs/fes-app myapp pnpm create @fesjs/fes-app myapp
@ -42,11 +47,7 @@ pnpm i
pnpm dev pnpm dev
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 创建模板 # 创建模板
npx @fesjs/create-fes-app myapp npx @fesjs/create-fes-app myapp
@ -57,11 +58,12 @@ npm install
npm run dev npm run dev
``` ```
</CodeGroupItem> :::
</CodeGroup>
## 反馈 ## 反馈
| Github Issue | Fes.js 开源运营小助手 | | Github Issue | Fes.js 开源运营小助手 |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| [@fesjs/fes.js/issues](https://github.com/WeBankFinTech/fes.js/issues) | <img src="https://cos-1254145788.cos.ap-guangzhou.myqcloud.com/WechatIMG104.jpeg" height="250"/> | | [@fesjs/fes.js/issues](https://github.com/WeBankFinTech/fes.js/issues) | <img src="https://cos-1254145788.cos.ap-guangzhou.myqcloud.com/WechatIMG104.jpeg" height="250"/> |
</HomeContent>

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -1,204 +1,232 @@
--- ---
sidebar: auto aside: left
outline: [2, 3]
--- ---
# API # API
Fes.js 统一了API的出口所有运行时API包含Fes.js内置API和插件提供的API全部通过`@fesjs/fes`导出。
Fes.js 统一了 API 的出口,所有运行时 API包含 Fes.js 内置 API 和插件提供的 API全部通过`@fesjs/fes`导出。
```js ```js
import { someApi } from "@fesjs/fes" import { someApi } from '@fesjs/fes';
``` ```
## 基础API ## 基础 API
### plugin ### plugin
::: tip ::: tip
主要在插件里面使用,项目代码中一般用不到。 主要在插件里面使用,项目代码中一般用不到。
::: :::
运行时插件接口,是 Fes.js 内置的跑在浏览器里的一套插件体系。 运行时插件接口,是 Fes.js 内置的跑在浏览器里的一套插件体系。
```js ```js
import { plugin, ApplyPluginsType } from '@fesjs/fes'; import { plugin, ApplyPluginsType } from '@fesjs/fes';
// 注册插件 // 注册插件
plugin.register({ plugin.register({
apply: { dva: { foo: 1 } }, apply: { dva: { foo: 1 } },
path: 'foo', path: 'foo',
}); });
plugin.register({ plugin.register({
apply: { dva: { bar: 1 } }, apply: { dva: { bar: 1 } },
path: 'bar', path: 'bar',
}); });
// 执行插件 // 执行插件
// 得到 { foo: 1, bar: 1 } // 得到 { foo: 1, bar: 1 }
plugin.applyPlugins({ plugin.applyPlugins({
key: 'dva', key: 'dva',
type: ApplyPluginsType.modify, type: ApplyPluginsType.modify,
initialValue: {}, initialValue: {},
args: {}, args: {},
async: false, async: false,
}); });
``` ```
#### **plugin.register** 参数包含: #### **plugin.register** 参数包含:
- apply 插件文件导出的内容
- path 插件文件路径
- apply 插件文件导出的内容
- path 插件文件路径
#### **plugin.applyPlugins** 参数包含:
- key坑位的 key
#### **plugin.applyPlugins** 参数包含: - type执行方式类型详见 [ApplyPluginsType](#applypluginstype)
- key坑位的 key - initialValue初始值
- type执行方式类型详见 [ApplyPluginsType](#applypluginstype) - args参数
- initialValue初始值 - async是否异步执行且返回 Promise
- args参数
- async是否异步执行且返回 Promise
### ApplyPluginsType ### ApplyPluginsType
::: tip ::: tip
主要在插件里面使用,项目代码中一般用不到。 主要在插件里面使用,项目代码中一般用不到。
::: :::
运行时插件执行类型enum 类型,包含三个属性: 运行时插件执行类型enum 类型,包含三个属性:
- compose用于合并执行多个函数函数可决定前序函数的执行时机
- modify用于修改值 - compose用于合并执行多个函数函数可决定前序函数的执行时机
- event用于执行事件前面没有依赖关系 - modify用于修改值
- event用于执行事件前面没有依赖关系
### defineRouteMeta ### defineRouteMeta
定义页面的元信息 定义页面的元信息
### defineBuildConfig ### defineBuildConfig
定义构建配置 定义构建配置
### defineRuntimeConfig ### defineRuntimeConfig
定义运行时配置 定义运行时配置
## 路由 API
## 路由API
Fes.js 路由基于 [Vue Router 4.0](https://next.router.vuejs.org/introduction.html),想了解更多的同学可以看看官方文档。 Fes.js 路由基于 [Vue Router 4.0](https://next.router.vuejs.org/introduction.html),想了解更多的同学可以看看官方文档。
### getRouter ### getRouter
返回当前 `router` 实例。 返回当前 `router` 实例。
```js ```js
import { getRouter } from "@fesjs/fes"; import { getRouter } from '@fesjs/fes';
const router = getRouter(); const router = getRouter();
router.push(); router.push();
``` ```
### getHistory ### getHistory
返回当前路由的History
返回当前路由的 History
### useRoute ### useRoute
返回当前 `route` 实例,相当于在模板内使用 `$route`。必须在 `setup` 函数内调用。 返回当前 `route` 实例,相当于在模板内使用 `$route`。必须在 `setup` 函数内调用。
```js ```js
import { useRoute } from "@fesjs/fes"; import { useRoute } from '@fesjs/fes';
export default { export default {
setup(){ setup() {
const route = useRoute() const route = useRoute();
} },
} };
``` ```
### useRouter ### useRouter
返回 `router` 实例,相当于在模板语法中使用 `$router`。必须在 `setup` 函数内调用。 返回 `router` 实例,相当于在模板语法中使用 `$router`。必须在 `setup` 函数内调用。
```js ```js
import { useRouter } from "@fesjs/fes"; import { useRouter } from '@fesjs/fes';
export default { export default {
setup(){ setup() {
const router = useRouter() const router = useRouter();
} },
} };
``` ```
### onBeforeRouteUpdate ### onBeforeRouteUpdate
添加导航守卫,在当前路由即将更新时触发。类似于之前的`beforeRouteUpdate`,但是可用于任何组件。卸载组件时,将移除守卫。 添加导航守卫,在当前路由即将更新时触发。类似于之前的`beforeRouteUpdate`,但是可用于任何组件。卸载组件时,将移除守卫。
```js ```js
import { onBeforeRouteUpdate } from "@fesjs/fes"; import { onBeforeRouteUpdate } from '@fesjs/fes';
export default { export default {
setup(){ setup() {
onBeforeRouteUpdate((to, from, next)=>{ onBeforeRouteUpdate((to, from, next) => {});
}) },
} };
}
``` ```
### onBeforeRouteLeave ### onBeforeRouteLeave
添加导航守卫,在当前路由即将离开时触发。类似于之前的`beforeRouteLeave`,但可用于任何组件。卸载组件时,将移除守卫。 添加导航守卫,在当前路由即将离开时触发。类似于之前的`beforeRouteLeave`,但可用于任何组件。卸载组件时,将移除守卫。
```js ```js
import { onBeforeRouteLeave } from "@fesjs/fes"; import { onBeforeRouteLeave } from '@fesjs/fes';
export default { export default {
setup(){ setup() {
onBeforeRouteLeave((to, from, next)=>{ onBeforeRouteLeave((to, from, next) => {});
}) },
} };
}
``` ```
### createWebHashHistory ### createWebHashHistory
::: tip ::: tip
在开发插件时可能用上,平时一般用不上 在开发插件时可能用上,平时一般用不上
::: :::
创建一个 hash 历史记录。对于没有主机的 web 应用程序 (例如 file://)或当配置服务器不能处理任意URL时这非常有用。注意如果 SEO 对你很重要,你应该使用 `createWebHistory` 创建一个 hash 历史记录。对于没有主机的 web 应用程序 (例如 file://),或当配置服务器不能处理任意 URL 时这非常有用。注意:如果 SEO 对你很重要,你应该使用 `createWebHistory`
### createWebHistory ### createWebHistory
::: tip ::: tip
在开发插件时可能用上,平时一般用不上 在开发插件时可能用上,平时一般用不上
::: :::
创建HTML5历史记录。单页应用程序最常见的历史记录。必须通过 http 服务打开页面地址 。 创建 HTML5 历史记录。单页应用程序最常见的历史记录。必须通过 http 服务打开页面地址 。
### createMemoryHistory ### createMemoryHistory
::: tip ::: tip
在开发插件时可能用上,平时一般用不上 在开发插件时可能用上,平时一般用不上
::: :::
创建一个基于内存的历史记录。这个历史记录的主要目的是处理 SSR。它在一个特殊的位置开始这个位置无处不在。如果用户不在浏览器上下文中它们可以通过调用 router.push() 或 router.replace() 将该位置替换为启动位置。 创建一个基于内存的历史记录。这个历史记录的主要目的是处理 SSR。它在一个特殊的位置开始这个位置无处不在。如果用户不在浏览器上下文中它们可以通过调用 router.push() 或 router.replace() 将该位置替换为启动位置。
### createRouter ### createRouter
创建一个路由器实例,该实例可用于 Vue 应用程序。查看[路由器选项](https://next.router.vuejs.org/api/#routeroptions),了解可以传递的所有属性的列表。 创建一个路由器实例,该实例可用于 Vue 应用程序。查看[路由器选项](https://next.router.vuejs.org/api/#routeroptions),了解可以传递的所有属性的列表。
### RouterLink ### RouterLink
使用自定义组件路由器链接来创建链接,而不是使用常规标签。这使得 Vue 路由器无需重新加载页面即可更改 URL、处理 URL 生成及其编码。 使用自定义组件路由器链接来创建链接,而不是使用常规标签。这使得 Vue 路由器无需重新加载页面即可更改 URL、处理 URL 生成及其编码。
```html ```html
<router-link to="/about">Go to About</router-link> <router-link to="/about">Go to About</router-link>
``` ```
可以查看[官方文档](https://next.router.vuejs.org/api/#router-link-props)了解更多 RouterLink 的 Porps。查看[官方文档](https://next.router.vuejs.org/api/#router-link-s-v-slot)了解 RouterLink 的作用域插槽。 可以查看[官方文档](https://next.router.vuejs.org/api/#router-link-props)了解更多 RouterLink 的 Porps。查看[官方文档](https://next.router.vuejs.org/api/#router-link-s-v-slot)了解 RouterLink 的作用域插槽。
### useLink ### useLink
返回的结果跟 RouterLink 的作用域插槽的属性一致,查看[官方API](https://next.router.vuejs.org/api/#router-link-s-v-slot)了解更多。
返回的结果跟 RouterLink 的作用域插槽的属性一致,查看[官方 API](https://next.router.vuejs.org/api/#router-link-s-v-slot)了解更多。
```js ```js
import { RouterLink, useLink } from '@fesjs/fes' import { RouterLink, useLink } from '@fesjs/fes';
export default { export default {
name: 'AppLink', name: 'AppLink',
props: { props: {
// add @ts-ignore if using TypeScript // add @ts-ignore if using TypeScript
...RouterLink.props, ...RouterLink.props,
inactiveClass: String, inactiveClass: String,
}, },
setup(props) { setup(props) {
// `props` contains `to` and any other prop that can be passed to <router-link> // `props` contains `to` and any other prop that can be passed to <router-link>
const { navigate, href, route, isActive, isExactActive } = useLink(props) const { navigate, href, route, isActive, isExactActive } = useLink(props);
// profit! // profit!
return { isExternalLink } return { isExternalLink };
}, },
} };
``` ```
### RouterView ### RouterView
router-view 将显示当前 URL 的对应的路由组件。你可以把它放在任何地方,以适应你的布局。 router-view 将显示当前 URL 的对应的路由组件。你可以把它放在任何地方,以适应你的布局。
```html ```html
<router-view></router-view> <router-view></router-view>
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<component :is="Component" /> <component :is="Component" />
</router-view> </router-view>
``` ```
可以查看[官方文档](https://next.router.vuejs.org/api/#router-view-props)了解更多 RouterView 的 Porps。查看[官方文档](https://next.router.vuejs.org/api/#router-view-s-v-slot)了解 RouterView 的作用域插槽。 可以查看[官方文档](https://next.router.vuejs.org/api/#router-view-props)了解更多 RouterView 的 Porps。查看[官方文档](https://next.router.vuejs.org/api/#router-view-s-v-slot)了解 RouterView 的作用域插槽。
### 其他 Router Methods ### 其他 Router Methods
查看[vue-router 官方文档](https://next.router.vuejs.org/api/#router-methods)了解更多。
查看[vue-router 官方文档](https://next.router.vuejs.org/api/#router-methods)了解更多。

View File

@ -1,5 +1,6 @@
--- ---
sidebar: auto aside: left
outline: [2, 3]
--- ---
# 命令行工具 # 命令行工具
@ -19,10 +20,10 @@ Options:
``` ```
可以在本机安装后使用: 可以在本机安装后使用:
<CodeGroup>
<CodeGroupItem title="PNPM" active>
```bash ::: code-group
```bash [pnpm]
# 全局安装 # 全局安装
pnpm global add @fesjs/create-fes-app pnpm global add @fesjs/create-fes-app
@ -30,11 +31,7 @@ pnpm global add @fesjs/create-fes-app
create-fes-app fes-app create-fes-app fes-app
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 全局安装 # 全局安装
npm i -g @fesjs/create-fes-app npm i -g @fesjs/create-fes-app
@ -42,15 +39,13 @@ npm i -g @fesjs/create-fes-app
create-fes-app fes-app create-fes-app fes-app
``` ```
</CodeGroupItem> :::
</CodeGroup>
推荐使用 `pnpm create``npx` 方式创建模板,一直使用最新的模板: 推荐使用 `pnpm create``npx` 方式创建模板,一直使用最新的模板:
<CodeGroup> ::: code-group
<CodeGroupItem title="PNPM" active>
```bash ```bash [pnpm]
# 创建模板 # 创建模板
pnpm create @fesjs/fes-app myapp pnpm create @fesjs/fes-app myapp
@ -61,11 +56,7 @@ pnpm i
pnpm dev pnpm dev
``` ```
</CodeGroupItem> ```bash [npm]
<CodeGroupItem title="NPM">
```bash
# 创建模板 # 创建模板
npx @fesjs/create-fes-app myapp npx @fesjs/create-fes-app myapp
@ -76,8 +67,7 @@ npm install
npm run dev npm run dev
``` ```
</CodeGroupItem> :::
</CodeGroup>
## fes ## fes

View File

@ -1,5 +1,6 @@
--- ---
sidebar: auto aside: left
outline: [2, 3]
--- ---
## 配置文件 ## 配置文件

View File

@ -1,28 +0,0 @@
# 介绍
## 插件列表
| 插件 | 介绍 |
| ---- | ---- |
| [@fesjs/plugin-access](./plugins/access.md) | 提供对页面资源的权限控制能力 |
| [@fesjs/plugin-enums](./plugins/enums.md) | 提供统一的枚举存取及丰富的函数来处理枚举 |
| [@fesjs/plugin-icon](./plugins/icon.md) | svg 文件自动注册为组件 |
| [@fesjs/plugin-jest](./plugins/jest.md) | 基于 `Jest`,提供单元测试、覆盖测试能力 |
| [@fesjs/plugin-layout](./plugins/layout.md) | 简单的配置即可拥有布局,包括导航以及侧边栏 |
| [@fesjs/plugin-locale](./plugins/locale.md) | 基于 `Vue I18n`,提供国际化能力 |
| [@fesjs/plugin-model](./plugins/model.md) | 简易的数据管理方案 |
| [@fesjs/plugin-request](./plugins/request.md) | 基于 `Axios` 封装的 request内置防止重复请求、请求节流、错误处理等功能 |
| [@fesjs/plugin-vuex](./plugins/vuex.md) | 基于 `Vuex`, 提供状态管理能力 |
| [@fesjs/plugin-qiankun](./plugins/qiankun.md) | 基于 `qiankun`,提供微服务能力 |
| [@fesjs/plugin-sass](./plugins/sass.md) | 样式支持sass |
| [@fesjs/plugin-monaco-editor](./plugins/editor.md) | 提供代码编辑器能力, 基于`monaco-editor`VS Code使用的代码编辑器 |
| [@fesjs/plugin-windicss](./plugins/windicss.md) | 基于 `windicss`,提供原子化 CSS 能力 |
| [@fesjs/plugin-pinia](./plugins/pinia.md) | 基于 `pinia`,提供状态管理 |
| [@fesjs/plugin-watermark](./plugins/watermark.md) | 水印 |
| [@fesjs/plugin-swc](./plugins/swc.md) | swc |
## 架构
<!-- ![架构](/framework.png "架构") -->
<img :src="$withBase('framework.png')" alt="架构">
Fes.js 把大家常用的技术栈封装成一个个插件进行整理,收敛到一起,让大家只用 Fes.js 就可以完成 80% 的日常工作。

View File

@ -0,0 +1,33 @@
# 介绍
<script setup>
import { withBase } from 'vitepress'
</script>
## 插件列表
| 插件 | 介绍 |
| -------------------------------------------------- | ----------------------------------------------------------------------- |
| [@fesjs/plugin-access](./plugins/access.md) | 提供对页面资源的权限控制能力 |
| [@fesjs/plugin-enums](./plugins/enums.md) | 提供统一的枚举存取及丰富的函数来处理枚举 |
| [@fesjs/plugin-icon](./plugins/icon.md) | svg 文件自动注册为组件 |
| [@fesjs/plugin-jest](./plugins/jest.md) | 基于 `Jest`,提供单元测试、覆盖测试能力 |
| [@fesjs/plugin-layout](./plugins/layout.md) | 简单的配置即可拥有布局,包括导航以及侧边栏 |
| [@fesjs/plugin-locale](./plugins/locale.md) | 基于 `Vue I18n`,提供国际化能力 |
| [@fesjs/plugin-model](./plugins/model.md) | 简易的数据管理方案 |
| [@fesjs/plugin-request](./plugins/request.md) | 基于 `Axios` 封装的 request内置防止重复请求、请求节流、错误处理等功能 |
| [@fesjs/plugin-vuex](./plugins/vuex.md) | 基于 `Vuex`, 提供状态管理能力 |
| [@fesjs/plugin-qiankun](./plugins/qiankun.md) | 基于 `qiankun`,提供微服务能力 |
| [@fesjs/plugin-sass](./plugins/sass.md) | 样式支持 sass |
| [@fesjs/plugin-monaco-editor](./plugins/editor.md) | 提供代码编辑器能力, 基于`monaco-editor`VS Code 使用的代码编辑器) |
| [@fesjs/plugin-windicss](./plugins/windicss.md) | 基于 `windicss`,提供原子化 CSS 能力 |
| [@fesjs/plugin-pinia](./plugins/pinia.md) | 基于 `pinia`,提供状态管理 |
| [@fesjs/plugin-watermark](./plugins/watermark.md) | 水印 |
| [@fesjs/plugin-swc](./plugins/swc.md) | swc |
## 架构
<!-- ![架构](/framework.png "架构") -->
<img :src="withBase('framework.png')" alt="架构">
Fes.js 把大家常用的技术栈封装成一个个插件进行整理,收敛到一起,让大家只用 Fes.js 就可以完成 80% 的日常工作。

View File

@ -1,3 +1,7 @@
<script setup>
import { withBase } from 'vitepress'
</script>
# @fesjs/plugin-layout # @fesjs/plugin-layout
## 介绍 ## 介绍
@ -35,22 +39,22 @@
### side ### side
<!-- ![side](/side.png) --> <!-- ![side](/side.png) -->
<img :src="$withBase('side.png')" alt="side"> <img :src="withBase('side.png')" alt="side">
### top ### top
<!-- ![top](/top.png) --> <!-- ![top](/top.png) -->
<img :src="$withBase('top.png')" alt="top"> <img :src="withBase('top.png')" alt="top">
### mixin ### mixin
<!-- ![mixin](/mixin.png) --> <!-- ![mixin](/mixin.png) -->
<img :src="$withBase('mixin.png')" alt="mixin"> <img :src="withBase('mixin.png')" alt="mixin">
### left-right ### left-right
<!-- ![mixin](/mixin.png) --> <!-- ![mixin](/mixin.png) -->
<img :src="$withBase('left-right.png')" alt="left-right"> <img :src="withBase('left-right.png')" alt="left-right">
### 页面个性化 ### 页面个性化

View File

@ -1,4 +1,4 @@
{ {
"extends": "../tsconfig.base.json", "extends": "../tsconfig.base.json",
"include": [".vuepress/**/*"] "include": [".vitepress/**/*"]
} }

View File

@ -13,9 +13,9 @@
"build": "node scripts/build.mjs", "build": "node scripts/build.mjs",
"release": "node scripts/release.mjs", "release": "node scripts/release.mjs",
"clean": "rm -rf ./node_modules & rm -rf packages/**/node_modules & rm -rf packages/**/.cache", "clean": "rm -rf ./node_modules & rm -rf packages/**/node_modules & rm -rf packages/**/.cache",
"docs:dev": "vuepress dev docs --clean-cache", "docs:dev": "vitepress dev docs",
"docs:build": "vuepress build docs --clean-cache", "docs:build": "vitepress build docs",
"docs:build-pages": "BASE=fes.js vuepress build docs --clean-cache", "docs:build-pages": "BASE=fes.js vitepress build docs",
"test": "fes test", "test": "fes test",
"lint": "eslint -c ./.eslintrc.js --ignore-pattern='templates' --ext .js,.jsx,.vue,.ts", "lint": "eslint -c ./.eslintrc.js --ignore-pattern='templates' --ext .js,.jsx,.vue,.ts",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
@ -34,18 +34,12 @@
"enquirer": "^2.3.6", "enquirer": "^2.3.6",
"execa": "^6.1.0", "execa": "^6.1.0",
"minimist": "^1.2.6", "minimist": "^1.2.6",
"semver": "^7.3.6", "semver": "^7.3.6"
"vuepress": "2.0.0-beta.53"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.21.3",
"@babel/preset-env": "^7.20.2",
"@commitlint/cli": "^11.0.0", "@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0", "@commitlint/config-conventional": "^11.0.0",
"@vuepress/plugin-back-to-top": "2.0.0-beta.53", "@vite-pwa/vitepress": "^0.0.5",
"@vuepress/plugin-docsearch": "2.0.0-beta.53",
"@vuepress/plugin-pwa": "2.0.0-beta.53",
"@vuepress/plugin-pwa-popup": "2.0.0-beta.53",
"@webank/eslint-config-webank": "1.2.7", "@webank/eslint-config-webank": "1.2.7",
"chokidar": "^3.5.2", "chokidar": "^3.5.2",
"commitizen": "^4.2.1", "commitizen": "^4.2.1",
@ -54,8 +48,9 @@
"fs-extra": "^11.1.1", "fs-extra": "^11.1.1",
"husky": "^8.0.3", "husky": "^8.0.3",
"lint-staged": "^13.2.0", "lint-staged": "^13.2.0",
"postcss": "^8.4.21", "vite-plugin-pwa": "^0.14.7",
"postcss-loader": "^7.1.0", "vitepress": "1.0.0-alpha.73",
"vue": "^3.2.47",
"yargs-parser": "^21.1.1" "yargs-parser": "^21.1.1"
}, },
"lint-staged": { "lint-staged": {
@ -74,4 +69,4 @@
"path": "./node_modules/cz-conventional-changelog" "path": "./node_modules/cz-conventional-changelog"
} }
} }
} }

View File

@ -36,6 +36,7 @@
"@babel/preset-typescript": "^7.21.0", "@babel/preset-typescript": "^7.21.0",
"@fesjs/utils": "^3.0.0", "@fesjs/utils": "^3.0.0",
"@vue/babel-plugin-jsx": "^1.1.1", "@vue/babel-plugin-jsx": "^1.1.1",
"ajv": "^8.12.0",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"babel-loader": "^9.1.2", "babel-loader": "^9.1.2",
"cli-highlight": "^2.1.4", "cli-highlight": "^2.1.4",

View File

@ -33,12 +33,13 @@
"@fesjs/fes": "^3.0.0" "@fesjs/fes": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.21.3",
"@babel/preset-env": "^7.15.0", "@babel/preset-env": "^7.15.0",
"@vue/babel-plugin-jsx": "^1.0.6", "@vue/babel-plugin-jsx": "^1.0.6",
"babel-jest": "^27.0.6", "babel-jest": "^27.0.6",
"jest": "^27.0.6", "jest": "^27.0.6",
"jest-transform-stub": "^2.0.0", "jest-transform-stub": "^2.0.0",
"jest-watch-typeahead": "^0.6.1", "jest-watch-typeahead": "^2.2.2",
"ts-jest": "^27.0.4", "ts-jest": "^27.0.4",
"typescript": "^4.9.0", "typescript": "^4.9.0",
"vue3-jest": "^27.0.0-alpha.1" "vue3-jest": "^27.0.0-alpha.1"

View File

@ -43,10 +43,10 @@
"access": "public" "access": "public"
}, },
"dependencies": { "dependencies": {
"@fesjs/fes-design": "^0.7.0",
"@fesjs/builder-vite": "workspace:*", "@fesjs/builder-vite": "workspace:*",
"@fesjs/builder-webpack": "workspace:*", "@fesjs/builder-webpack": "workspace:*",
"@fesjs/fes": "workspace:*", "@fesjs/fes": "workspace:*",
"@fesjs/fes-design": "^0.7.0",
"@fesjs/plugin-access": "workspace:*", "@fesjs/plugin-access": "workspace:*",
"@fesjs/plugin-enums": "workspace:*", "@fesjs/plugin-enums": "workspace:*",
"@fesjs/plugin-icon": "workspace:*", "@fesjs/plugin-icon": "workspace:*",
@ -59,7 +59,6 @@
"@fesjs/plugin-request": "workspace:*", "@fesjs/plugin-request": "workspace:*",
"@fesjs/plugin-sass": "workspace:*", "@fesjs/plugin-sass": "workspace:*",
"core-js": "^3.29.1", "core-js": "^3.29.1",
"cssnano": "^6.0.0",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"vue": "^3.2.47" "vue": "^3.2.47"
}, },

View File

@ -1,7 +0,0 @@
module.exports = {
plugins: [
require('cssnano')({
preset: 'default',
}),
],
};

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
// vetur.config.js
/** @type {import('vls').VeturConfig} */
module.exports = {
// **optional** default: `{}`
// override vscode settings
// Notice: It only affects the settings used by Vetur.
settings: {
'vetur.useWorkspaceDependencies': true,
'vetur.experimental.templateInterpolationService': true
},
// **optional** default: `[{ root: './' }]`
// support monorepos
projects: [
'./packages/fes-template' // shorthand for only root
]
};