惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

TaoSecurity Blog
TaoSecurity Blog
T
Troy Hunt's Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
T
Threatpost
G
Google Developers Blog
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Exploit Database - CXSecurity.com
H
Heimdal Security Blog
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
T
The Blog of Author Tim Ferriss
Know Your Adversary
Know Your Adversary
Hacker News: Ask HN
Hacker News: Ask HN
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Schneier on Security
B
Blog
V2EX - 技术
V2EX - 技术
NISL@THU
NISL@THU
C
CERT Recently Published Vulnerability Notes
W
WeLiveSecurity
C
Cybersecurity and Infrastructure Security Agency CISA
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Y
Y Combinator Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Spread Privacy
Spread Privacy
The Last Watchdog
The Last Watchdog
V
Vulnerabilities – Threatpost
N
Netflix TechBlog - Medium
Schneier on Security
Schneier on Security
F
Fortinet All Blogs
N
News | PayPal Newsroom
Attack and Defense Labs
Attack and Defense Labs
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
S
Security @ Cisco Blogs
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
P
Privacy & Cybersecurity Law Blog
P
Proofpoint News Feed
Project Zero
Project Zero
I
Intezer
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
SecWiki News
SecWiki News
Martin Fowler
Martin Fowler

WAYJAM

告别 NPM Token:迁移到 Trusted Publishing 全记录 Sing-box:IPv6 优先出站与 Netflix 强制 IPv6 分流 [All In One] HomeLab 虚拟化 iKuai + Mihomo - IPv6 支持 [All In One] HomeLab 虚拟化 iKuai + Mihomo LiteLLM 多模型 API 中转 MacOS Bootstrp with Nix Fluency Support Full Rss [All In One] PVE 中 OpenWrt LXC 重启问题 Tabby 终端配置以及配置全平台同步 Cloudflare Tunnel + Nginx Proxy Manager:服务穿透 PVE 7 升级 8 笔记 PVE 安装 Android x86 & 安装 Magisk Fly.io 部署 Artalk 评论系统 [All In One] HomeLab 2023 搭建总结 [All In One] 轻量的文件 & 媒体服务器配置 [All In One] R71s 主机散热改造 [All In One] PVE LXC 安装 OpenWrt 软路由以及网络规划 [All In One] 安装 Proxmox VE 7.4 从零开始配置Rime - 2023 Self Hosted Bitwarden + Cloudfare HTTPS Debian NFS Server 以及 MacOS Client AdguardHome 和 Clash 透明代理配合使用 使用 Kind 部署 Prow 手记 BackBlaze B2 + Cloudfare Worker 图床 PicGo Amazon S3 插件 自动给模板生成 Inline-Svg Hugo Theme WeUI 发布! Hugo Theme Fluency 发布! Docker Clash 和 透明代理 有限状态机与分布式熔断器 「家庭娱乐」N1刷 EmuELEC 做游戏盒子 「家庭娱乐」N1刷 Armbian 做家庭服务器 分布式限流器之令牌桶实现 Kustomize 管理 Kubernetes 集群 Mixedpaper 主题发布到 Hugo 官方仓库 About 优化 Docker 构建时间 解决 etcd 与 grpc 不兼容问题 Kubernetes 部署 ElasticSearch7 集群 从零开始配置Rime - 2019 转移域名,更换评论系统,更换图床 搭建 NPM Proxy 之预编译包 搭建 NPM Proxy 美区Apple ID终于绑定PayPal成功 LogStash的调试 GitLab Shell如何通过SSH工作 Python打开类 荒原 [Theme] Bitcron主题Mixedpaper发布! Ngrok端口转发 故事之五 - 柠檬茶 故事之四 - 我是天才 故事之一 Arch滚挂了怎么办? OpenWrt内网IPv6之二 某次更新后Primusrun不能启动Dota2 OpenWrt的DNS智能解析方案 替换Google CDN库 使用Privoxy将socks代理转化为http代理 ArchLinux之软件篇 再次安装ArchLinux手记 博客再次重生 搞了个Minecraft服务器 【LnV工作室荣誉出品】小苹果MV华农大版 雨梦 醉臥石中笑人間 路由器内网IPV6地址分配 OPENWRT安装软件的两个问题 路由器上进行锐捷认证 改了BIOS的LOGO Windows下搭建我的C/C++的开发环境 Linux下用Mentohust认证校园网 Archlinux+Windows 双系统安装手记(UEFI+GPT) Google-code-prettify代码高亮 《末世迷踪》 Hello Net World!
无可奈何的页面增强方案
2018-07-14 · via WAYJAM

