tossjs v0.0.23
Tossjs
灵智数科 React 脚手架和基础运行库,主要服务于管理端/中台项目,包含一些实用型的脚本命令和通用的运行时功能。
Toss 折腾的意思
1. 核心概念和功能说明
1.1 应用
分为根应用和子应用,根应用提供和业务相关联的基础模块,例如侧边栏、顶栏等,子应用则是独立于框架与根应用的模块,但是其运行依赖于框架和根应用,类似于 exe 应用和 windows 系统的关系。
可以通过toss.apps.js
来配置子应用(下文3.3的示例),通过脚本工具toss update-apps
来更新子应用
1.2 服务
无论根应用还是子应用,都有许多需要与后端接口进行数据交互的地方,这些交互在框架中被定义为对服务的调用,其本质是对叶峰的createRequest
机制的封装和完善。
服务定义规则
通过键值对对象的方式进行服务定义,其中键是服务名,值则是服务对应的接口地址、请求方式以及传参规则的组合:
{ '<SERVICE_NAME>': '[METHOD] <API_URL>[?param=:value]' }
其中METHOD
表示请求的方式,默认为POST
,以下是示例:
module.exports = {
'common.getProductList': 'GET /api/ms-product-backend/products/tree?category=:id',
'common.updateProduct': '/api/ms-product-backend/products/update',
// ... 更多服务定义
}
根应用的服务定义
在根应用中,可以在src/services/
目录中进行服务定义,例如:
// src/services/common.js
// 服务配置文件会被node脚本工具处理,为此不能直接使用ES6的export default方式来导出
module.exports = {
'common.getCityTree': 'GET /api/ms-base-backend/city/tree',
'common.downloadTemplate': 'GET /api/ms-base-backend/template/download?templatId=:templateId',
}
src/services/
目录下面的所有 js 文件都会被认为是服务配置文件,请不要在此目录下放置其他的文件
子应用的服务定义
在子应用根目录下面的services.js
中进行服务的定义,例如:
// src/pages/marketing/services.js
module.exports = {
'marketing.getCoupons': 'GET /api/ms-marketing-backend/product/list',
}
不同子应用的服务名,务必加上不同的前缀以避免冲突,多个子应用公用的服务,最好也放到根应用的服务定义中去
框架会适时读取所有的服务定义文件并汇总成生成到src/.services.js
中,例如启动 Dev Server 之后和进行构建之前,以及启动 Dev Server 之后监听到任何服务定义文件有变化的时候,也可以手动执行npm run update-services
来进行更新(需要参考后文配置 npm scripts)。
服务的调用
通过toss.request
中的requestService
方法来调用服务:
import { requestService } from 'toss.request'
// 发起一个正常的请求
requestService('marketing.getCoupons', { page: 1, pageSize: 10 }).then(response => {
console.log(response)
})
// 下载文件
requestService.download('common.downloadTemplate', {}, { templateId: 'xxx' })
1.3 路由
框架中运行的不同应用,需要通过不同的路由地址进行访问。默认情况下,在启动 Dev Server 之后,框架会监听所有子应用目录的变化,自动生成一级路由声明文件提供给根应用使用,如果需要对子应用的子路由进行更详细的配置,则需要在子应用的根目录创建一个route.js
文件,以下是示例:
// src/pages/marketing/route.js
module.exports = {
name: 'marketing',
path: '/marketing',
entry: 'pages/marketing/index.jsx', // 子应用根路由入口文件
local: true, // local为true时,框架会将子路由声明生成为子应用根目录下的route.jsx,需要子应用可以自行引入处理,local为false时,子路由声明也会合并到根应用中去
children: [
{
name: 'marketingCoupon',
path: '/coupon',
entry: 'pages/marketing/pages/coupon/index.jsx',
exact: true,
},
{
name: 'marketingCouponData',
path: '/coupon-data',
entry: 'pages/marketing/pages/couponData/index.jsx',
exact: true,
},
],
}
1.4 国际化
框架摒弃了之前基于react-intl
的国际化方案,因为配置繁琐,而且实时切换语言的需求场景实际上也很少:
在现有方案中,在需要显示文字的地方使用lang
这个全局函数即可,示例:
// 显示纯字符串
console.log(lang('你好啊!'))
// > 你好啊!
// 显示包含动态数据的字符串
console.log(lang('{name},你好啊!', { name: '曾祥瑞' }))
// > 曾祥瑞,你好啊!
后续会提完善的工具来协助创建完整的语言配置文件。
2. 框架结构与说明
tossjs/
- runtime/ # 运行库目录
- action
- assets
- components
- helpers
- history
- service
- store
- utils
- scripts/ # 脚本目录
- build
- plugins
- tools
- utils
- cli.js
- index.js
对于 runtime 目录中的模块,都可以通过toss.{模块名}
来引用,例如:
import action from 'toss.action'
import BasePage from 'toss.components/BasePage'
import broadcast from 'toss.helpers/broadcast'
import baseUtils from 'toss.utils/base'
import { requestService } from 'toss.service'
// 也可以使用下列语法来引入单个的component/helper/util
import { Loading } from 'toss.components'
import { storage } from 'toss.helpers'
import { validate, request } from 'toss.utils'
3. 使用方式
3.1 新建一个项目作为根应用,结构如下:
project/
- src/
- pages/
- templates/
- index.ejs
- index.jsx
3.2 执行npm init
初始化package.json
文件,
project/
- src/
- pages/
- templates/
- index.ejs
- index.jsx
- package.json
3.3 执行npm install tossjs
安装tossjs
,然后创建 配置文件:toss.app.js
和toss.config.js
project/
- src/
- pages/
- templates/
- index.ejs
- index.jsx
- package.json
- toss.app.js
- toss.config.js
toss.app.js
文件示例:
// 定义所有可用的子应用
const apps = {
app1: {
name: '应用1',
dir: 'src/pages/app1',
repo: 'http://gitlab.xxx.com/app1.git',
},
app2: {
name: '应用2',
dir: 'src/pages/app2',
repo: 'http://gitlab.xxx.com/app2.git',
},
// ... 更多子应用配置
}
// 定义不同环境用到的子应用,其中配置的具体规则是`{APP_NAME}@{BRANCH_NAME}`
// 这个环境配置的用处,会在后文说明
const env = {
default: ['app1@dev'], // 默认配置
dev: ['app1@dev', 'app2@dev'], // 开发环境配置
test: ['app1@test', 'app2@test'], // 测试环境配置
uat: ['app1@pre_release', 'app2@pre_release'], // 预演环境配置
prod: ['app1@master', 'app2@master'], // 生产环境配置
}
// 导出配置对象
module.exports = { apps, env }
toss.config.js
文件示例:
module.exports = {
// 子应用所在的目录
subAppsFolder: 'src/pages',
// 路由相关的配置
route: {
// 根路由跳转路径,直接访问/会跳转至/welcome
indexRedirect: 'welcome',
// 路由文件生产路径
output: 'src/.routes.jsx',
// 是否监听文件变化自动更新路由
watch: true,
},
// 全局变量配置
globalVars: {
// JS全局变量配置,可以通过window.__TOSS_GLOBAL__来访问这里设置的值
js: {
publicPathPrefix: '/test',
},
// SCSS全局变量配置,所有SCSS文件都可以访问到在这里定义的变量
scss: {
publicPathPrefix: '/test',
},
},
// webpack构建配置
build: {
// html模板文件路径
htmlTemplate: './src/templates/index.ejs',
// 基础的webpack配置,可以在此处扩展loader等,参考webpack配置手册
base: {},
// webpack开发配置,例如devServer等,参考webpack配置手册
dev: {},
// webpack打包配置,参考webpack配置手册
prod: {},
// webpack dll配置,参考webpack dll配置手册
dll: {},
// babel配置文件,可以扩展babel插件等,参考babel配置手册
babel: {},
},
}
3.4 在package.json
的script
字段中加入自定义脚本配置:
"scripts": {
"start": "toss start",
"build": "toss build",
"build:dev": "toss build --env=dev",
"build:test": "toss build --env=test",
"build:uat": "toss build --env=uat",
"build:prod": "toss build --env=prod",
"build:dll": "toss build-dll",
"update-apps": "toss update apps",
"update-apps:dev": "toss update apps --env=dev",
"update-apps:test": "toss update apps --env=test",
"update-apps:uat": "toss update apps --env=uat",
"update-apps:prod": "toss update apps --env=prod",
"update-routes": "toss update routes",
"update-services": "toss update services",
},
脚本说明:
- start 启动开发环境配置,在非 windows 环境中,可以通过
npm start -- --dashboard
来启动一个带有友好交互形式的构建窗口 - build 执行打包操作
- build:{ENV} 先更新指定环境的子应用,再执行打包
- update-apps 更新默认环境的子应用,或者通过
npm run update-apps app1@dev app2@master
来更新指定的子应用到指定分支 - update-apps:{ENV} 更新指定环境的子应用
- update-routes 更新路由配置
- update-services 更新服务配置
3.5 完善src/templates/index.ejs
内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="expires" content="0" />
<title>Tenon Test</title>
</head>
<body>
<script>
//
window.__TOSS_GLOBAL__ = <%= JSON.stringify(htmlWebpackPlugin.options.globalVars.js) %>
</script>
<div id="root" class="site-container">
<div id="container"></div>
</div>
</body>
</html>
3.6 完善src/index.jsx
内容:
import React from 'react'
import { render } from 'react-dom'
import TossEntry from 'toss.entry'
import AppRoutes from '.routes.jsx'
const RootRoute = props => {
return <AppRoutes match={props.match} />
}
render(
<TossEntry basename="/admin">
<RootRoute />
</TossEntry>,
document.getElementById('root')
)
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago