帮一家客户做 SharePoint Online 门户性能优化的时候,最直观的问题就是:首页图片、JS、CSS 加载慢,首屏出来要五六秒。经验告诉我,这类静态资源应该走 CDN,于是自然想到 SharePoint Online 自带的 CDN 功能。可当我打开管理中心准备去找开关时,发现根本没有入口。翻了一圈官方文档才确认:启用 SharePoint Online CDN 这件事,目前只能通过 PowerShell 来完成,UI 完全不提供操作按钮。也正是这个原因,PowerShell 启用 SharePoint Online CDN 这件事,值得单独整理成一篇实操记录。
这篇内容不是简单堆几条命令,而是把公共 CDN 和私有 CDN 的区别、为什么要用 PowerShell、具体怎么启用、添源、验证、回滚,以及我实际踩过的坑全部讲清楚。适合人群很明确:需要管理 SharePoint Online 租户的 IT 管理员、负责前端资源托管或门户性能优化的开发者、还有刚接手客户 SharePoint 环境、想做规范化改造的顾问。
1. 为什么这个功能非要用 PowerShell 不可
1.1 管理中心的“隐藏开关”和官方态度
先说结论:SharePoint Online CDN 是租户级别的功能,它不能放在某个站点集里设置,也不能靠网站所有者权限开启。早期版本的管理中心还保留过入口,后来规划里直接把它移到了一律走 PowerShell 的路线。官方文档里写得很直白:CDN 管理只能通过 PowerShell 操作。所以你在 UI 里找不到,不是权限不够,是官方根本没给按钮。
这个设计对管理员来说其实是好事。CDN 源(Origin)的变更牵一发动全身,尤其在公共 CDN 模式下,源里的文件会被匿名公开访问。如果做成 UI 按钮,很容易被误点;放在 PowerShell 命令里,至少能留下明确的执行记录,也方便脚本化、批量化和审计。
1.2 CDN 到底替我们做了什么
想理解后面所有操作,先搞清楚一个底层逻辑:CDN 的核心是“内容寻址与就近分发”。用户在访问 SharePoint 页面时,如果静态资源直接由 SharePoint Online 原站返回,每次请求都要走原站链路,还要经过身份验证、权限校验等环节。而启用 CDN 后,JS、CSS、图片、字体这类静态资源会被分发到全球边缘节点,用户从物理距离最近的节点拿数据,响应时间自然就降下来了。
我见过最典型的优化效果对比:未启用 CDN 时,一张 300KB 的图片跨地区加载耗时约 2.1 秒;启用后同一张图从 CDN 节点返回,耗时降到了 400 毫秒左右。当然这只是个参考,真实收益取决于用户分布、资源大小、网络链路,但方向是对的。
1.3 用什么 PowerShell 模块来操作
现在社区里主流、官方推荐的是 PnP.PowerShell。它把 SharePoint Online CDN 相关操作封装成了几个语义清晰的命令:Enable-PnPOffice365CDN、Get-PnPOffice365CDNStatus、Get-PnPOffice365CDNOrigin、Add-PnPOffice365CDNOrigin等。
老项目里常见的 SharePointPnPPowerShellOnline 模块已经停止更新,新环境不要再用。也不要试图用普通 REST API 去直接拼 CDN 配置接口,那套接口对外暴露得很有限,用 PowerShell 是最省心、最不容易出错的方式。
2. 公共 CDN 和私有 CDN 到底怎么选
2.1 一张表看清两种模式
很多第一次接触 SharePoint Online CDN 的人会卡在这里:到底该启用 Public 还是 Private?其实它们不是互斥关系,可以同时开启,关键是搞清楚各自的使用边界。
| 对比项 | 公共 CDN | 私有 CDN |
|---|---|---|
| 访问范围 | 匿名公开,任何人拿到 URL 就能访问 | 需要经过 SharePoint Online 身份验证 |
| 典型内容 | JS、CSS、公开图片、字体、图标 | 受权限控制但需要加速的资产 |
| 默认域名形态 | publiccdn.sharepointonline.com 开头的地址 | 形如 租户名.sharepointcdn.com 的地址 |
| 权限控制 | 不生效,源内文件视为公开内容 | 仍然受 SharePoint 原有权限约束 |
| 适用场景 | 门户首页、营销站点、公共资源库 | 企业内部应用、受限站点集、机密性较低的内部素材 |
公共 CDN 的域名是租户级统一分配的。例如一个租户的公共 CDN 文件地址大致为https://publiccdn.sharepointonline.com/你的租户.sharepoint.com/sites/站点/库目录/文件.jpg。私有 CDN 则通常是对应租户独立域名,看起来是https://你的租户.sharepointcdn.com/sites/站点/库目录/文件.png。
2.2 公共 CDN 最大的坑:权限不生效
公共 CDN 最容易翻车的地方在于:很多人误以为“文件在 SharePoint 库里设置了权限,外部就看不到”。在公共 CDN 源里,这个假设是错的。公共 CDN 的文件一旦能从 CDN 地址访问,就不经过 SharePoint 原有的 ACL 校验,等于把源文件“放到了公网缓存里”。之前有运维同事把一份带员工编号的内部表格放在公共源里,结果测试链接直接匿名打开,虽然内容不至于算机密,但也给所有人上了一课。
所以我的建议很明确:凡是无法公开的内容,一律不要放进公共 CDN 源。要么用私有 CDN,要么干脆不要走 CDN。
2.3 怎么判断自己该用哪个模式
你可以按照下面的过滤条件来决策:
- 资源是否可以被任何人访问?如果答案是“是”,直接公共 CDN。
- 资源是否必须登录后才能看到?如果答案是“是”,考虑私有 CDN。
- 资源是否高度敏感,例如合同、财务表、个人数据?即使私有 CDN 也建议谨慎,CDN 本质上是缓存与加速层,不该成为敏感资产的主要存储形态。
- 资源是否频繁更新且需要强缓存?CDN 都适合静态文件,但如果更新太频繁,要考虑文件名带版本号,避免缓存旧内容。
同时补充一点:公共 CDN 和私有 CDN 可以同时启用。很多企业两边都用,公共 CDN 放门户公开展示素材,私有 CDN 放需要登录访问的内部系统资源。启用操作彼此独立,互不干扰。
3. 从零到一:PowerShell 启用 CDN 完整实操
3.1 准备环境:安装 PnP.PowerShell 模块
在开始之前,你需要有一个安装了 PowerShell 的 Windows 或 macOS/Linux 环境。PnP.PowerShell 支持 PowerShell 7,同时也兼容 Windows PowerShell 5.1,但从我的使用体验看,PowerShell 7 的交互登录和稳定性更好,建议尽量用 7.x。
安装模块的命令很简单:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser Install-Module PnP.PowerShell -Scope CurrentUser -Force第一次安装后,可以用Get-Module -ListAvailable PnP.PowerShell确认版本。注意,模块版本会持续更新,不同版本之间命令参数可能有细微差异,安装完后最好看一眼Get-Command -Module PnP.PowerShell *Office365CDN*,确认你要用的几个命令都在。
3.2 连接 SharePoint Online 管理端点
CDN 是租户级配置,所以连接的时候要连管理站点,而不是普通站点。连接 URL 的格式是:
Connect-PnPOnline -Url "https://你的租户前缀-admin.sharepoint.com" -Interactive-Interactive会弹出浏览器登录窗口,适合管理员手动操作。如果之后要做自动化,也可以使用-ClientId加证书或者-ManagedIdentity的方式,但这里先不展开。
连接成功后,执行命令查看当前 CDN 状态:
Get-PnPOffice365CDNStatus -CdnType Public Get-PnPOffice365CDNStatus -CdnType Private如果之前从未启用过,返回结果会显示当前状态为未启用。结果里的字段主要包含:启用状态、CDN 域名、文件扩展名策略、统计策略等信息。第一次看到这些字段别慌,重点先看 Enabled 那条。
3.3 启用公共 CDN 与私有 CDN
启用操作非常直接,一条命令对应一种模式:
Enable-PnPOffice365CDN -CdnType Public Enable-PnPOffice365CDN -CdnType Private如果你两种模式都要启用,就两条都执行。启用过程一般几秒到几十秒结束,没有交互确认。执行完可以再次用Get-PnPOffice365CDNStatus确认。
有一点需要提醒:启用动作是全局的。一旦启用公共 CDN,系统会自动把租户内一些通用位置登记为默认源,通常包括 masterpage、siteassets 这类固定目录。这些默认源意味着你可能没做任何配置,某些站点下特定目录里的资源已经开始尝试走 CDN。这也是为什么我建议启用后第一时间查看源列表,做到心里有数。
3.4 查看默认源和添加自定义源
查看源列表的命令:
Get-PnPOffice365CDNOrigin -CdnType Public Get-PnPOffice365CDNOrigin -CdnType Private返回的 Origin 列表是完整的租户级源路径数组。你会看到类似*/masterpage、*/siteassets这样的默认值。这里的*是通配符,表示任意站点集下的 masterpage 或 siteassets 库都会被纳入 CDN。
实际项目中,资源通常不会只放在默认库里。比如客户的门户素材放在/sites/portal/Style Library/PublicAssets下面,那就需要手动添加源:
Add-PnPOffice365CDNOrigin -CdnType Public -OriginUrl "/sites/portal/Style Library/PublicAssets"注意几个细节:
OriginUrl必须以/开头,表示站点集根路径下的相对路径,不要写成完整的https://...链接。- 路径中间有空格的话,保持原样就好,PowerShell 会用引号处理。
- 库名建议统一规范。使用
Style Library/PublicAssets这种层级结构,后面维护源列表时比散落的目录清晰得多。 - 支持通配符,例如想匹配所有站点的
SiteAssets库,可以写*/SiteAssets。但通配符不要滥用,范围越大,公共 CDN 暴露的文件就越多。
添加完成后,再次执行Get-PnPOffice365CDNOrigin,确认新增的源已经进入列表。
3.5 验证 CDN 是否真正生效
启用和添加源本身不算结束,关键是验证请求是否真的走了 CDN。最简单的办法:把一个测试文件放到源路径下,然后直接访问它的 CDN URL。
假设测试文件原本位于:
https://你的租户.sharepoint.com/sites/portal/Style Library/PublicAssets/logo.png公共 CDN 对应的访问地址大致是:
https://publiccdn.sharepointonline.com/你的租户.sharepoint.com/sites/portal/Style Library/PublicAssets/logo.png如果你启用的是私有 CDN,对应的地址形如:
https://你的租户.sharepointcdn.com/sites/portal/Style Library/PublicAssets/logo.png把地址输入浏览器或者用curl -I去请求,看返回状态码和响应头。如果返回 200,并且响应头里有 CDN 相关的缓存节点信息,说明已经生效。如果返回 404,大概率是路径拼接错误、源还没同步、或者文件本身不在源路径下。
这里要给一个非常重要的耐心提示:新加源后,CDN 完成全量分发需要时间,官方常见说法是 15 分钟内基本完成,但跨区域边缘节点有时会长一点。所以刚配置完测试 404 不要急着改配置,等一会儿再试。
3.6 调整 CDN 文件扩展名策略和批量操作
CDN 不会所有文件都缓存,扩展名策略会在里面起作用。默认策略通常覆盖了常见静态资源类型:css、js、图片格式、字体格式等。如果业务里有特殊后缀需要纳入,可以用策略命令调整:
Set-PnPOffice365CDNPolicy -CdnType Public -PolicyType IncludeFileExtensions -PolicyValue "css,js,json,webp"执行后再用Get-PnPOffice365CDNPolicy查看生效的策略。不同版本模块对参数值的写法可能有差异,我建议你在测试环境里先小范围改一次,确认没问题再推到生产租户。
如果你要批量添加多个源,写一个简单的循环即可:
$origins = @( "/sites/portal/Style Library/PublicAssets", "/sites/marketing/Style Library/PublicAssets", "/sites/downloads/Style Library/PublicAssets" ) foreach ($origin in $origins) { Add-PnPOffice365CDNOrigin -CdnType Public -OriginUrl $origin }批量操作前务必核对路径列表,因为源一旦加进去,公共 CDN 模式下这些位置的文件就开始公开可见了。我不止一次看到有人因为复制粘贴路径少了一层目录,结果把整个站点集根目录暴露成公共源。所以批量脚本执行前,先打印一遍路径,人眼确认一次再跑。
4. 常见问题与排查实录
4.1 常见问题速查表
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
| 连接时报错或提示权限不足 | 当前账号不是 SharePoint 管理员 | 换成租户 SharePoint 管理员账号,或让管理员授予权限后重试 |
| 执行 Enable 后状态仍然没有变化 | PowerShell 模块版本过旧 | 更新 PnP.PowerShell 到最新版,重新连接后再次执行 |
| 添加源返回路径无效 | OriginUrl 写成了完整 URL,或没有以/开头 | 改成/sites/xxx/库名形式 |
| 访问 CDN URL 返回 404 | 文件不在源路径下,或等待时间不足 | 确认文件路径,等待 15 至 30 分钟后再试 |
| 资源更新后页面仍加载旧版本 | 同名文件被 CDN 缓存 | 文件名带版本号,如app-v2.js,或等待缓存过期 |
| 想启用两个模式却不知道如何操作 | 误以为两者只能选一个 | 两个模式互不冲突,分别执行 Enable 即可 |
| 公共 CDN 下文件明明有权限却还能匿名访问 | 公共 CDN 不做权限校验 | 立刻移除该源,把文件迁出公共源,改用私有 CDN 或普通库 |
4.2 排查实录一:公共源路径写错导致根目录暴露
有一次我给某个站点集配置公共 CDN 源,本意是添加/sites/portal/Style Library/PublicAssets,结果少写了/Style Library/PublicAssets这一段,变成了/sites/portal。命令执行成功后,我下意识去Get-PnPOffice365CDNOrigin看了一眼,发现源列表里多出了一条粗粒度路径。幸好这是测试环境,而且我立刻用Remove-PnPOffice365CDNOrigin把它移除,没有造成实际影响。
这个案例给所有人的启示是:启用公共 CDN 后,第一时间检查源列表,任何你不认识的源都要问清楚来源。尤其要注意那些看起来很“宽”的路径,宽路径意味着大范围文件暴露,必须立即处理。
4.3 排查实录二:页面资源没有走 CDN
还有一次配置完 CDN,客户反馈首页打开还是慢。我检查 CDN 状态、源列表都没问题,单独访问 CDN 地址也正常,但页面元素查看网络请求时发现很多资源还是从原站域名加载的。
后来慢慢梳理出原因:CDN 启用后,SharePoint 会对受支持的页面资产链接做自动重写,但不是所有自定义代码里的 URL 都会自动替换。尤其是一些自定义 WebPart 里硬编码了完整的原站链接,这部分不会因为你启用了 CDN 就自动变成 CDN 地址。最终还是得在前端代码里显式引用 CDN URL,或者通过服务端逻辑生成含 CDN 域名的地址。
这里我的经验是:CDN 配置属于基础设施,只解决“有条件走 CDN 的资源”,不负责“把原站链接全局改写成 CDN 链接”。如果你要让全站资源都走 CDN,必须在页面模板和代码层面保持一致。
4.4 回滚操作:移除源与关闭 CDN
如果某个源不再需要,或者发现配置有误,第一时间移除源:
Remove-PnPOffice365CDNOrigin -CdnType Public -OriginUrl "/sites/portal/Style Library/PublicAssets"如果需要彻底关闭某种模式的 CDN,使用对应的禁用命令:
Disable-PnPOffice365CDN -CdnType Public Disable-PnPOffice365CDN -CdnType Private回滚之后,原有的 CDN URL 不会立刻全部消失。CDN 缓存和边缘节点上的内容还有生命周期,别人如果直接拿着旧 CDN 链接,短时间内仍然可能访问到缓存内容。所以当源里存在敏感文件时,做完移除动作后,不要觉得“当场生效”,要按缓存生命周期去评估残留风险。
5. 长期维护的经验建议
如果你只是临时开一次 CDN,那看前面的操作就够了。但如果你想在一个正式环境里长期跑,有几条经验值得固化到日常流程里。
第一,源目录结构尽量收敛。不要今天加一个/sites/a/assets,明天加一个/sites/b/img,最后源列表乱成一片。我推荐的模式是:公共 CDN 只映射统一的Style Library/PublicAssets这类专门目录,私有 CDN 单独映射业务站点下的受限资源库。目录清晰,后续排查和审计都方便。
第二,文件名带上版本信息。CDN 的本性是“尽量缓存”,而缓存与实时更新天然冲突。像app.js这种固定名字的文件,发布新版本后经常要等缓存过期才能看到变化;但改成app-2025-06-01.js,每次发布都是全新 URL,CDN 会视为新资源立即回源拉取,用户也会拿到最新的内容。这个习惯对体验提升非常明显。
第三,定时巡检源列表和状态。CDN 配置不是一次性的,它会在租户里长期存在。建议写一个简单的巡检脚本,定期输出Get-PnPOffice365CDNStatus和Get-PnPOffice365CDNOrigin的结果,存成日志。这样一旦发现源列表多了异常路径,或者策略被修改,至少能第一时间察觉。
第四,公共 CDN 的安全性永远放在第一位。任何一次新增源的操作前,都问自己:这个目录下所有的文件,是否都允许互联网上的任何人访问?只要有一丝犹豫,就不要放公共 CDN。私有 CDN 虽然带权限校验,但也不是把所有敏感数据丢进去的理由。
最后说一点个人体会:PowerShell 启用 SharePoint Online CDN 这个操作本身很简单,真正有分量的部分是对“公共与私有边界”的理解,以及上线后的验证与维护。配置命令记不住可以查文档,但如果你分不清哪些内容该放进公共源、哪些该留在私有源,那命令执行得再漂亮,也会给环境埋下隐患。希望这篇记录能帮你少走一点弯路,至少别再为了找那个不存在的 UI 开关浪费时间了。