From 930541e7265602e37d07deb2b7b576e619078a58 Mon Sep 17 00:00:00 2001 From: harrywan <445436867@qq.com> Date: Wed, 9 Mar 2022 10:27:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A1=B5=E9=9D=A2=E6=94=AF=E6=8C=81tsx?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E4=BE=9BdefineRoute=E9=85=8D=E7=BD=AEtsx?= =?UTF-8?q?=E5=92=8Cjsx=E7=9A=84route=20(#106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 页面支持tsx,提供defineRoute配置tsx和jsx的route * .vue文件也支持defineRouteMeta * feat: 改回声明用法 --- .../src/plugins/misc/route/index.js | 44 ++++++++++++---- .../plugins/misc/route/template/routes.tpl | 4 ++ packages/fes-template-h5/src/pages/index.vue | 50 ++++++++++++------- .../fes-template-h5/src/pages/onepiece.vue | 2 +- packages/fes-template-h5/src/pages/test.jsx | 7 --- packages/fes-template-h5/src/pages/test.tsx | 15 ++++++ packages/fes-utils/package.json | 1 + packages/fes-utils/src/index.js | 4 +- packages/fes/types.d.ts | 7 ++- 9 files changed, 96 insertions(+), 38 deletions(-) delete mode 100644 packages/fes-template-h5/src/pages/test.jsx create mode 100644 packages/fes-template-h5/src/pages/test.tsx diff --git a/packages/fes-preset-built-in/src/plugins/misc/route/index.js b/packages/fes-preset-built-in/src/plugins/misc/route/index.js index 272d662e..f963cb00 100644 --- a/packages/fes-preset-built-in/src/plugins/misc/route/index.js +++ b/packages/fes-preset-built-in/src/plugins/misc/route/index.js @@ -2,7 +2,7 @@ import { readdirSync, statSync, readFileSync } from 'fs'; import { join, extname, posix, basename } from 'path'; -import { lodash } from '@fesjs/utils'; +import { lodash, parser, generator } from '@fesjs/utils'; import { parse } from '@vue/compiler-sfc'; import { Logger } from '@fesjs/compiler'; import { runtimePath } from '../../../utils/constants'; @@ -21,7 +21,7 @@ const logger = new Logger('fes:router'); const isProcessFile = function (path) { const ext = extname(path); - return statSync(path).isFile() && ['.vue', '.jsx'].includes(ext); + return statSync(path).isFile() && ['.vue', '.jsx', '.tsx'].includes(ext); }; const isProcessDirectory = function (path, item) { @@ -71,6 +71,19 @@ const getRoutePath = function (parentRoutePath, fileName) { return posix.join(parentRoutePath, fileName); }; +function getRouteMeta(content) { + const ast = parser.parse(content, { + sourceType: 'module', + plugins: ['jsx', 'typescript'] + }); + const defineRouteExpression = ast.program.body.filter(expression => expression.type === 'ExpressionStatement' && expression.expression.type === 'CallExpression' && expression.expression.callee.name === 'defineRouteMeta')[0]; + if (defineRouteExpression) { + const argument = generator(defineRouteExpression.expression.arguments[0]); + return JSON.parse(argument.code.replace(/'/g, '"').replace(/(\S+):/g, (global, m1) => `"${m1}":`)); + } + return null; +} + let cacheGenRoutes = {}; // TODO 约定 layout 目录作为布局文件夹, @@ -88,16 +101,12 @@ const genRoutes = function (parentRoutes, path, parentRoutePath, config) { // 文件或者目录的绝对路径 const component = join(path, item); if (isProcessFile(component)) { - const { descriptor } = parse(readFileSync(component, 'utf-8')); - const routeMetaBlock = descriptor.customBlocks.find( - b => b.type === 'config' - ); const ext = extname(item); const fileName = basename(item, ext); // 路由的path const routePath = getRoutePath(parentRoutePath, fileName); if (cacheGenRoutes[routePath]) { - logger.warn(`[WARNING]: The file path: ${routePath}(.jsx/.vue) conflict in router,will only use ${routePath}.jsx,please remove one of.`); + logger.warn(`[WARNING]: The file path: ${routePath}(.jsx/.tsx/.vue) conflict in router,will only use ${routePath}.tsx or ${routePath}.jsx,please remove one of.`); return; } cacheGenRoutes[routePath] = true; @@ -105,7 +114,24 @@ const genRoutes = function (parentRoutes, path, parentRoutePath, config) { // 路由名称 const routeName = getRouteName(parentRoutePath, fileName); const componentPath = getComponentPath(parentRoutePath, fileName, config); - const routeMeta = routeMetaBlock?.content ? JSON.parse(routeMetaBlock.content) : {}; + + let content = readFileSync(component, 'utf-8'); + let routeMeta = {}; + if (ext === '.vue') { + const { descriptor } = parse(content); + const routeMetaBlock = descriptor.customBlocks.find( + b => b.type === 'config' + ); + routeMeta = routeMetaBlock?.content ? JSON.parse(routeMetaBlock.content) : {}; + if (descriptor.script) { + content = descriptor.script.content; + routeMeta = getRouteMeta(content) || routeMeta; + } + } + if (ext === '.jsx' || ext === '.tsx') { + routeMeta = getRouteMeta(content) || {}; + } + const routeConfig = { path: routePath, component: componentPath, @@ -302,7 +328,7 @@ export default function (api) { api.addCoreExports(() => [ { - specifiers: ['getRoutes', 'getRouter', 'getHistory', 'destroyRouter'], + specifiers: ['getRoutes', 'getRouter', 'getHistory', 'destroyRouter', 'defineRouteMeta'], source: absCoreFilePath } ]); diff --git a/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl b/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl index e6a6c6aa..6d2083d4 100644 --- a/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl +++ b/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl @@ -60,3 +60,7 @@ export const destroyRouter = ()=>{ router = null; history = null; } + +export const defineRouteMeta = (param)=>{ + return param +} diff --git a/packages/fes-template-h5/src/pages/index.vue b/packages/fes-template-h5/src/pages/index.vue index 8cf4ebc3..7d6479dc 100644 --- a/packages/fes-template-h5/src/pages/index.vue +++ b/packages/fes-template-h5/src/pages/index.vue @@ -1,26 +1,30 @@ - -{ - "title": "首页", - "name": "testIndex", - "layout": "false" -} - diff --git a/packages/fes-template-h5/src/pages/onepiece.vue b/packages/fes-template-h5/src/pages/onepiece.vue index bcf8dafd..e8c335c6 100644 --- a/packages/fes-template-h5/src/pages/onepiece.vue +++ b/packages/fes-template-h5/src/pages/onepiece.vue @@ -5,7 +5,7 @@ { "title": "onepiece", - "layout": "true" + "layout": true }