-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
工具链 | ||
|
||
webpack | ||
webpack的热更新 | ||
基础概念 | ||
1.webpack compiler : 将js代码编译成bundle | ||
2. bundle server: 提供文件在浏览器的访问 | ||
3.HMR server:将热更新的文件输出到HMR runtime | ||
4.HMR runtime:会被注入到bundle中,与HMR server 通过websocket链接,接收文件变化并且更新对应文件 | ||
5.bundle.js: 构建输出的文件 | ||
原理 | ||
1.启动阶段 | ||
a.webpack compiler 将对应文件打包成bundle.js 。发送给 bundler server | ||
b.浏览器可以通过访问服务器的方式获得bundle.js | ||
2.更新阶段 | ||
a.webpack compiler 重新编译,发送结果给 HMR server | ||
b.HMR server 计算得出哪些模块变化了,通过websocket发送给HMR runtime | ||
c.HMR runtime 更新代码 | ||
详细过程 | ||
1.使用express启动本地服务,当浏览器访问资源时对此做响应。 | ||
2.服务端和客户端使用websocket实现长连接 | ||
3.webpack监听源文件的变化,即当开发者保存文件时触发webpack的重新编译。 | ||
a.每次编译都会生成hash值、已改动模块的json文件、已改动模块代码的js文件 | ||
b.编译完成后通过socket向客户端推送当前编译的hash戳 | ||
4.客户端的websocket监听到有文件改动推送过来的hash戳,会和上一次对比。 | ||
a.一致则走缓存 | ||
b.不一致则通过ajax和jsonp向服务端获取最新资源 | ||
5.使用内存文件系统去替换有修改的内容实现局部刷新 | ||
|
||
loader 和 plugin | ||
loader是什么 | ||
Webpack默认只认识JS,对于非JS的文件,比方说样式,图片,文件,json等等,就需要一些工具来帮忙翻译。而loader,就是那个翻译官,可以解析非原生JS的代码或文件。 | ||
loader是文件加载器,能够加载资源文件,并对文件进行一些处理。处理一个文件可以使用到多个loader,执行的顺序是从下到上。 | ||
第一个loader最后执行,第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码。 | ||
|
||
plugin是什么 | ||
Webpack插件是对Webpack功能的扩展和增强,可以帮助我们在打包过程中自动执行一些额外的操作,例如生成HTML文件、压缩代码、提取CSS等 | ||
plugin让webpack的机制更加灵活,它在编译过程中留下的一系列生命周期的钩子,通过调用这些钩子来实现在不同编译结果时对源模块进行处理gin 的实现可以是一个类,使用时传入相关配置来创建一个实例,然后放到配置的 plugins 字段中,而 plugin 实例中最重要的方法是 apply,该方法在 webpack compiler 安装插件时会被调用一次,apply 接收 webpack compiler 对象实例的引用,你可以在 compiler 对象实例上注册各种事件钩子函数,来影响 webpack 的所有构建流程,以便完成更多其他的构建任务。 | ||
|
||
|
||
Tree-shaking | ||
通过静态分析消除js模块中未使用的代码,减小项目体积。 | ||
Tree-Shaking依赖于es6的模块机制,因为es6模块是静态的,编译时就能确定模块的依赖关系,对于非es6模块的代码或者动态引入的代码,无法被消除掉。 | ||
配置 | ||
需要配置webpack.config 中的optimization.useExport 为true, 同时在babel配置中使用babel-preset-env, 开启module为true,避免在构建过程中,es模块被转化成cjs模块。 | ||
|
||
webpack打包流程 | ||
1.解析配置文件,根据配置文件初始化webpack实例,构建打包流程 | ||
2.解析模块依赖,webpack会从entry配置中指定入口文件开始,递归解析模块之间的依赖关系,并构建模块依赖图谱 | ||
3.加载模块:webpack会根据模块依赖图谱,加载所有需要打包的模块,通过配置的loader将文件转换成webpack可以识别的模块。 | ||
4.执行插件:webpack在打包流程中根据钩子触发事件,通知插件完成各种任务,比如生成html 和 压缩代码等 | ||
5.输出打包结果:webpack将打包后的代码和资源输出到指定的输出目录 | ||
6.监听变化:在开发模式下,webpack-dev-server 会执行HMR流程 | ||
|
||
webpack常见事件 | ||
1.before-run: 在开始构建前触发,一般用于清理上一次构建的临时文件或者状态 | ||
2.run: 开始构建时 | ||
3.before-compile: 开始编译代码之前触发,用于添加一些额外的编译配置或者预处理 | ||
4.compile:在webpack开始编译代码时触发,用于监听编译过程或者处理编译错误 | ||
5.emit:在webpack生成输出文件之前触发,用于修改输出文件或生成一些附加文件 | ||
6.after-emit: 在生成输出文件之后触发,用于清理中间文件或执行一些其他草走 | ||
7.done:完成构建时触发,用于生成构建报告或者通知开发者构建结果。 | ||
|
||
webpack5 | ||
1.更快的构建速度,特别是开发者模式下 | ||
2.tree-shaking 优化: 改进了tree-shaking算法 | ||
3.内置的持久化缓存:可以缓存每一个模块的编译结果,加速后续的构建 | ||
4.原生支持webAssembly | ||
5.构建umd产物默认是target:es6 | ||
6.模块联邦 | ||
|
||
模块联邦 | ||
|
||
webpack开发环境优化 | ||
1.使用cache-loader等实现缓存,将模块打包结果缓存避免重复构建 | ||
2.使用dllplugin,将一些不常用的三方库,预先打包好,避免重复打包 | ||
3.开发环境下权衡后是否需要sourcemap | ||
4.多线程打包,thread-loader开启多线程需要额外的开销,并不一定会更快 | ||
5.配置模块解析,webpack在模块解析时会搜索node_module目录,这个耗时大。可以使用alias指定特定路径,或者exclude不解析node_module | ||
6.使用webpack5、vite 、rspack等 | ||
|
||
打包结果优化 | ||
1.打包体积分析,webpack-analyzer | ||
2.代码压缩, css、js压缩 | ||
3.使用懒加载拆分bundle | ||
4.开启gzip:使用compression-webpack-plugin插件,生成额外的gzip静态文件,然后部署时再开启Nginx的gzip即可。 | ||
5.使用splitChunks提取公共代码 | ||
6.分类第三方库,单独打包,提高缓存命中率 | ||
|
||
|
||
|
||
vite | ||
为什么选择vite | ||
webpack-dev-server启动缓慢,他会从入口开始,递归检索需要的模块,经过loader 和 plugin等处理。webpack的HMR随着模块数量变大而变慢。 | ||
vite 是bundless,编写的模块是按文件加载,HMR是在原生ESM上执行的,同时利用HTTP的协商缓存源码模块,依赖模块则会使用强缓存。 | ||
vite在启动时不需要打包,而是请求模块的时候实时编译,在HMR方面,也是让浏览器重新请求该模块即可,不像webpack那样需要把该模块关联的依赖全部编译一次,效率更高。 | ||
|
||
原理 | ||
1.模块解析 | ||
a.启动服务器 | ||
b.解析依赖 | ||
2.预构建 | ||
a.判断本地缓存是否存在 | ||
b.收集依赖的模块路径 | ||
c.esbuild 将三方依赖构建缓存到.vite文件夹,而且将一些cjs的文件替换成esm | ||
|
||
|
||
pnpm | ||
在分析了CI过程后,发现CI耗时主要在构建镜像、依赖解析、依赖安装和构建产物这几部分上 | ||
1.构建镜像:尽量使用相同的node版本,然后预先安装特定的工具,并且保持轻量,能减少导入镜像的耗时 | ||
2.依赖分析:将依赖包的版本区间解析为某个具体的版本号 | ||
a.npm是单线程 | ||
b.yarn多线程解析依赖resolving,在解析完成后下载fetching,最后将下载好的依赖写入node_modules文件夹linking | ||
c.pnpm也是多线程解析依赖,如果存在lockfile就不需要这一步了。边解析边下载依赖,多个不同的依赖的解析和下载是并行的,可以节省依赖解析 + 依赖安装的整体耗时 | ||
3.依赖安装: | ||
a.部分项目每次CI都重复安装依赖,没有利用好缓存,导致每次CI都需要重新执行依赖安装 | ||
4.构建产物: | ||
a.项目有多条构建命令的时候,要注意指令是否可以并行执行。 | ||
|
||
不同项目pnpm提速波动原因 | ||
1.安装依赖 | ||
a.yarn 和 pnpm 在存在lockfile的情况下,不需要resolving,这一个很耗时的步骤被省略掉了 | ||
b.在本地缓存存在的情况下,yarn 和 pnpm 都能避免从网络下载资源。但是pnpm是硬链接,会比yarn快。当依赖不复杂的情况下,io不够多,提升不明显 | ||
c.在docker上没命中缓存时,pnpm的并行解析和下载,优势比较明显 | ||
d.本地,pnpm会越来越快,因为会不断命中缓存,相同版本的依赖,reuse本地,硬链接很快。 | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
盘古低代码复盘 | ||
收益维度 | ||
运营数据 | ||
1.接入的团队(总量和新增) | ||
2.创建的应用数量(总量和新增) | ||
3.创建的页面数量 (总量和新增) | ||
效率数据 | ||
1.应用配置平均耗时 | ||
2.页面配置平均耗时 | ||
3.单应用接口开发数量 | ||
4.单应用开发周期 7天 - 1天 | ||
5.单应用人力成本 5人天 - 1人天 | ||
6.联动、校验编写难度降低, AI辅助 | ||
7.工单数量、客服号答疑 | ||
8.发布速度 | ||
9.微前端 | ||
|
||
|
||
安全 | ||
配置安全性 | ||
1.配置事故率 | ||
2.配置错误的可追溯性,日志、操作记录 | ||
3.权限控制,应用级别的控制,页面级别的控制,同一页面内弹窗级别的控制 | ||
4.crush优化,页面出现错误的情况避免配置数据丢失。重载页面后能进行配置数据回填 | ||
逻辑安全性 | ||
1.组件版本控制 | ||
2.页面版本控制 | ||
3.页面回滚 | ||
4.外网接口在非正式环境的拦截 | ||
5.发布环境控制 | ||
6.发布速度 | ||
7.按需加载 | ||
8.接口请求避免出现 “413 payload too large" | ||
|
||
技术选型 | ||
1.技术栈适配性: react、formily | ||
2.是否开源 | ||
3.代码的完成度 和 质量 | ||
4.社区的生态,star 数量、discussion 、issue 回复速度 | ||
5.团队积累 | ||
6.接入难度 | ||
7.扩展性 | ||
|
||
扩展点 | ||
1.稳定性, clone一份维护,保持和向上兼容,外部资源替换 | ||
2.跟进issue更新 | ||
3.易用性改造,文档整理,素材的生成和消费路径缩减,指定准入规范 | ||
4.新特性:插件式 | ||
5.将这种可视化编排生成schema的编辑器的,抽象成可直接使用的 | ||
|
||
交互设计 | ||
1.增强引导与提示 | ||
2.简化/省略不必要的步骤,增加默认值 | ||
3.保持配置流程连续性,避免来回跳 | ||
4.其他交互细节优化 | ||
5.文档同步更新 | ||
6.接入ChatGPT,智能创建管理系统 | ||
|
||
HEART模型 | ||
happiness:满意度 | ||
engagement:参与度 | ||
adoption:接受度 | ||
retention:留存率 | ||
Task success:任务完成率 | ||
|
||
素材的开发、构建和消费串联了整个平台 | ||
素材开发 | ||
1.本地开发、热更新 | ||
2.本地预览 | ||
3.二次开发创建素材库 | ||
4.本地轻量版本的playground | ||
|
||
官方素材库设计 lerna+monorepo | ||
1.分类:基础组件,体积不大并且改动不频繁 | ||
复杂组件,体积可大可小,改动频繁 或者是 业务类型组件需要独立的版本控制 | ||
2.构建配置:公用配置 和 extend | ||
3.版本控制 | ||
4.正式版本发布控制在master | ||
5.esm产物和umd产物 | ||
6.脚手架创建 | ||
7.本地轻量的playground 通过alias去引用对应包的东西,这样能实现修改组件里面实现热更新,同时打出cjs产物用于类型提醒 | ||
|
||
构建 | ||
1.script module : 基于umi的项目,顶层await 改造量大 | ||
2.npm包:参与构建,无环境区分、难按需加载、安装依赖耗时和版本控制难以解决, 重复安装依赖 | ||
3.git submodule: 仓库耦合、无法二次开发、管理和更新过于复杂 | ||
4.umd:传递性、依赖顺序、组件体积偏大 | ||
|
||
构建依赖分析 | ||
umd具有传递性,一个包用umd产物,那么它本身external的那些依赖都必须是umd的 | ||
某些重复使用的UI组件库和依赖库,需要单独构建到一个umd bundle中,避免package的构建重复打包 | ||
依赖的顺序控制 | ||
|
||
步骤 | ||
1.tsc 生成esm和cjs的产物用来发npm包在其他地方使用,也可以用作类型声明 | ||
2.rollup 根据情况区分,是整个package一个umd产物,还是package中每个组件一个umd产物,这种情况先构建了无版本号的umd资源 | ||
3.读取lerna配置的version,通过copy命令复制umd产物,文件名称带上版本号 | ||
4.build maifest, 生成每个umd产物的资源索引文件,比如组件A它的js外链、css外链列表。 | ||
|
||
|
||
二次开发 | ||
1.初始化脚手架 | ||
2.使用脚手架创建组件 | ||
3.推送代码出发CI生成UMD资源文件 | ||
4.二次开发的仓库绑定到低代码平台,低代码平台通过正则将git地址转成唯一标识前缀。 | ||
5.拉二次开发资源的时候,可以通过拼接git标志和文件,拉取到二次开发的代码资源 | ||
|
||
素材的消费-配置平台 | ||
1.通过脚本操作html模板,每次CI动态生成 | ||
2.读取manifest文件,动态生成script外链,按预定顺序,插入html模板的插槽中 | ||
3.使用的不带版本号的umd资源,确保每次都是最新的 | ||
|
||
素材的消费-产物平台 | ||
1.产物的渲染完全依赖于fomily-render,通过接口拉取配置平台保存的schema, 使用Formily/SchemaField渲染。 | ||
2.产物采用的是运行时渲染,而不是出码渲染。 SchemaField本身就是一个渲染器 | ||
3.产物平台项目代码,只是一个空壳的layout,核心渲染部分完全是在配置平台配置的部分,这部分由SchemaFild 和 保存的schema渲染。 | ||
需要做的按需引入用到的组件的umd。 | ||
4.在配置平台保存的时候a. 保存/发布 | ||
b. 获取需要发布的机器的ipc. 通知其他机器一起执行发布d. 判断是否需要重新构建 - 素材版本是否变了 - 产物平台的md5是否变了e. 不需要重新构建,更新html版本号即可。 index_version.html 和 index.html | ||
f. 需要重新构建,在空壳html 中,按需插入引用到的组件的最新的带版本号的外链g. 更新html版本号,并且覆盖当前html | ||
5.产物的环境区分: 资源外链都是通过node插入的,引入对应环境的资源链接 | ||
6.资源复用,按需加载:资源外链都是通过node按需插入的 | ||
7.发布速度达到3-5秒:只需要node动态插入组件外链资源,不需要重新构建项目 | ||
8.项目隔离:每个项目一个html,发布和回滚,都可以通过保存的html版本号,找到对应的html文件。 | ||
9.项目稳定性保证 | ||
|
||
监控 | ||
1.页面错误告警 | ||
2.素材体积看板 | ||
3.素材-页面关联看板:每个页面用到了哪些组件,每个组件在哪些页面用到了 | ||
|
||
|
||
Easyform | ||
抽象成一个可直接调用的组件,提供给其他平台使用 | ||
有一些平台需要 “配置一个底板, 在其他地方复用此底板生成表单,然后产品再在新的表单上填写数据”。 | ||
生成底板和渲染表单的能力可以提供给其他项目使用 | ||
|
||
|