theme: channing-cyan
前言
在大前端的工程化趋势下,自动化也成为前端不可分离的一部分,自动化为我们日常开发中提高了不少效率且能少码不少代码,单配置一个json文件就可以生成一系列想要的代码是开发者的终极目标,本章将基于react讲述如何通过json文件生成对应路由。
准备工作
在开始之前,先检查一下你的版本(我是基于react的,vue的也是一样):
- react >= 16
- npm <= 11 (题主的是10.15.3)
- gulp 3.9.1(3. )
由于高版本的node会与我当前gulp的版本会有冲突,所以务必确保npm版本要低于11,可以使用nvm进行node的版本管 理确保你可以自由的切换node版本。
路由书写
一般我们书写react路由通过react-router-dom提供的方法来书写,并且配备一些懒加载等优化处理。
代码语言:javascript复制import React, { Suspense, lazy } from "react";
import { Route, Switch } from "react-router-dom";
const loading = true;
const router = (
<Suspense fallback={loading}>
<Switch>
<Route
path="/operator/list"
exact
component={lazy(() =>
import("../view/operator/list/app")
)}
/>
</Switch>
</Suspense>
)
如上,后续有新增路由,在后面继续新增即可,但当路由数目较多时候,我们所做的重复性操作就有些频繁。当重复操作过多的时候,就适合使用自动化让项目变得灵活一些。
自动生成路由
利用glup以及glup-rename来完成我们的自动化生成,实际上node也可以来完成,node作为前端工具来说是相当不错的,但我们这里主要叙述利用glup来完成。
在开始之前,首先我们要定义好必要的模板,比如主页、404页等等。
代码语言:javascript复制// 定义路由模板
const routerTemplates = `
import React, { Suspense, lazy } from 'react'
import { Route, Switch } from 'react-router-dom'
const Home = lazy(() => import('../view/home/app'))
const NoMatch = lazy(() => import('../view/error/404.jsx'))
const loading = true
{$$ImportComponent$}
const router = (
<Suspense fallback={loading}>
<Switch>
{$$SubRoutes
<Route path="/" exact$} component={Home}/>
<Route path="*" component={NoMatch}/>
</Switch >
</Suspense>
)
export default router
`
// 定义生成路由占位
const subRouteTemplate = `
<Route path="{$$route$}" exact component={lazy(() => import('../view{$$path$}/app'))}/>
`
// 定义要解析的json
const MENUS_PATH = './src/static/app/js/route/menus.json'
// 定义输出目录
const MUNUS_DEST_PATH = './src/static/app/js/route/'
定义好模板后,我们利用through2来处理流,以及占位符来替换掉我们想要的路由。
代码语言:javascript复制const through = require('through2')
function generateRoutes() {
const subLoader = []
const subRoutes = []
return through.obj((file, enc, cb) => {
const list = JSON.parse(file.contents.toString())
list.map((menu) => {
menu.items.map((item) => {
item.routes.map((route) => {
subRoutes.push(
subRouteTemplate
.replace('{$$route$}', route.route)
.replace('{$$name$}', route.name)
.replace('{$$path$}', route.path)
)
})
})
})
const final = routerTemplates
.replace('{$$ImportComponent$}', subLoader.join(''))
.replace('{$$SubRoutes$}', subRoutes.join(''))
file.contents = Buffer.from(final)
return cb(null, file)
})
}
最后我们利用glup来定义任务,即可通过命令执行自动生成路由。
代码语言:javascript复制gulp.task('generate-routes', () => {
return gulp
.src(MENUS_PATH)
.pipe(generateRoutes())
.pipe(rename('routes.jsx'))
.pipe(gulp.dest(MUNUS_DEST_PATH))
})
完整代码:
代码语言:javascript复制/* eslint-disable array-callback-return */
const gulp = require('gulp')
const through = require('through2')
const rename = require('gulp-rename')
const MENUS_PATH = './src/static/app/js/route/menus.json'
const MUNUS_DEST_PATH = './src/static/app/js/route/'
const routerTemplates = `
import React, { Suspense, lazy } from 'react'
import { Route, Switch } from 'react-router-dom'
const Home = lazy(() => import('../view/home/app'))
const NoMatch = lazy(() => import('../view/error/404.jsx'))
const loading = true
{$$ImportComponent$}
const router = (
<Suspense fallback={loading}>
<Switch>
{$$SubRoutes
<Route path="/" exact$} component={Home}/>
<Route path="*" component={NoMatch}/>
</Switch >
</Suspense>
)
export default router
`
const subRouteTemplate = `
<Route path="{$$route$}" exact component={lazy(() => import('../view{$$path$}/app'))}/>
`
function generateRoutes() {
const subLoader = []
const subRoutes = []
return through.obj((file, enc, cb) => {
const list = JSON.parse(file.contents.toString())
list.map((menu) => {
menu.items.map((item) => {
item.routes.map((route) => {
subRoutes.push(
subRouteTemplate
.replace('{$$route$}', route.route)
.replace('{$$name$}', route.name)
.replace('{$$path$}', route.path)
)
})
})
})
const final = routerTemplates
.replace('{$$ImportComponent$}', subLoader.join(''))
.replace('{$$SubRoutes$}', subRoutes.join(''))
// eslint-disable-next-line no-param-reassign
file.contents = Buffer.from(final)
return cb(null, file)
})
}
gulp.task('generate-routes', () => {
return gulp
.src(MENUS_PATH)
.pipe(generateRoutes())
.pipe(rename('routes.jsx'))
.pipe(gulp.dest(MUNUS_DEST_PATH))
})
配置路由的json文件:
代码语言:javascript复制[
{
"text": "管理系统",
"key": "mng",
"items": [
{
"key": "operator",
"text": "运营商",
"routes": [
{
"title": "商品管理",
"name": "product_mng",
"route": "/operator/product/list",
"path": "/operator/product/product_mng/list"
}
]
}
]
}
]
之后在控制台执行命令generate-routes即可生成路由。
最后
类似的方法也不止这一种,也可以使用node的读写流进行操作,webpack也有提供获取上下文的api,如require.context等。
如果文章对你有帮助,还望不吝三连~