{"id":19430210,"url":"https://github.com/etherdream/freecdn-js","last_synced_at":"2025-04-24T18:33:21.144Z","repository":{"id":40575781,"uuid":"281623949","full_name":"EtherDream/freecdn-js","owner":"EtherDream","description":"freecdn browser side files","archived":false,"fork":false,"pushed_at":"2022-12-08T22:46:54.000Z","size":807,"stargazers_count":26,"open_issues_count":2,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-09T06:55:25.240Z","etag":null,"topics":["cdn","javascript","proxy","serivceworker"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EtherDream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-22T08:45:20.000Z","updated_at":"2024-04-29T14:01:53.000Z","dependencies_parsed_at":"2023-01-25T15:15:42.868Z","dependency_job_id":null,"html_url":"https://github.com/EtherDream/freecdn-js","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Ffreecdn-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Ffreecdn-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Ffreecdn-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Ffreecdn-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EtherDream","download_url":"https://codeload.github.com/EtherDream/freecdn-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223963139,"owners_count":17232606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cdn","javascript","proxy","serivceworker"],"created_at":"2024-11-10T14:23:58.289Z","updated_at":"2024-11-10T14:23:58.793Z","avatar_url":"https://github.com/EtherDream.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# freecdn-js\n\n[![npm version](https://img.shields.io/npm/v/freecdn-js.svg?style=flat)](https://www.npmjs.com/package/freecdn-js)\n\n[freecdn](https://github.com/EtherDream/freecdn) 前端脚本。\n\n\n# 结构\n\n* core-lib：核心库（可脱离 Service Worker 运行，方便开发和测试）\n\n* main-js：主程序（静态链接 core-lib）\n\n* loader-js：加载器（体积极小，动态加载 main-js）\n\n* fail-js：异常处理\n\n\n# 特性\n\n## 体积\n\nloader-js 仅保留 Service Worker 基本功能，压缩后只有几百字节，从而能更快加载，尽早开启请求拦截。\n\n完整功能放在 main-js，该脚本默认从公共 CDN 加载，最大程度节省当前站点流量。\n\n## 安全\n\nloader-js 加载 main-js 时会校验其 Hash 值，如果和预期不一致则拒绝执行，避免 CDN 风险。\n\nHash 值是硬编码在 loader-js 中的，因此不存在热更新的现象。即使脚本有升级，开发者必须主动更新才会生效。\n\n## 稳定\n\n为了避免公共 CDN 不稳定因素，loader-js 同时从多个 CDN 加载 main-js，哪个先完成运行哪个，用流量换时间。如果 CDN 都不可用，则从当前站点加载 main-js。\n\n这些额外的流量也不是完全浪费。因为提前和多个 CDN 进行预热，之后访问会更快。并且这几个文件的加载时间，还会用于各个 CDN 的性能评估。\n\n## 兼容\n\nloader-js 生成 ES3 语法，可兼容所有浏览器。运行时会检测浏览器是否支持 ES2020，支持则加载 main-js，否则加载 fail-js，做一些不支持的处理。\n\n如果 CSP 策略导致 Service Worker 无法执行 eval，loader-js 也会加载 fail-js。（页面存在 CSP 无影响）\n\n## 复用\n\nloader-js 既能在页面中运行，也能在 Service Worker 中运行。在控制台网络栏中可见该脚本会出现两次。\n\n## 安装过程\n\n\u003cimg src=\"design.png\" height=\"335\"\u003e\n\n如果 Service Worker 安装成功，页面会立即刷新；如果浏览器不支持或安装超时，页面会加载 fail-js 进一步处理异常情况。\n\nService Worker 安装后，页面加载 loader-js 得到的不再是原先内容，而是被拦截替换成 freecdn 页面层的功能代码。该模块目前未开发，之后会用于 WebRTC 等 Service Worker 无法实现的功能。\n\n\n# 使用\n\n实际使用时通过工具生成前端脚本：\n\n    freecdn js --make\n\n因为 loader-js 包含公钥信息，所以文件内容是不固定的。通过工具生成可自动写入公钥。\n\n\n# 调试\n\n为本项目创建全局链接：\n\n    npm link\n\n进入 freecdn 项目，使用本地 freecdn-js 包代替远程版本：\n\n    npm link freecdn-js\n\n同时 freecdn 项目也可通过 `npm link` 创建全局链接，之后执行 `freecdn` 命令时直接使用本地版本。\n\n\n# 编译\n\n本项目所有模块都使用 TypeScript 开发。执行：\n\n    npm run dev\n\n之后源文件有变化时会自动编译相应的模块，生成的 JS 位于 dist 目录。\n\n配合调试的站点，使用开发模式创建前端文件：\n\n    freecdn js --make --dev\n\n开发模式有如下特征：\n\n* 前端文件创建在 `freecdn-internal/dev` 目录，而不是 `freecdn-internal/$VER` 目录\n\n* `freecdn-internal/dev` 中的文件使用 `link` 的方式和本项目 dist 中的文件保持同步\n\n* 前端脚本不会加载外部站点的资源，总是从当前站点 `freecdn-internal/dev` 加载\n\n* 前端脚本使用未压缩的版本，方便调试\n\n* 前端源码中 `IS_DEBUG` 条件变量为 true\n\n\n# 压缩\n\n    npm run build\n\n本项目使用 [terser](https://github.com/terser/terser) 对 JS 进行压缩，生成相应的 .min.js 文件。","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fetherdream%2Ffreecdn-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fetherdream%2Ffreecdn-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fetherdream%2Ffreecdn-js/lists"}