当前目录快照中 web_dom 收录项目数为 0;本篇不会虚构“热门工具”。Web 语境里的 root 是公开文件目录或树/API 的起点,不会让 Android 获得超级用户权限。我们用一个只绑定 127.0.0.1 的小页面,把服务器端 document root 与浏览器端 DOM root 分开观察。
你会完成什么#
- 看懂 Nginx
root、ApacheDocumentRoot与 URL 到文件路径的映射。 - 在浏览器中找到
document.documentElement和getRootNode()。 - 创建一个 open ShadowRoot,并理解它是组件树边界而非安全沙箱。
- 用 CSS
:root修改自定义属性,同时知道它为何也叫 root。 - 停止本地服务器并删除只有实验文件的目录。
先看结论#
| “root” 写法 | 所在一侧 | 实际对象 | 是否 Android Root |
|---|---|---|---|
Nginx root / Apache DocumentRoot | 服务器 | URL 映射到的文件目录 | 否 |
document.documentElement | 浏览器 | HTML 文档的根元素 <html> | 否 |
node.getRootNode() | 浏览器 | 节点所属的 Document 或 ShadowRoot | 否 |
CSS :root | 浏览器样式 | 文档树根元素的伪类匹配 | 否 |
Android su | Android 系统 | 经 Root 管理器授权的高权限请求 | 是另一条技术路线 |
心智模型#
客户端请求 /card.svg
│
├─服务器:document root /srv/demo + /card.svg → 磁盘文件
│
└─浏览器:Document → <html> → <body> → <root-demo>
└─ ShadowRoot → <span>
这些 root 是路径/树的起点;没有 Bootloader、boot image 或 su 授权
工具清单#
| 工具或规范 | 角色 | 什么时候用 | 来源与注意 |
|---|---|---|---|
Python http.server | 临时提供静态文件 | 本篇 loopback 小实验 | 仅开发用途,不暴露公网,也不是安全加固 Web 服务器 |
Nginx root / alias | 生产服务器路径映射指令 | 阅读真实 Nginx 配置时 | 两者拼接 URI 的规则不同,不能机械替换 |
Apache DocumentRoot | 指定主文档树目录 | 阅读 Apache 虚拟主机时 | 访问权限仍由 <Directory> 等规则控制 |
| WHATWG DOM | 定义 Document、节点树和 shadow tree | 判断 API 的精确定义 | 标准,不是可下载的 Root 工具 |
| 浏览器 DevTools | 观察 Elements、Console 和样式 | 本篇验证 DOM 与 :root | 页面脚本仍不应包含秘密 |
Node.getRootNode() | 返回节点所属根 | 区分 Document 与 ShadowRoot | closed shadow tree 也不是安全边界 |
项目全景:Web root 与 DOM的 0 个项目,一个不漏#
当前数据集中该细分类别为 0 个项目。文章必须明确写出空集,不借用其他类别项目凑数;概念段只用于解释以后出现结果时如何区分 Web 文档根、DOM 根和 ShadowRoot。
当前快照没有项目被归入这个细分类别。文章仍保留独立教程,用来解释概念边界;在数据集出现首个项目之前,不虚构项目名称或推荐来源。
开始前#
需要一台个人电脑、Python 3、文本编辑器和现代浏览器。新建一个空实验目录并记录其绝对路径 <lab-dir>。当前数据集该小类是空槽位,所以“工具清单”来自 Web 标准和官方服务器文档,而不是声称站点已经收录这些仓库。不要使用含个人文件的目录作为 document root。
操作步骤#
1. 创建最小页面#
在 <lab-dir> 中用编辑器创建 index.html,内容如下。它只定义一个 CSS 变量和一个 open shadow tree,不访问网络或存储:
<!doctype html>
<meta charset="utf-8">
<style>:root { --accent: seagreen; } body { color: var(--accent); }</style>
<h1>Root meanings lab</h1>
<root-demo></root-demo>
<script>
const host = document.querySelector('root-demo');
host.attachShadow({ mode: 'open' }).innerHTML = '<span>inside shadow root</span>';
</script>
确认目录中只有这个教学文件。这里 <root-demo> 只是自定义元素名,不获得任何系统权限。
2. 以专用目录启动 loopback 服务#
从任意安全目录运行 python3 -m http.server 8000 --bind 127.0.0.1 --directory <lab-dir>,把占位符替换成真实路径。打开 http://127.0.0.1:8000/。请求 /index.html 被拼到 <lab-dir>/index.html,这就是本实验的 document root 映射;若改成 Nginx/Apache,概念相同,语法和权限模型不同。
3. 在 DevTools 区分三个浏览器根#
打开 Console,依次求值 document.documentElement.tagName、document.querySelector('h1').getRootNode() === document、document.querySelector('root-demo').shadowRoot.constructor.name 和 document.querySelector('root-demo').shadowRoot.querySelector('span').getRootNode() === document.querySelector('root-demo').shadowRoot。预期依次得到 HTML、true、ShadowRoot、true。在 Styles 面板找到 :root 的 --accent,临时改值并观察颜色;刷新即回退。
4. 停止并清理#
回到服务器终端按 Ctrl-C。刷新页面应显示连接失败,证明服务已停止。确认 <lab-dir> 是本次专用目录后,用文件管理器删除 index.html 和空目录。不要删除父目录,也不需要改权限、卸载浏览器或清理 Android 设备。
验证#
- 浏览器只能通过
127.0.0.1:8000访问实验页面。 - URL
/index.html明确对应<lab-dir>/index.html。 - 普通标题节点的根是
Document,shadow 内 span 的根是ShadowRoot。 - 修改
:root变量只影响 CSS,刷新后恢复。 - 停止进程后端口不再服务,且 Android 设备没有任何变化。
排错#
| 现象 | 常见原因 | 安全处理 |
|---|---|---|
| 浏览器返回 404 | --directory 路径错或文件名不是 index.html | 停止服务,运行 pwd/列出专用目录后重试 |
| 端口已占用 | 另一个本地进程使用 8000 | 选另一个高端口并保持 --bind 127.0.0.1 |
shadowRoot 是 null | 脚本未运行、语法错,或使用 closed 模式 | 查看 Console 错误;保持示例为 mode: 'open' |
getRootNode() 返回结果不同 | 选中的节点在另一棵树中 | 从 Elements 面板确认具体节点,再逐层观察 |
想用 chmod 777 修复 403 | Web worker 与文件权限未正确设计 | 在真实服务器按最小读取权限配置,不开放所有写权限 |
完成清单#
- 我知道该分类当前收录项目为 0,没有把规范冒充数据集项目。
- 我只从专用目录、只在 loopback 提供静态页面。
- 我能分别指出 document root、Document 根、ShadowRoot 和 CSS
:root。 - 我没有把 Shadow DOM 当成秘密或安全边界。
- 我已停止服务并只删除实验文件。