挑战21天手写前端框架 day13 解析用户配置文件,将框架行为交到用户手里

简介: 挑战21天手写前端框架 day13 解析用户配置文件,将框架行为交到用户手里

image.png


阅读本文需要 5 分钟,编写本文耗时 1 小时


到目前为止,我们的框架行为都是由我们的设计开发时制定的,但是实际项目中肯定会涉及到用户需要定制化的一些数据和定制化需求,由于我们并不是要写一个真正的前端框架,因此我们还是以管控能力为主,尽量将最少的配置能力给到用户。尽量只让用户配置一些框架无关的信息和数据,这将意味着用户需要知道的前端工程化的东西非常的少。借此来提升本次框架的用户开发体验。即整个项目技术栈的选择,都有框架设计统一制定。其实这个思路非常适合用在公司内部团队中构建的框架方案中。


首先依旧随便约定一个配置文件的名字 malita.config.ts 然后将它放到根目录下,然后我们还是用昨天构建“生命周期函数”的方式,增加一个生命周期,getUserConfig


比如就按住我们昨天留下的两个配置需求将真正的 keepalive 需求,传递到 中,使用用户配置 title 作为页面 dom 的title。

export default {
    title: 'Hello',
    keepalive: [/./]
}
复制代码


然后我们尝试着将它引入到我们的框架中,

import { existsSync } from 'fs';
import path from 'path';
import type { AppData } from './appData';
import { DEFAULT_CONFIG_FILE } from './constants';
export const getUserConfig = ({ appData }: { appData: AppData; }) => {
    return new Promise((resolve, rejects) => {
        let config = {};
        const configFile = path.resolve(appData.paths.absSrcPath, DEFAULT_CONFIG_FILE);
        if (existsSync(configFile)) {
            config = require(configFile).default;
        }
        resolve(config);
    })
}
复制代码


结果并不像我们设想的那样被成功引入,我们在控制台上看到有如下错误:

