微前端工具箱:用subtree解决多模块复用问题

Codex内置浏览器:DOM直连式前端开发新范式 DOM(文档对象模型)是Web前端的核心运行时抽象,其本质是可编程、可遍历、可响应的结构化界面接口。传统上,开发者需通过DevTools手动探查、用Puppeteer模拟交互、靠OCR或静态HTML解析间接理解页面状态,导致调试低效、跨框架兼容性差、动态渲染信息丢失。Codex内置浏览器突破性地将Chromium渲染进程与AI推理环境深度耦合,实现原生级DOM访问——支持毫秒级获取computedStyle、boundingRect、Vue/React内部状态等真实引擎数据,并允许在页面JS上下文中直接执行 阅读详情

653ca8779c7bb88a76ea8bf50118e29e.png

在日常开发工作中,可能会面临这样一种需求:项目 A 中,存在一个或多个有价值的功能模块,这里的所谓模块指有一个或几个页面组成的功能模组;其他项目,如项目 B,也想借助这些模块给自己赋能,且基本要求如:

  • 要使用项目 B 自己的导航菜单

  • 要重新定义路由并将各个模块分散到不同页面下

  • 接口请求要统一加特殊标识参数

  • 项目 B 要根据额外的环境变量对各模块中的功能做限制

  • 项目 B 希望以自己的上线节奏更新模块

df74d6f523ceb6ebfdeb723e30e066be.png

为了理解方便,约定文档中可能通用的几个称呼:

  • 主项目 - 项目 A

  • 新项目 - 项目 B 等

  • 子模块 - 从项目 A 里划分出的几个模块

【方案对比】

经过调研,常用且纯前端的项目模块化改造方案如下:

成本 \ 方案iframe微前端npm包Git子模块
首次改造主项目3355
首次改造新项目1322
维护子模块2332
更新子模块1531
同步子模块1121
总开发成本8161511

综合到考虑各业务项目体量、具体产品需求,和由改造带来的长期用户体验等,我们可能会在工具箱中选择Git子模块方案进行。

【git subtree 介绍】

subtree 是 git submodule 技术的主要替代技术,避免了后者的一些麻烦。

具体介绍这里不做赘述,可以直接参考文末的资料,如 《submodule vs. subtree 对比》[1]

简而言之:

  • 为每个子模块创建一个独立的 git 仓库

  • 子模块的 git 仓库中的文件可以被当成一个普通的子目录添加到主项目/新项目中

  • 过程中只拉取文件,不会产生额外的 git 隐藏文件等

  • 子模块中的改变会被正常提交到所在项目的历史中

  • 在主项目/新项目层面也可完成子模块的 git 推送/拉取操作,这也是推荐的做法

分别在主项目/新项目中执行的 git 命令:

  • 添加 remote 以简化后续命令:

git remote add -f <子模块别名> git@coding.foo.com:<子模块的...`.git`>

后面以 子模块别名 为 report 为例

  • 添加 subtree:

git subtree add --prefix=<相对路径> report <分支> --squash
  • 拉取 subtree:

git subtree pull --prefix=<相对路径> report <分支> --squash
  • 推送 subtree:

git subtree push --prefix=<相对路径> report <分支>
  • 查看 subtree 的 id:

git ls-remote report
或
git ls-remote report | grep <sha-1>

【选择一种分支策略】

和 git 本身各种流派的 workflow 一样,subtree 并没有规定特定的工作流程;这里尝试总结两种:

⇲ 单向模式:被动小分支

  • 涉及子模块中功能升级、优化、改进的内容,都在主项目中

  • 日常的以上改动都 push 到子模块的 master

  • 子模块仓库中维护某个独立分支,如用于项目 B 的 feature-projB

  • 子模块 master 有更新时手动 merge 到 feature-projB

  • 新项目只 pull 最新的 feature-projB

