⚠️温馨提示: 文档中包含【1个】暂不支持的区域,请通过搜索关键字【暂不支持的文档区域】进行后续处理
前端复用与团队协同开发演进
微前端技术经历了多个阶段的发展,从最早的多页开发到组件化开发,再到区块化开发,最终演进到微前端。以下是每个阶段的详细说明:
多页开发
特征
- 每个页面都是一个独立的 HTML 文件,页面之间通过超链接进行跳转。
- 服务器渲染每个页面,客户端负责简单的交互逻辑。
优点 :
- 简单易用,适合小型项目。
- 页面之间完全独立,互不影响。
缺点 :
- 难以复用代码,每个页面需要重复编写相同的代码。
- 难以维护,特别是当项目规模变大时。
- 用户体验较差,每次跳转页面都需要重新加载整个页面。
示例
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Home Page</title>
</head>
<body>
<h1>Welcome to the Home Page</h1>
<a href="about.html">About</a>
</body>
</html>
<!-- about.html -->
<!DOCTYPE html>
<html>
<head>
<title>About Page</title>
</head>
<body>
<h1>About Us</h1>
<a href="index.html">Home</a>
</body>
</html>
组件化开发
特征 :
- 将页面拆分为多个可复用的组件,每个组件负责特定的功能或UI部分。
- 组件可以通过组合形成复杂的页面结构。
- 典型代表框架:React、Vue、Angular。
优点 :
- 代码复用性高,组件可以在不同的页面或项目中重复使用。
- 易于维护和扩展,组件化的结构使得项目更加模块化和清晰。
- 更好的用户体验,单页应用(SPA)只需要部分更新页面内容,而不是整个页面刷新。
缺点 :
- 初学者上手难度较高,需要理解组件化和框架的使用。
- 对于大型项目,组件的管理和通信可能变得复杂。
示例
// App.js
import React from 'react';
import Header from './Header';
import Footer from './Footer';
function App() {
return (
<div>
<Header />
<main>
<h1>Welcome to the Home Page</h1>
</main>
<Footer />
</div>
);
}
export default App;
// Header.js
import React from 'react';
function Header() {
return (
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
);
}
export default Header;
// Footer.js
import React from 'react';
function Footer() {
return (
<footer>
<p>© 2024 My Company</p>
</footer>
);
}
export default Footer;
区块化开发
特征 :
- 在组件化开发的基础上,将页面进一步划分为独立的区块(Block),每个区块负责更高层次的业务逻辑。
- 区块之间可以独立开发、测试和部署。
- 典型应用:大中型企业级应用,采用模块化设计。
优点 :
- 更高的模块化程度,使得团队可以并行开发不同的区块。
- 每个区块可以独立部署和更新,不影响整个系统的稳定性。
- 区块之间可以通过明确的接口进行通信,降低耦合度。
缺点 :
- 需要设计良好的区块通信机制,确保区块之间的数据和事件传递。
- 管理和协调多个区块的开发和部署复杂度较高。
示例
- 安装 Umi.js:
npx create-umi my-app
cd my-app
yarn
- 添加 Umi Block:
yarn add @umijs/block-sdk
umi block add AntDesignPro/AccountSettings
使用 Block:
- 生成的 Block 会自动添加到路由中,你可以直接在浏览器中访问
微前端
特征 :
- 将前端应用拆分为多个微型的、独立的前端应用(子应用),每个子应用可以由不同的团队开发和部署。
- 子应用可以使用不同的技术栈,通过统一的容器集成到一起。
- 微前端架构允许不同的子应用在同一个页面中协同工作。
优点 :
- 各子应用独立开发、测试和部署,提高开发效率和灵活性。
- 技术栈独立,不同团队可以根据需求选择最合适的技术。
- 提升系统的可扩展性和维护性,子应用的变化不会影响其他部分。
缺点 :
- 需要复杂的路由和通信管理,确保各子应用之间的数据和事件流畅传递。
- 初期架构设计和搭建成本较高,需要经验丰富的开发人员。
- 性能管理和优化变得更加重要,因为页面上可能同时存在多个子应用。
示例
// main.js (Host Application)
import { registerApp, start } from './microFrontendFramework';
registerApp('app1', {
mount: async (container) => {
const { mount } = await import('app1/mount');
mount(container);
},
unmount: async (container) => {
const { unmount } = await import('app1/unmount');
unmount(container);
}
});
registerApp('app2', {
mount: async (container) => {
const { mount } = await import('app2/mount');
mount(container);
},
unmount: async (container) => {
const { unmount } = await import('app2/unmount');
unmount(container);
}
});
start();
// microFrontendFramework.js
class MicroFrontend {
constructor() {
this.apps = [];
this.activeApp = null;
window.addEventListener('hashchange', this.loadActiveApp.bind(this));
}
registerApp(name, app) {
this.apps.push({ name, app });
}
async loadActiveApp() {
const hash = window.location.hash.slice(1);
const app = this.apps.find(app => app.name === hash);
if (app) {
if (this.activeApp && this.activeApp.unmount) {
await this.activeApp.unmount();
}
this.activeApp = app.app;
if (app.app.mount) {
await app.app.mount(document.getElementById('app-container'));
}
}
}
start() {
this.loadActiveApp();
}
}
const microFrontend = new MicroFrontend();
export function registerApp(name, app) {
microFrontend.registerApp(name, app);
}
export function start() {
microFrontend.start();
}
模块联邦
模块联邦(Module Federation)是 Webpack 5 引入的一项重要特性,旨在解决微前端架构下的代码共享和依赖管理问题。它允许多个独立的前端应用在运行时动态加载和共享模块。
特征 :
- 动态加载 :模块联邦支持在运行时动态加载远程模块,而不是在编译时将所有代码打包在一起。
- 代码共享 :不同应用之间可以共享模块,无需重复打包,提高了代码复用性和加载速度。
- 独立部署 :各个应用可以独立开发、测试和部署,互不影响。
- 自动依赖处理 :模块联邦自动处理依赖关系,确保加载的模块能够正常运行。
优点 :
- 提高开发效率 :不同团队可以独立开发和部署各自的模块或应用,减少了开发依赖,提高了开发效率。
- 代码复用 :通过模块联邦,多个应用可以共享相同的代码或组件,减少了重复代码,降低了维护成本。
- 性能优化 :动态加载减少了初始加载时间,只在需要时加载特定模块,提高了应用的性能。
- 独立部署 :各个应用或模块可以独立部署和更新,降低了集成和发布的复杂性。
- 技术栈独立 :不同的子应用可以使用不同的技术栈,满足各团队的技术需求。
缺点 :
- 复杂性增加 :模块联邦引入了更多的配置和管理复杂性,需要开发者具备一定的知识和经验。
- 版本管理 :在共享模块时,必须小心处理版本兼容性问题,确保不同版本的模块能够正常工作。
- 性能开销 :动态加载远程模块可能引入一定的网络延迟和性能开销,特别是在低带宽或高延迟环境下。
- 构建和部署协调 :需要良好的构建和部署策略,确保各个模块或应用在发布时能够正确加载和运行。
示例
应用 A (Host) 配置
// webpack.config.js (App A)
const path = require('path');
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
entry: './src/index.js',
mode: 'development',
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 3001,
},
output: {
publicPath: 'http://localhost:3001/',
},
plugins: [
new ModuleFederationPlugin({
name: 'appA',
remotes: {
appB: 'appB@http://localhost:3002/remoteEntry.js',
},
}),
],
};
应用 B (Remote) 配置
// webpack.config.js (App B)
const path = require('path');
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
entry: './src/index.js',
mode: 'development',
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 3002,
},
output: {
publicPath: 'http://localhost:3002/',
},
plugins: [
new ModuleFederationPlugin({
name: 'appB',
filename: 'remoteEntry.js',
exposes: {
'./Module': './src/Module',
},
}),
],
};
应用 B 中的模块
// src/Module.js (App B)
export const greet = () => 'Hello from App B';
应用 A 中使用远程模块
// src/index.js (App A)
import('appB/Module').then(module => {
console.log(module.greet());
});
浅尝微前端
基本概念
微前端架构具备以下几个核心价值:
- 技术栈无关 主框架不限制接入应用的技术栈,微应用具备完全自主权
- 独立开发、独立部署 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
- 增量升级
- 在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
- 独立运行时 每个微应用之间状态隔离,运行时状态不共享
微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。
更多关于微前端的相关介绍,推荐大家可以去看 这几篇文章:
single-spa 使用示例
详见代码示例
微前端原理剖析
微前端框架实现的核心包含:生命周期、样式隔离、应用隔离、应用间通信等。
生命周期(子应用接入协议)
微前端底座不用关心子应用加载细节,但它需要清除子应用以何种形式进行初始化,以何种形式进行挂载,最后又以何种形式进行卸载。
以 single-spa 源码为例,用于管理子应用的生命周期包含:
- bootstrap: 初始化应用,仅执行一次。
- mount: 挂载应用,每次进入应用时执行。
- unmount: 卸载应用,每次离开应用时执行。
不管你用什么技术栈实现子应用,最终在子应用入口都需要导出 bootstrap、mount、unmount 方法,这样 single-spa 就知道在对应时机如何处理子应用。
原生 js
import { registerApplication, start } from "single-spa";
// 这里可以是你的框架初始化代码
export function bootstrap() {
return Promise.resolve();
}
export function mount() {
return Promise.resolve().then(() => {
const el = document.getElementById("main-app");
el.innerHTML = "<h1>App 1</h1>";
});
}
export function unmount() {
return Promise.resolve().then(() => {
const el = document.getElementById("main-app");
el.innerHTML = "";
});
}
React
import React from 'react';
import ReactDOM from 'react-dom';
import singleSpaReact from 'single-spa-react';
import App from './App';
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
domElementGetter: () => document.getElementById('main-app'),
});
export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount;
Vue
import { h, createApp } from 'vue';
import singleSpaVue from 'single-spa-vue';
import App from './App.vue';
const vueLifecycles = singleSpaVue({
createApp,
appOptions: {
render() {
return h(App);
},
},
handleInstance: (app) => {
app.config.globalProperties.$router = {};
},
});
export const bootstrap = vueLifecycles.bootstrap;
export const mount = vueLifecycles.mount;
export const unmount = vueLifecycles.unmount;
样式隔离
为了防止样式冲突,可以使用 CSS Modules 或 Shadow DOM。CSS Modules 将样式限定在模块范围内,Shadow DOM 则创建一个封闭的 DOM 范围。
社区有很多关于样式隔离的提案,综合考虑可行性,最终还是工程化方式处理最靠谱。
工程化手段( 算是最佳方案 )
目前,CSS Module 是主流实践,其原理在于通过编译生成不会互相冲突的选择器名称。通过使用 CSS Module(可以在构建工具中集成CSS预处理器),可以轻松避免应用程序之间的选择器冲突。在应用程序打包构建之后,各个模块之间的选择器名称是唯一的,因此不会造成样式冲突。
另一方面,CSS-in-JS 也是一种流行的解决方案,它能够确保样式编码不会发生冲突。因此,大多数情况下,通过适当的工程化手段处理主子应用程序之间的样式冲突即可解决样式隔离的问题。
Dynamic Stylesheet
首要任务是实现动态样式表。当从子应用 A 切换到子应用 B 时,需要移除子应用 A 的样式表,并加载子应用 B 的样式表。这样可以确保在项目中子应用 A 和子应用 B 的样式不会同时存在,基本实现了样式的隔离。切换应用时,样式会自动从应用 A 切换到应用 B,会自动处理样式的删除和加载。然而,这种方法仅在单应用模式下有效,即同一时间只能有一个应用处于活跃状态。
尽管动态样式表解决了子应用之间的样式冲突,但并未解决主应用之间的问题。通常最佳的解决方案是通过工程化手段,如 BEM 命名约定。例如,约定给应用 A 的样式添加前缀 "a-",应用 B 的样式添加前缀 "b-",框架应用也添加统一的前缀。通过这种约定,可以有效避免样式冲突。特别是在处理主子应用之间的冲突时,只需确保主应用的样式规则清晰具体,与子应用不会发生冲突,即可解决大部分问题。然而,这种方案依赖于约定,有时可能存在漏洞。
Shadow DOM
Shadow DOM 能够真正实现 CSS 完全隔离,通过阴影边界将主应用和子应用的样式彻底隔离开来。
然而,大多数情况下,并不建议盲目启用严格样式隔离。之前已经有同事提到了一些原因,例如当使用弹窗组件时(这些组件通常默认添加到 document.body),它会跳过阴影边界进入主应用,导致样式失效。另外,如果子应用使用 React 技术栈,React 的事件代理实际上是挂载在 document 上的,这也可能引发问题。因此,一旦启用 Shadow DOM,你可能需要手动逐个修复这些问题,这是一个相对繁琐的过程。
runtime css transformer
我们可以通过引入限定条件,在 `data-qiankun-app1` 子应用的最外层容器(例如 div)上规定只有 `.main` 样式才能生效。通过这种运行时的转换,我们也能达到样式隔离的目的。然而,这种方案存在一些问题,例如转换过程增加了一定的运行时开销,而且在处理一些媒体查询和动画时可能会出现意外情况。
应用隔离
- 快照沙箱
- 代理沙箱
应用隔离层就需要使用到我们常说的 js 沙箱方案。
上面提到 single-spa 应用,但如果你直接裸用 Single-SPA ,一旦应用之间的发生了冲突,你的应用很可能就跑不下去了,所以就需要有 JS 沙箱。
在沙箱的实现里,底座加载开辟 全局环境 ,加载的子应用我们额外开辟环境,也就是我们说的 沙箱环境 。
快照沙箱 SnapshotSandbox
快照沙箱的实现思路很简单:在应用沙箱挂载和卸载时记录快照,并在应用切换时根据快照恢复环境。
当子应用加载并启动后,即进入渲染环境,在内部沙箱中记录当前快照状态。当最后一个子应用卸载时,会将当前环境与记录的快照进行比较,以恢复全局状态。这意味着整个应用的运行环境在挂载和卸载过程中会回到最初状态,子应用对全局环境的修改在卸载时会被撤销,这就是快照沙箱的基本思路。
举例来说,假设在应用 A 运行时添加了一个全局变量 `window.a = 123`,此时 `window.a` 将变成 123。然而,当应用 A 卸载后,快照还原,`window.a` 将会被删除,因此在全局环境中看不到 `a` 变量。
实现上,使用窗口差异(windows diff)很简单:对比当前环境和原始环境,通过两个循环来找出差异,并全面恢复原始环境的状态。
class SnapshotSandbox{
constructor(){
this.proxy = window;
this.modifyPropsMap = {};
this.active();
}
active(){ // 激活
this.windowSnapshot = {}; // 拍照
for(const prop in window){
if(window.hasOwnProperty(prop)){
this.windowSnapshot[prop] = window[prop];
}
}
Object.keys(this.modifyPropsMap).forEach(p=>{
window[p] = this.modifyPropsMap[p];
})
}
inactive(){ // 失活
for(const prop in window){
if(window.hasOwnProperty(prop)){
if(window[prop] !== this.windowSnapshot[prop]){
this.modifyPropsMap[prop] = window[prop];
window[prop] = this.windowSnapshot[prop]
}
}
}
}
}
代理沙箱 ProxySandbox
另一种思路是利用 ES6 的 Proxy 功能来实现沙箱环境。通过劫持全局对象 `window`,我们可以拦截子应用对全局环境的修改操作。当子应用向 `window` 上添加、修改或删除内容时,我们可以记录这些操作。在恢复到外部全局环境时,只需反向执行这些操作即可。例如,如果在沙箱内部设置了新变量 `window.a = 123`,在离开时只需删除 `a` 变量即可。
class ProxySandbox {
constructor() {
const rawWindow = window;
const fakeWindow = {}
const proxy = new Proxy(fakeWindow, {
set(target, p, value) {
target[p] = value;
return true
},
get(target, p) {
return target[p] || rawWindow[p];
}
});
this.proxy = proxy
}
}
通信
应用通信的主要方式有:
- 既有 URL
- 事件系统
- props
URL 机制
通过 url 参数约定,调用对应子应用中的函数实现通信
事件机制
在 window 宿主环境下有一个 CustomEvent
// 主应用
window.addEventListener('app1-event', (event) => {
console.log('Received data from app1:', event.detail);
});
// app1/main.js
const sendEvent = () => {
const event = new CustomEvent('app1-event', { detail: { message: 'Hello from App 1' } });
window.dispatchEvent(event);
};
export const mount = () => {
sendEvent();
// 其他 mount 逻辑
};
props
其实这个 props 是一个宽泛的说法,除了 props 以外还包含集中状态 store、context 等都可以实现。
// 主应用
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const initialState = {
sharedData: null,
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_SHARED_DATA':
return { ...state, sharedData: action.payload };
default:
return state;
}
};
const store = createStore(reducer);
// app1
import { connect } from 'react-redux';
const mapStateToProps = (state) => ({
sharedData: state.sharedData,
});
const mapDispatchToProps = (dispatch) => ({
setSharedData: (data) => dispatch({ type: 'SET_SHARED_DATA', payload: data }),
});
const App = ({ sharedData, setSharedData }) => {
setSharedData('Hello from App 1');
return <div>{sharedData}</div>;
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
大厂微前端方案
阿里 qiankun https://qiankun.umijs.org/zh
qiankun 是一个基于 single-spa 的 微前端 实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,我们将其微前端内核抽取出来并开源,希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统,同时也希望通过社区的帮助将 qiankun 打磨的更加成熟完善。
目前 qiankun 已在蚂蚁内部服务了超过 2000+ 线上应用,在易用性及完备性上,绝对是值得信赖的。
qiankun 的核心设计理念
- 🥄 简单
- 由于主应用微应用都能做到技术栈无关,qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造。同时由于 qiankun 的 HTML entry 及沙箱的设计,使得微应用的接入像使用 iframe 一样简单。
- 🍡 解耦/技术栈无关
- 微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用,而 qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。
特性
- 📦 基于 single-spa 封装,提供了更加开箱即用的 API。
- 📱 技术栈无关 ,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
- 💪 HTML Entry 接入方式 ,让你接入微应用像使用 iframe 一样简单。
- 🛡 样式隔离 ,确保微应用之间样式互相不干扰。
- 🧳 JS 沙箱 ,确保微应用之间 全局变量/事件 不冲突。
- ⚡️ 资源预加载 ,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
- 🔌 umi 插件 ,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
字节 Garfish https://www.garfishjs.org/
Garfish 起源于 头条号 的实际场景,随着业务发展变成一个 Monolithic-Applications ( 巨石应用 )。同时由于维护的团队人员都比较分散,工程大,导致开发调试效率低、上线困难(代码合并相互依赖),成为阻碍业务发展的一个重要因素。
于是在 2018 年衍生了 Garfish 这个微前端框架,经过大量业务方实际场景的验证和打磨,Garfish 逐渐趋于成熟。并且随着更多的业务对微前端的需求,Garfish 也在不断迭代之中,已经积累了丰富的微前端问题解决经验。
适合场景
- 项目的团队成员来自多个团队
- 项目内多条迭代出现需求挤兑,影响测试、发布效率
- 跨空间、跨时间维度导致团队内技术体系无法统一
- 多个前端应用需要达到「内聚的单个产品」特征
- 「内聚的单个产品」中部分内容希望达到独立开发、独立发布、独立测试、独立灰度等能力
特性
🌈 丰富高效的产品特征
- Garfish 微前端子应用支持任意多种框架、技术体系接入
- Garfish 微前端子应用支持「独立开发」、「独立测试」、「独立部署」
- 强大的预加载能力,自动记录用户应用加载习惯增加加载权重,应用切换时间极大缩短
- 支持依赖共享,极大程度的降低整体的包体积,减少依赖的重复加载
- 支持数据收集,有效的感知到应用在运行期间的状态
- 支持多实例能力,可在页面中同时运行多个子应用提升了业务的拆分力度
- 提供了高效可用的调试工具,协助用户在微前端模式下带来的与传统研发模式不同带来的开发体验问题
📦 高扩展性的核心模块
- 通过 Loader 核心模块支持 HTML entry、JS entry 的支持,接入微前端应用简单易用
- Router 模块提供了路由驱动、主子路由隔离,用户仅需要配置路由表应用即可完成自主的渲染和销毁,用户无需关心内部逻辑
- Sandbox 模块为应用的 Runtime 提供运行时隔离能力,能有效隔离 JS、Style 对应用的副作用影响
- Store 提供了一套简单的通信数据交换机制
🎯 高度可扩展的插件系统
- 提供业务插件满足业务方的各种定制需求
设计思想
- Garfish 的 沙箱设计 借鉴了 qiankun
- Garfish 的 Bridge 设计借鉴了 single-spa
- Garfish 的样式隔离设计借鉴了 reworkcss
简历深度优化(30K+ 简历)
技能描述
熟练掌握 HTML、CSS、JavaScript、Typescript 以及 OOP、FP、 AOP 等设计思想
掌握样式体系构建与落地,对 css 预编译、css in js、module css 以及 utility-first CSS 有深入研究,并从零改良过样式体系以支持 SSR、SSG
熟悉 React、Vue 相关技术栈,熟悉 React、Vue 及相关技术框架的实现原理
掌握构建工具 Webpack、Vite 等,掌握编译工具 Babel,并深入理解其原理,并参与 Rspack 构建
丰富的数据可视化经验,熟悉 Canvas、svg 开发范式,理解 Echarts、Antv 原理,能根据业务需求基于 d3、zrender 开发自定义渲染引擎
丰富的跨端开发经验,熟练使用 Taro、Flutter、React-Native 开发跨端应用,对构建 hybird App 有丰富经验,深入理解跨端开发编译原理
基于 Node.js 开发脚手架、打包构建优化工具及中间件服务
掌握常用设计模式、算法与安全知识,追求开发高质量、高可维护性代码,追求极致产品体验
团队管理经验,并在项目架构设计与性能优化方面具有丰富经验
算法与编程技术
- 精通各种算法题的分类及解决方法,包括排序与查找、数据结构、动态规划、贪心算法、回溯算法、分治算法、图论算法、数学算法等。
- 重点掌握动态规划的基本概念、解题步骤和经典题目。
3D 数字孪生平台开发经验
- 熟练使用 WebGL 和 WebAssembly 技术,开发高效的 3D 渲染引擎。
- 精通正射影像和倾斜摄影技术,具备 Tile 和模型(包括白膜和精模)的处理经验,能够使用 Blender 进行模型制作。
- 熟悉材质、光效和粒子系统的实现与优化。
全面性能优化能力
- 具备打包构建优化经验,熟练使用 Webpack 进行模块打包,掌握 chunk、treeshaking、happypack、cache-loader 等优化技巧,并使用 Webpack Module Federation 进行模块联邦管理。
- 精通资源优化,能够有效进行图片、字体压缩,管理请求队列,并通过 OSS 和 CDN 提升资源加载速度。
- 具有应用性能优化经验,包括数据结构优化和应用模块更新。
- 深入了解缓存机制,熟悉强缓存(Expiration、Cache-Control)、协商缓存(Etag)和策略缓存(Service-Worker)的配置与管理。
项目描述
这个环节至关重要,很多同学不重视,简历随便写一写就开始投递了,结果投出去几百份可能一家公司面试都没有,结果就在怀疑前端行情出问题了
STAR 法则:
- 遇到了什么问题 question,需求
- 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
- 具体方案落地
- 结果反思,细节优化思考
大家先看这段描述:
技术栈:Java、Vue2、echarts、WEui、BaiduMap、JavaScript 、HTTP数据库:MySQL管理工具:SVN
责任描述:
1)产品前端研发负责人,主要负责整体样式沟通,样式调配实现;门户、管理平台、移动端、智端、可视化等前端内容实现;
2)实现组织管理、人员管理、党员关系转接、待办通知、绩效考核(复杂功能算法实现)、发展党员(25个流程)、可视化等主体功能,兼容性优化、适配1920*1080屏幕以及响应式布局实现;
3)相关功能开发,包含前后端、数据库;
4)门户框架搭建、门户整体设计、后端接口、门户前端 UI 实现等;
5)微信小程序框架搭建、小程序页面设计及开发、知识图谱技术预演;
6 )项目经理工作辅助,包含需求沟通、UI设计沟通、交付材料项目经历整理、前端代码质量管理、部分功能设计。
深度优化一下
工作内容和成果
- 【 架构设计 】参与智慧管理平台整体架构设计、技术选型与方案评审,担任全栈开发,完成相关核心模块
- 【 企微开发 】对接企业微信生态,基于企微 SDK 完成平台支付、消息推送、机器人等功能开发
- 【 可视化 】主导完成平台可视化渲染引擎(可视化图表的组件,数据协议)设计与开发,基于 echarts (svgRenderer、canvasRenderer 一千万行数据的表格渲染【不能使用 虚拟滚动 】 canvas table,chunk)封装业务图表库,服务于平台可视化场景
- 【 地图开发 】使用百度地图 SDK,封装业务地图渲染器(MapRenderer),包含:地图撒点、地区数据下钻等功能
- 【 小程序与App 】基于 uniapp 实现智慧党建用户端多端开发落地,产物编译为 H5、微信小程序两端应用
- 【 团队基建 】推进团队业务组件库、图表库与基础库沉淀,完成 10+ 个业务组件沉淀,以此提升了团队协同开发效率
- 【 优化 】设计产品响应式系统,基于 media query 设计响应式端点规则,适配不同端应用的展示
- 【 自研 OA 打通 】...
STAR
【技术栈】
- Java、Vue2、ECharts、WEui、BaiduMap、JavaScript、HTTP
- 数据库 :MySQL
- 管理工具 :SVN
【产品前端研发负责人】
- 情境 (Situation) :担任产品前端研发负责人,负责门户、管理平台、移动端、智端、可视化等前端内容的实现。
- 任务 (Task) :主要任务是与设计团队沟通,调配和实现整体样式,确保产品界面的一致性和用户体验。
- 行动 (Action) :我协调设计与开发团队,定期召开样式沟通会,亲自进行样式的调配与实现,并负责不同平台和设备的前端内容开发。
- 结果 (Result) :成功实现了多个平台的前端开发工作,提升了产品的用户体验和一致性,获得了团队和用户的高度评价。
【实现复杂功能及优化】
- 情境 (Situation) :项目需要实现复杂功能算法和大规模功能模块,包括组织管理、人员管理、党员关系转接、待办通知、绩效考核、发展党员(25个流程)和可视化功能。
- 任务 (Task) :负责上述复杂功能的实现,并优化其兼容性和响应式布局。
- 行动 (Action) :通过设计和实现复杂算法,确保各模块的功能性;进行兼容性优化,使系统适配1920*1080屏幕和响应式布局。
- 结果 (Result) :成功实现并优化了所有复杂功能,系统在不同设备和分辨率下均表现良好,提高了用户操作的流畅度和满意度。
【全面功能开发】
- 情境 (Situation) :需要进行前后端和数据库的全面开发,确保系统各功能模块的无缝集成。
- 任务 (Task) :开发和实现相关功能,包括前端UI、后端接口和数据库交互。
- 行动 (Action) :采用Java、Vue2等技术,开发并调试各功能模块,与后端团队密切合作,确保接口的准确性和数据的一致性。
- 结果 (Result) :成功完成了所有功能模块的开发和集成,系统运行稳定,性能优异,受到了客户的好评。
【微信小程序开发与知识图谱预演】
- 情境 (Situation) :项目需要开发微信小程序,并进行知识图谱技术的预演。
- 任务 (Task) :负责小程序框架的搭建、页面设计及开发,同时进行知识图谱的技术预演。
- 行动 (Action) :使用WEui、JavaScript等技术,设计并开发小程序页面,进行知识图谱的技术预演和验证。
- 结果 (Result) :成功搭建了微信小程序框架,完成了页面设计和开发工作,知识图谱技术预演顺利,通过了技术验证。
【项目经理工作辅助】
- 情境 (Situation) :在项目中辅助项目经理,确保项目需求沟通顺畅,UI设计协调到位,交付材料齐全,前端代码质量高。
- 任务 (Task) :辅助项目经理进行需求沟通、UI设计沟通、交付材料整理、前端代码质量管理以及部分功能设计。
- 行动 (Action) :积极参与需求和UI设计的沟通,整理和管理项目交付材料,进行代码审查和质量管理,并参与功能设计。
- 结果 (Result) :成功辅助项目经理完成了项目的各项工作,提高了项目的开发效率和交付质量,确保了项目的顺利进行。
其实还不够,这些项目才是求职香饽饽
你可能不具备这些项目的实战经验,很多同学写了很多年管理系统,简单增删改查项目,如果不跳出这个圈子,很难在薪资上有非常大的突破!
大厂 UI 组件库(Vue3)整体设计与开发实践(monorepo 架构)
大厂业务 Hooks 库(React 18)整体设计与开发实践(从零到一的架构、规范流程)
企业级脚手架工具开发实践
企业级文档编辑器飞书文档开发实践
前端性能、异常与行为监控
3D 可视化数字孪生低代码实战 💥
- 基于 cesium(arcGis、超图) 方案的 WebGIS 开发实践
- 基于 openlayer、mapbox 开发
- 基于 WebGL 3D 可视化开发实践
年包 50W+ 薪资长线规划
核心要素
全面的技术储备
- Vue 经验、React 经验,Vue3 + Typescript,React18(Hooks、Concurrent)【框架基础】
- 框架原理,React 生态库原理(React-Router、Redux)、Vue 生态库原理
- 工程化(构建工具:Webpack、Vite、Rspack、ESBuild、swc)
- CI/CD 自动化,自动化构建、自动化部署
- 基建能力(Node、命令行工具开发 Cli),UI 库、图表库、工具库
- 业务方面(管理系统、图表类),衍生 -> 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
至少参加过两个以上大型项目,并主导过一个复杂项目
- 管理系统,(项目搭建、方案、技术栈、CI/CD 等等)
- 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
面试表现好
个人介绍【 打个草稿 】,基本信息、技术栈、项目重难点
STAR:
- 遇到了什么问题 question,需求
- 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
- 方案落地
- 反思,优化
- 面试过程中,重点去复习只是重难点(v8 内存管理、Promise A+ 规范、事件循环、this、面向对象编程原型)
- 技术储备,由你的项目经验体验,技术怎样在你的项目中落地的
学历
- 大专,尽快考一个本科证(年限去掉)
- 民办
- 内推,学历问题、工作经历的问题
补足短板
项目简单,管理后台一做就是大半年,天天 CRUD
- 看开源项目(react-hook-form ts 类型、hook 处理、状态管理、架构 Provider,keyPath)
- 找一些不错的项目练手
- 拿好的项目,学习完放在简历里, 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
- 1.自研:15K, 2.外包:20K ,这个火坑, 灰(供需决定)
技术栈掌握不深不广,只会用 Vue2 (Vue3 + Typescript),React18(React stack reconciler)
架构、方案设计没碰过
- React,create-react-app、umi,没有真正从零到一去设计初始化过一个项目
- Vue,Vue CLI,Vite/Webpack。Vue2 CLI 创出来项目 1. webpack、2.vite
没有专精的技能或业务
- 自驱 (假定自己是 Leader),项目的赢利点、商业价值【 可视化、编辑器、白板、团队基建、AI产品 】
- 与生俱来有些东西,好奇心、自驱力、清晰规划
- 我:管理平台,HPE(官网、后台管理),云表格(维格表、飞书云表格)、云编辑器(CKEditor 老【html string】)(语雀、【石墨文档】)
妙码学院——全程陪跑、督学、内推
⚠️ 暂不支持的文档区域,【文档小组件】
- 跨端开发 Taro(Taro 编译器 compiler、运行时 runtime)、uniapp
- 协同编辑器(文档类、画板类)wangEditor、CKEditor
- 团队基建工程(UI 库、图表库、Cli -> 产生产物 npm 包)
- 3D 可视化数字孪生 bigdata
- 低代码平台
课程体系 2.0 升级,除了基础知识夯实,融入了更多项目实战内容,包含:
企业级脚手架工具开发实践
企业级文档编辑器飞书文档开发实践
大厂 UI 组件库(Vue3)整体设计与开发实践
大厂业务 Hooks 库(React 18)整体设计与开发实践
埋点与数据监控平台实战
3D 可视化数字孪生实战 💥
- 基于 cesium 方案的 WebGIS 开发实践
- 基于 WebGL 3D 可视化开发实践
不同阶段对前端人的硬性要求
以下是对您提供的内容进行权威和专业化改写的建议:
1~3年
在此阶段,重点在于评估个人的基础知识和热情。对前端基础、计算机原理、网络通信和算法等领域的要求较高。由于在此阶段难以评估业务深度,因此更多关注基础知识的掌握程度。
- 关键在于通过学术教育或网络资源加强基础知识;
- 在简历中以多种方式展示对前端的热情,展现个人潜力;
- 积极探索前沿技术,关注国内外技术动态;
- 尝试开发小型项目或参与社区开源项目;
- 建立技术博客,以输出促进知识吸收。
3~5年
此阶段通常是向成为独立工程师发展的关键时期,避免重复使用有限的经验。
关注社区中关于进阶的资料和路线,强化基础知识;
深入掌握常用框架的高级用法,探索其原理;
在业务开发中不仅完成功能,还需考虑项目结构设计、封装基础工具、设计和开发基础组件;
思考提高团队效率的方法,例如:
- 集成代码检验和风格统一插件(如 eslint、stylelint、prettier、spellcheck);
- 从工程化角度提高本地开发效率,优化webpack构建,探索esbuild、vite等工具;
- 对于多项目开发,整理差异和统一部分,建立内部脚手架以减少重复工作;
- 尝试搭建CI/CD平台,维护公司内部的通用npm包;
- 培养软技能,如沟通协作,协调各角色共同推进目标。
5年以上
进入此阶段,可能朝技术专家或管理方向发展。期望您能够独立负责高复杂度项目,突破关键技术难题。
- 负责技术调研,关注行业趋势,选择最优技术方案,具备决策能力;
- 拥有丰富的技术经验和技术储备,能够解决遇到的困难,并有自己的方法论;
- 协助或主导业务目标制定,合理推动项目达成预期效果;
- 是否具有团队领导经验,能够协调跨团队项目,处理团队成员情绪问题,解决技能分布不平衡等问题;
- 打造技术氛围,促进团队共同成长。
职业规划指导
评论区选取三位同学互动,其他同学也可以联系咨询老师,文字方式提供辅导解答。
【未知组件reminder】