如果有一个大型的 Web 程序,需要对其进行一些使用上的改进,但有时候又需要跟踪上游的更新;需要保持其稳定性,不能频繁地部署;更重要的是,没有足够的时间、人员资源去进行二次开发。 如果说只是更改页面的样式或者体验性增强,可以通过浏览器插件来做到类似客户端的效果,而且有更大的权限去做更多的事情,但是可能没有办法去令到每个人安装这样的插件,特别是Chrome收紧了安全策略之后。 该怎么做呢?

我是这样做的:找到切入点,使这个程序加载一个外部的 JavaScript 脚本,通过脚本去修改页面的 DOM,数据来源是页面上的 DOM 结构以及藏在 window 对象下的的信息。当然了,单纯地改变页面并不足以满足需求,还要通过各式各样的API(包括这个 Web 程序的,或者我们自己开发的后端)去获取数据、去触发钩子操作。

仔细分析,这样的操作就是 userscript,greasyfork.org 上有大量这样的脚本,唯一不同的只是脚本的位置,我将这样的操作叫做:运行在服务端的UserScript。

首先第一个问题来了,为了部署方便,最后我们只会利用 Webpack 打包出一个脚本,整站都会加载,那么不同的页面自然有不同的功能需求,且不同功能之间不能够互相影响。我希望有一个功能(规则)表,能够根据规则来开启不同的功能。

import FeatureA from 'components/feature-a';
import FeatureB from 'components/feature-b';
import FeatureC from 'components/feature-c';
rules = {
    "controller1": {
        "page1": FeatureA
    },
    "controller2": {
        "page2": [FeatureB, FeatureC],
        "controller5": {
            components: FeatureB,
            children: [{"page4": FeatureC}]
        }
    },
    "controller3": {
        "controller4": {
            "page3": [FeatureA]
        }
    }
}

第二个问题,如何编写功能组件。首先设计一个抽象基类,所有功能组件都继承自它,并且它保持了一些基本的元信息,并且可以进行一些初始化操作和开启关闭某些操作。

abstract class Base {
    feature={}
    constructor(parent: Base | undefined) {
        this.parent = perent;
    }
    abstract init(): void;
}
class FeatureA extends Base {
    feature={action1: true, action2: false}
    init() {
        // do something
    }
    action1() {}
    action2() {}
}

第三个问题,就是解决根据规则表加载功能组件。

class App {
    constructor () {
        go(rules, path);
    }
    load (component, args) {
        let c = new component(..args);
        c.init();
        if (c.hasOwnProperty('feature')) {
            Object.keys(c.feature).map((action)=> {
                if (!c.feature.action) return;
                if (c.hasOwnProperty(action)) c.action();
            })
        }
    }
    go (rules: IRules, path, parent) {
        // if is component
        // or if is component list
        // then load it directly
        // if has components key, load rules[components] = parent
        // then go rules[children], and set parent to parent
    }
}
new App()

通过脚本来更改 DOM 免不了需要编写 HTML 片段,个人认为 JSX 可能是比较好的解决方案,我会选择轻量的 Preact 去渲染 HTML 片段,处理内部事件,但其生命周期由上面所述功能组件决定。例如,我需要在页面上增加一个按钮,这个按钮会触发一些事件,进行某些操作,按钮的状态与外部交互通过事件通信,或者说由外部重新渲染(依靠内部 diff )。

class ReactButtonDemo extends PreactComponent {}
class Feature extends Base {
    init () {
        render(<ReactButtonDemo {...args} click={()=>this.click()} />)
    }
}