优点:
  1. 新项目可以随意修改特定的子模块分支

  2. 合并冲突可以在子模块中按普通方式解决

  3. 子模块代码中无需判断所在项目的环境

缺点:
  1. 如果改动需要反向同步到 master,可能需要额外的重复修改或 cherry-pick

♺ 双向模式:共建master

  • 主项目和新项目各自维护涉及子模块的相关功能

  • 新项目中的改动也可以 push 到子模块的 master

  • 新项目涉及子模块的改动应保证不污染主项目等其他项目

优点:
  1. 涉及子模块中功能升级、优化、改进的内容,可以由各个业务项目共同贡献

  2. 如果改动不复杂可以跳过再去子模块仓库下进行的各种操作

缺点:
  1. 可能需要改动 webpack 配置等以区分项目环境

  2. 代码中需要区分环境的片段需要重点关注

【注意问题】

  • 新项目和主项目结构、基础能力难免不一致,如 src/store 和 src/common/store ,以及 http 等模块中方法的不同

    • 要竭尽所能地使子模块低耦合,保证多项目适配的基本可行性

    • 要在文档中(如子模块根目录的README)标明所有依赖点

  • merge 代码冲突

    • 双向模式下,如果本方没有更新,可以直接 rm -rf 掉子模块目录并重新 add

【参考文档】

[1]

《submodule vs. subtree 对比》: https://einverne.github.io/post/2020/04/git-subtree-usage.html#sub-module-vs-sub-tree-%E5%AF%B9%E6%AF%94

  • https://betterprogramming.pub/git-subtree-usage-6aaba8b5d947

  • https://medium.com/@v/git-subtrees-a-tutorial-6ff568381844

  • https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec

  • https://medium.com/codex/github-subtrees-fb93d229cdc0

  • https://segmentfault.com/a/1190000012002151

  • https://tech.youzan.com/git-subtree/

  • http://www.fwolf.com/blog/post/246

  • https://liuyufang.com/version-control/git/git-subtree

  • https://www.worldhello.net/gotgit/04-git-model/050-subtree-model.html

989235ad52761f89b735db5d234da35e.png

9b71cfa53fedbb6440ecb61727c8a6b6.png