/Users/congxiaochen/Documents/malita/examples/app/malita.config.ts:1
export default {
^^^^^^
SyntaxError: Unexpected token 'export'
复制代码


这是因为我们的 malita dev 是运行在 es5 的环境下的。但是我们的配置文件使用的却是 es6 的语法。 我们可以尝试着修改配置文件``,将它改成 es5 的语法

module.exports = {
    title: 'Hello',
    keepalive: [/./]
}
复制代码


这是便可以正确获取到配置信息了

> malita dev
App listening at http://127.0.0.1:8888
{ title: 'Hello', keepalive: [ /./ ] }
复制代码



配置构建

所有当你在框架开发中遇到类似的错误时,你就可以往语法未正确转换,即文件未编译这个思路上去分析和定位,做同样的尝试,如果修改后文件可用,那么你就可以确定下来问题所在。在提出针对性的解法,比如这里文件未转译,我们就使用 esbuild 对文件进行构建。


构建方法与我们构建主入口文件一直,需要注意的是我们需要导出使用,因此需将 format 改为 cjs:

import { existsSync } from 'fs';
import path from 'path';
import { build } from 'esbuild';
import type { AppData } from './appData';
import { DEFAULT_CONFIG_FILE } from './constants';
export const getUserConfig = ({ appData, sendMessage }: { appData: AppData; sendMessage: (type: string, data?: any) => void; }) => {
    return new Promise(async (resolve, rejects) => {
        let config = {};
        const configFile = path.resolve(appData.paths.cwd, DEFAULT_CONFIG_FILE);
        if (existsSync(configFile)) {
            await build({
                format: 'cjs',
                logLevel: 'error',
                outdir: appData.paths.absOutputPath,
                bundle: true,
                watch: {
                    onRebuild: (err, res) => {
                        if (err) {
                            console.error(JSON.stringify(err));
                            return;
                        }
                        sendMessage('reload');
                    }
                },
                define: {
                    'process.env.NODE_ENV': JSON.stringify('development'),
                },
                external: ['esbuild'],
                entryPoints: [configFile],
            });
            try {
                config = require(path.resolve(appData.paths.absOutputPath, 'malita.config.js')).default;
            } catch (error) {
                console.error('getUserConfig error', error);
                rejects(error);
            }
        }
        resolve(config);
    })
}
复制代码



配置使用

keepalive

keepalive 配置传递到 generateEntry 函数中 ,修改 malita.config.ts 中的配置,验证配置是否有效。我们将状态保持配置修改为只有 users 页面能够被保持。

export default {
    title: 'Hello',
    keepalive: ['/users']
}
复制代码


值得注意的是,我们的 keepalive 配置是支撑正则表达式的,但是正则表达式在 JSON.stringify 会被转换成 {},因此我们需要编写一个工具类,来对这个配置做特殊的处理,

const configStringify = (config: (string | RegExp)[]) => {
    return config.map((item) => {
        if (item instanceof RegExp) {
            return item;
        }
        return `'${item}'`;
    });
};
复制代码


然后修改 KeepAliveLayout 配置的获取方式

`
const App = () => {
    return (
        <KeepAliveLayout keepalive={[${configStringify(
            (userConfig.keepalive) || [],
        )}]}>
            <HashRouter>
                <Routes>
                    ${routesStr}
                </Routes>
            </HashRouter>
        </KeepAliveLayout>
    );
}
`
复制代码


执行 malita dev 验证效果。


title

title 配置传递到 generateHtml 函数中

const title = userConfig?.title ?? appData.pkg.name ?? 'Malita';
 <title>${title}</title>
复制代码


打开页面重控制台查看页面的 html

<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
复制代码


至此我们就简单的完成了用户配置的功能,不知道有没有细心的小伙伴发现了,在 malita dev 启动之后,修改配置之后,虽然页面有重新加载,但是配置数据的变更并没有被真正的覆盖到原来的逻辑,原因是我们仅仅重启了我们的浏览器端,但是并没有重启我们的服务端,这个问题我们将会在明天解决。


感谢阅读,明天我们将会解决上面提到的问题,并且添加框架内置的 http 请求方法,用于在项目中请求服务端数据。其中将会涉及到本地 mock 文件的解析和代理中间件的编写。如果你对这些内容感兴趣,请持续 follow 这个专题。


源码归档

目录
相关文章
|
4天前
|
资源调度 前端开发 JavaScript
第十章(应用场景篇) Single-SPA微前端架构深度解析与实践教程
第十章(应用场景篇) Single-SPA微前端架构深度解析与实践教程
|
4天前
|
存储 前端开发 JavaScript
Web前端主题色更换实现方式全解析(一)
Web前端主题色更换实现方式全解析(一)
|
2天前
|
JSON Rust 前端开发
【sheetjs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了如何使用`sheetjs`的`xlsx`库在前端实现Excel的导出和上传。项目依赖包括Vite、React、SheetJS和Arco-Design。对于导出,从后端获取JSON数据,通过`json_to_sheet`、`book_new`和`writeFile`函数生成并下载Excel文件。对于上传,使用`read`函数将上传的Excel文件解析为JSON并发送至后端。完整代码示例可在GitHub仓库[fullee/sheetjs-demo](https://github.com/fullee/sheetjs-demo)中查看。
34 10
|
3天前
|
iOS开发 Python
mac:python安装路径,带你全面解析Python框架体系架构view篇
mac:python安装路径,带你全面解析Python框架体系架构view篇
|
3天前
|
前端开发 JavaScript
Web前端开发之面试题全解析 一,2024年最新面经牛客
Web前端开发之面试题全解析 一,2024年最新面经牛客
|
3天前
|
移动开发 前端开发 JavaScript
Web前端开发之面试题全解析 一(3),前端面试题背不下来怎么办
Web前端开发之面试题全解析 一(3),前端面试题背不下来怎么办
|
3天前
|
前端开发 算法 搜索推荐
Web前端开发之面试题全解析 一(1),2024年最新前端组件化面试
Web前端开发之面试题全解析 一(1),2024年最新前端组件化面试
|
3天前
|
JSON Android开发 数据格式
Android框架-Google官方Gson解析,android开发实验报告总结
Android框架-Google官方Gson解析,android开发实验报告总结
|
4天前
|
缓存 算法 前端开发
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
前端开发者必知的缓存淘汰策略:LRU算法解析与实践
|
4天前
|
前端开发 JavaScript 容器
第九章(应用场景篇)Qiankun微前端深度解析与实践教程
第九章(应用场景篇)Qiankun微前端深度解析与实践教程

推荐镜像

更多