React平滑滚动实战:从CSS失效到自研Hook的全链路方案 平滑滚动是现代Web应用的基础交互能力,其本质是浏览器原生滚动API与JavaScript时序控制的协同问题。原理上需兼顾DOM挂载时机、渲染管线隔离与用户意图响应,技术价值在于保障首屏体验一致性、提升Lighthouse性能评分并支撑SSR/微前端等复杂架构。典型应用场景包括单页导航锚点跳转、文档站点目录联动、营销页模块定位及固定头部避让等。本文聚焦React生态下`scrollIntoView`和`window.scrollTo`的实际落地难点,结合`react-scroll`局限性与自研`useSmo 阅读详情

相关推荐

前端100道八股文+50道场景题

闭包是指一个函数能够访问它外部函数作用域中的变量,即使外部函数已经执行完毕。形成闭包需要三个条件:函数嵌套、内部函数引用外部变量、外部函数返回内部函数。闭包的主要作用有三个:第一,实现数据私有化。比如可以用闭包创建私有变量,外部无法直接访问,只能通过特定方法操作。第二,模块化。可以用闭包封装代码,只暴露需要的接口。第三,函数柯里化和防抖节流等高级技巧都会用到闭包。闭包的缺点是可能造成内存泄漏。因为闭包引用的外部变量不会被垃圾回收,如果大量使用闭包且不及时清理,会占用过多内存。

weixin_50762268的博客 1406

轻量级DOM缓存内核:UUID绑定与超级数组语义设计

DOM缓存是前端内存管理的核心技术,其本质在于建立DOM节点与其运行时状态之间的强引用映射关系,而非简单优化计算性能。传统函数式缓存(如memoize)无法解决事件处理器归属不清、解绑不精准导致的内存泄漏问题。基于UUID绑定可为每个DOM元素分配跨浏览器稳定的唯一标识,实现数据与实体的精确挂载;而超级数组语义(ensure/push/one等方法)则支撑声明式状态操作,使事件集合管理兼具去重性、有序性与可检索性。该方案广泛适用于中大型SPA、后台管理系统及微前端场景,尤其在IE11兼容、Vue/React

dejz8829的专栏 483

Chrome插件开发避坑指南:Manifest V3通信机制与权限实战

Chrome扩展(Chrome Extensions)是一种运行在严格沙箱环境中的浏览器增强技术,其核心依赖多进程隔离架构与标准化通信协议。Manifest V3重构了后台逻辑,以Service Worker替代常驻脚本,强制推行无状态、事件驱动模型,并将权限细分为host_permissions、activeTab等动态生命周期机制。这种设计提升了安全性与性能,但也带来content script注入时机、跨域通信失败、storage同步延迟、declarativeNetRequest规则限制等典型工程问

lanmh的专栏 439

前端高手进阶第31讲:微前端与功能的可重用性

这一课时介绍了微前端技术相关概念,核心内容如下:首先,微前端这种架构模式来源于微服务,目的在于对项目进行拆分和隔离,从而提高项目的可维护性和可复用性;其次,微前端这种架构的核心思想有 3 点,技术无关、环境独立、原生优先,其中环境独立比较难以实现,需要借助一定的技术手段或代码规范;最后,主流的微前端实现方式大致分为两类,在服务端集成或者在浏览器端集成,服务端集成一般通过代理转发方式实现;在浏览器端集成则实现方式较多,也有例如single-spa这类框架支持。

sucaiwa的博客 563

DOM元素获取的五大方法原理与工程实践指南

DOM元素访问是前端开发最基础也最关键的运行时操作,其本质是在内存DOM树中建立对目标节点的引用通道。不同方法底层机制差异巨大:getElementById基于哈希表实现O(1)查找,querySelector依赖完整CSS引擎解析,getElementsByClassName返回实时HTMLCollection,而querySelectorAll生成静态NodeList。理解这些原理,才能规避实时集合误用、选择器语法错误、跨上下文失效等高频陷阱,并在性能敏感场景(如首屏渲染、微前端隔离)中做出合理选型。本

afhu47033的博客 462

利用Docker Compose简化openGauss多节点容器化部署

本文详细介绍了如何利用Docker Compose简化openGauss多节点容器化部署,从环境准备到配置文件编写,再到集群部署与验证,提供了一套完整的解决方案。通过Docker Compose,原本复杂的手动部署流程被大幅简化,显著提升了部署效率和可靠性,特别适合企业级开源数据库的高可用架构需求。

weixin_30338481的博客 60

写出高质量的前端代码之消除代码中的重复

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。

郊眠寺 1062

基于OpenSSL的CA建立及证书签发(签发多域名/IP)

自签SSL证书(多域名/IP) 本文基于以下环境: 内核信息:Linux zabbix 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux 系统版本:CentOS Linux release 7.6.1810 (Core) OpenSSL版本:OpenSSL 1.0.2k-fips 26 Jan 2017 【前言】 在基于OpenSSL的CA建立及证书签发一文中(后面统.

hobby云说 4647

可能是你见过最完善的微前端解决方案

Techniques, strategies and recipes for building a modern web app with multiple teams ...

lentoo的博客 938

用Matlab和CVX搞定原子范数最小化:一个信号处理小白的避坑实践

本文详细介绍了如何使用Matlab和CVX实现原子范数最小化(Atomic norm minimization),特别适合信号处理初学者。从CVX安装配置、核心代码解析到实战中的典型问题与解决方案,提供了全面的避坑指南。通过具体案例展示了原子范数在频率估计和DOA估计中的优势,并给出性能优化策略和可视化方法。

weixin_28731231的博客 232

PaddleOCR训练自己的数据

一 、数据准备 采用PPOCRLabel标注自己的数据 PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置PP-OCR模型对数据自动标注和重新识别。使用Python3和PyQT5编写,支持矩形框标注和四点标注模式,导出格式可直接用于PaddleOCR检测和识别模型的训练。 1.1 安装PaddlePaddle pip3 install --upgrade pip # 如果您的机器安装的是CUDA9或CUDA10,请运行以下命令安装 python3 -m pip in.

zyb的博客 1万+

git子仓库submodule、subtree方案详解

submodule:类似于引用subTree:类似于拷贝场景例子:在一篇博客中想用到你另一篇博客的内容,git submodule是使用那篇博客的链接,而git subtree则是将内容完全copy过来。优劣subtree与submodule的作用是一样的,但是subtree出现得比submodule晚,它的出现是为了弥补submodule存在的问题:1、submodule不能在父版本库中修改子版本库的代码,只能在子版本库中修改,是单向的2、submodule没有直接删除子版本库的功能。

阿东的博客 1783

LangChain + PlayWright实战:5分钟搞定网页自动化测试(附完整代码)

本文详细介绍了如何利用LangChain与PlayWright构建智能网页自动化测试系统。通过环境配置、核心架构设计、实战Agent构建及性能优化等步骤,开发者可以快速实现高效的Web操作自动化,提升测试效率。文章还提供了完整代码示例和典型问题解决方案。

weixin_27791839的博客 239

微前端公共模块复用方案

什么是微前端? 微前端就是将不同的功能按照不同的维度拆分成多个子应用。通过主应用来加载这些子应用。 微前端的核心在于拆, 拆完后在合! 2018年 Single-SPA诞生了, single-spa 是一个用于前端微服务化的 JavaScript 前端解决 方案 (本身没有处理样式隔离, js 执行隔离) 实现了路由劫持和应用加载。 2019年 qiankun 基于Single-SPA, 提供了更加开箱即用的 API ( single-spa + sandbox + ...

ddwddw4的博客 4259

基于GEC6818开发板+Linux+Qt设计的智能养老院出入管理系统(195)

当前,传统的养老院出入管理模式普遍存在信息更新滞后、数据统计繁琐、实时监控能力不足等问题,难以满足现代养老机构对安全管理与服务质量提升的需求。本系统设计正是针对这些问题,通过集成先进的硬件设备如高性能GEC6818开发板以及RFID刷卡模块,结合稳定高效的嵌入式Linux操作系统和QT开发框架,构建一套功能齐全、操作直观、响应迅速的智能出入管理系统。 该系统能自动记录并实时显示老人的进出时间,方便管理人员及时了解每位老人的活动轨迹,同时具备强大的后台管理功能,支持管理员便捷地进行老人信息的增删改查操作。通

1069

【AI智能体】Codex 插件从使用到项目开发实战操作详解

Codex 插件从使用到项目开发实战操作详解

congge 7636

Mistral 架构深度解析:Contextual_KTO_Mistral_PairRM 的 32 层 Transformer 与 GQA 注意力机制完整指南

**Contextual_KTO_Mistral_PairRM** 是基于 Mistral-7B-Instruct-v0.2 底座、采用 KTO 偏好对齐算法训练的大语言模型。这篇文章带你深入它的 **32 层 Transformer 解码器**,拆解 **GQA 分组查询注意力**如何压缩 4 倍 KV 缓存、RoPE 位置编码与 SwiGLU 前馈网络各起什么作用,并逐行读懂 [config.

gitblog_00572的博客 382

华为OD机试 - 小火车最多人时所在园区站点(Java 2024 E卷 100分)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 996

Monorepo(单体仓库)架构

但是还不是Monorepo架构,因为它缺乏Monorepo的工程加载,没有共享依赖、没有跨项目引用。❗ 注意:不是所有“多项目同仓”都叫“规范的 Monorepo”如果你只是简单地把几个不相关的项目丢进一个带。

EmotionComputer 471

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

git subtree push --prefix dist origin gh-pages报错原因及解决方案

git subtree push --prefix dist origin gh-pages报错 问题描述 之前每次提交dist到gh-pages都会报错,经过排查原因出在CNAME 当通过Settings->Pages里的Custom domain填写域名的时候,gh-pages分支会创建一个CNAME文件,里面存放域名,导致文件不匹配。每次都需要删除gh-pages分支并重新push 解决方案 在源代码目录下新建一个CNAME,放入域名,每次npm run build之后重新将CNAME加入

qq_40624741的博客 931

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

java git subtree_Git Subtree的使用

背景项目A与项目B存在公用模块,在项目A中修改Bug或增加新功能需要同步到项目B中,由于存在区别所以还不能完全copy需求分析公用代码迁移出去独立的 git 仓库,供其他项目共享代码公用代码原本是什么样,抽取后也是什么样,不像pod会对公用代码进行动态库或静态库的包装公用代码库是可以在不同项目间双向同步的而不是单向同步保留公用代码库的历史提交记录与双向同步记录双向同步的栗子:A项目中依赖了子项目B...

weixin_34413326的博客 400

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Vue 组件化开发:构建可复用和可维护的前端应用

组件化开发是一种将应用程序划分为多个独立的、可复用的组件的开发方式。每个组件都具有自己的结构、样式和行为,可以在不同的上下文中被多次使用。通过组件化开发,可以实现代码的复用、模块化和维护性的提升。

weixin_43749805的博客 1225

git subtree使用体验

git subtree 旧版本的git也支持(最老版本可以到 v1.5.2). 详细了解先看这篇文章,写的挺好:https://tech.youzan.com/git-subtree/ 下面介绍具体操作: 1、初始化subtree项目 在主项目根目录的下面 git subtree add --prefix=用来放S项目的相对路径 S项目git地址 xxx分支 例如:git subtree add --prefix=modules/MultiMedia/TVKPlayer_...

李棚的优快云专栏 1933

如何处理前端开发中的模块耦合问题?

在前端开发中,模块耦合问题是一个常见的挑战,它会导致代码难以维护和扩展。:将复杂的前端项目分解为一个个小的、可复用的模块。每个模块负责特定的功能,这样可以减少模块之间的依赖关系,提高代码的可维护性和复用性。:基于模块化的基础上,进一步将模块封装为组件,实现更高层次的抽象和复用。组件化可以使得代码结构更加清晰,便于管理和维护。:迪米特法则(Law of Demeter)建议一个对象应该对其他对象有尽可能少的了解,只与直接朋友通信。通过遵循这一原则,可以降低模块之间的依赖关系,减少耦合。

破损的天堂鸟博客 698

微前端如何实现组件共享

组件共享是微前端的重要组成部分,它可以帮助开发者复用组件,减少代码的重复。通过使用组件库、模块联邦、通信机制和集成方式,开发者可以更高效地构建和管理微前端应用。希望本文对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言讨论。

你若盛开,清风自来 1085

前端开发的新突破:利用 Web Components 构建可复用的 UI 组件

Web Components 是一组浏览器原生支持的技术,使得前端开发者可以创建封装良好的、自定义的 HTML 元素。自定义元素(Custom Elements):允许开发者定义自定义标签,并为其绑定行为。影子 DOM(Shadow DOM):提供封装的 DOM,避免样式和脚本冲突。HTML 模板(HTML Templates):定义可重复使用的 HTML 结构。HTML 导入(HTML Imports)(已废弃): 允许开发者导入 HTML 文件并在页面中使用。

桂月二二博客 1131
上一篇: 全面了解 Vue.js 函数式组件
下一篇: [译] 用 sendBeacon 发送分析信息的优点
云前端
博客等级 码龄17年 101粉丝 113原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值