当前位置: 首页 > news >正文

怎样做网站性能优化上海装修公司排名统帅

怎样做网站性能优化,上海装修公司排名统帅,通信部门网站备案证明,单页面 网站怎么做的这篇文章也可以在我的博客中查看 页面路由 是什么 页面路由是指从url顺着网线砍到网站内容的途径#xff0c;说人话就是地址与页面的映射。 就像真实世界的地址一样#xff0c;我要找你#xff0c;必须知道你的地址。 在网站中#xff0c;通过地址找内容的机制#xf…这篇文章也可以在我的博客中查看 页面路由 是什么 页面路由是指从url顺着网线砍到网站内容的途径说人话就是地址与页面的映射。 就像真实世界的地址一样我要找你必须知道你的地址。 在网站中通过地址找内容的机制就称为页面路由(Route) 常见的路由有两种方式 页面地址映射到文件夹层级地址页面地址映射到数据结构 WordPress的路由 WordPress采用的是第二种。 在WordPress里几乎所有的页面访问其实都是在访问/index.php 而之所以能够输出不同的结果是依靠读取查询字符串中的数据再在template_includes中做判断以加载不同的模板文件。 打个比方www.mysite.com/page/2/访问主页的第二页 事实上等价于访问www.mysite.com/index.php?paged2 它唯一的好处就是更好看了有利于SEO 再比如www.mysite.com/0000/00/00/hello-world/访问第一篇文章 事实上你拿www.mysite.com/index.php?p1也可以跳转到同样的地址 所以通过添加查询字符串标记能够检测并跳转到不同的模板文件。 这是WordPress内置的做法。 为什么 说了半天为什么需要实现页面路由 WordPress提供的路由规则不香吗 因为WordPress只提供了默认的路由路径而没有直接做法可以往里面添加自己的路由。 比如我想在/game路径下添加一个很Cool的html小游戏你会发现做不到。 WordPress中一切皆是文章你需要展示一个东西那它必须先成为一篇文章。 你当然也可以创建一个名为game的页面(page)然后添加自定义模板 但这一步本身有必要存在吗 有些东西它本身就不好被描述成文章比如小游戏一些功能页面…… 因此虽然WordPress不提供但我们仍然需要自定义的页面路由 我们需要漏油 我们需要漏油 我们需要漏油 本文内容 当然我们也可以使用查询字符串的形式添加新的路由 可以但不优雅 因为这始终是污染查询字符串的结构了 虽然概率极低但我还是并不希望丑陋的?the_long_long_query_var1会被偶然发现又或者是?xid1与其它插件注册的查询字符串冲突 因此本文 实现真·页面路由 不需要创建任何page或者post文件通过url直接定位到php模板文件相当于扩充WordPress的主题层级模板 不使用查询字符串作为标志不破坏WordPress的生态任何function, hook该生效的还是生效 实现路由 old-school做法 WordPress已经有20年历史了byd这种做法一直是实现页面路由的主流做法 但不管怎么说这种查询字符串标记的做法算是鼻祖了 简单来说就是 使用add_rewrite_rule添加重写规则使用一个标志查询字符串kbp_book_finder1作为访问了www.mysite.com/bookfinder/的标志 function bookfinder_rewrite() {add_rewrite_rule(^bookfinder/?$, index.php?kbp_book_finder1, top); } add_action(init, bookfinder_rewrite);function bookfinder_query_vars($vars) {$vars[] kbp_book_finder;return $vars; } add_filter(query_vars, bookfinder_query_vars);在template_includehook中查找该标志然后跳转到php模板文件 function bookfinder_template($template) {if (!is_404() get_query_var(kbp_book_finder))return locate_template(/path/to/your/file/book-finder.php);return $template; } add_filter(template_include, bookfinder_template);本文做法 由于不爽这个查询字符串很久了所以萌生了新的想法 既然查询字符串的存在意义只是为了标志那为什么不用其它变量作为标志呢 经过反复尝试发现是可以的至少现在用着没出问题 出问题了再删文章 分析问题 首先一个路由最重要的是什么 路径行为结果 没错所以我们需要关注的是 访问什么地址服务器做出什么响应然后跳转/加载到哪个页面 这几个过程分散在WordPress生命周期的不同时期 为了实现路由的目标我们需要程序知道目前所加载的到底是什么页面 因此为每个路径加入一个专门标志也是必须的 具体实现 位置标记 首先解决最迫切的“我在哪”问题 WordPress没有为自定义页面实现路径标记信息或系统因此我们需要手动记录 查询字符串就是一个做法但其实我们完全可以不用它 我们直接定义一个变量记录目前的路由路径并配套若干访问相关的函数 名称空间不好存变量我习惯使用静态类充当单例 class Router {protected static ?string $activePath null;protected static function setActivePath($path){Router::$activePath $path;}protected static function atPath($path): bool{return !is_404() Router::$activePath $path;}protected static function atAnyPath(): bool{return Router::$activePath ! null;} }注册路由 接下来实现最关键的是实现registerRoute方法负责 定义路径路径相关的重定向如果没重定向加载哪个php文件 对于每个注册的路由都需要各自定义这些功能函数 这些函数都是上下文注册的路径有关的因此此时闭包很有用 public static function registerRoute(string $routePath, string $template, ?callable $redirect null) { }接下来逐个分析需要的几个闭包函数 老朋友add_rewrite_rule 1.需要添加重写规则才能够访问否则直接404。因此我们直接摆烂跳转到不附加任何参数的index.php 2.注意优先级要设置为top否则大概率不生效 3.更改重写规则需要刷新永久链接 add_action(init, fn () add_rewrite_rule($routePath, index.php, top));匹配url并设置标记变量 为了在生命周期中尽快生效使用最早能够获得url的钩子parse_request add_action(parse_request, function (wp) use (routePath) {if (preg_match(routePath, wp-request))Router::setActivePath(routePath); });检测标记并选择性进行页面加载 add_filter(template_include, fn ($tpl) Router::atPath($routePath) ? $template : $tpl);加入重定向逻辑回调函数 有时候我们希望加入与页面绑定的重定向逻辑虽然在任何位置都可以添加重定向逻辑但既然是页面相关的逻辑还是提供一个专门的入口 注意重定向后需要退出本次执行但该函数内不得获知能否成功重定向因此这需要在传入的回调函数中处理见后文示例 if ($redirect)add_action(template_redirect, fn () Router::atPath($routePath) $redirect());路由参数 有时候会有从url读取参数值的需求 借鉴WordPress REST API的做法我们可以用正则表达式的分组匹配实现参数提取 在上步parse_requesthook中增加接收匹配结果的$matches变量并存储到Router中 我增加了filterMatches函数只保留命名分组 class Router {public static ?array $data null;public static function registerRoute(string $routePath, string $template, ?callable $redirect null){add_action(parse_request, function ($wp) use ($routePath) {if (preg_match($routePath, $wp-request, $matches)) {Router::setActivePath($routePath);Router::$data Router::filterMatches($matches);}});}protected static function filterMatches($matches){return array_filter($matches, fn ($key) is_string($key), ARRAY_FILTER_USE_KEY);} }此时registerRoute所有代码合在一起是这个样子的 public static function registerRoute(string $routePath, string $template, ?callable $redirect null) {if (!$routePath) return;add_action(init, fn () add_rewrite_rule($routePath, index.php, top));add_action(parse_request, function ($wp) use ($routePath) {if (preg_match($routePath, $wp-request, $matches)) {Router::setActivePath($routePath);Router::$data Router::filterMatches($matches);}});add_filter(template_include, fn ($tpl) Router::atPath($routePath) ? $template : $tpl);if ($redirect)add_action(template_redirect, fn () Router::atPath($routePath) $redirect()); }使用示意 重要提示 更改重写规则后需要更新页面规则 在设置菜单中找到永久链接点击保存即可刷新 此时我们已经完成了路由的核心逻辑可以比较方便地使用 // https://my.site/bookfinder/ Router::registerRoute(^bookfinder/?$,locate_template(/path/to/file1.php) ); // https://my.site/user/ Router::registerRoute(^user/?$,locate_template(/path/to/file2.php),fn () !is_user_logged_in() wp_redirect(get_user_login_url()) and exit ); // https://my.site/date/1970/01/01/ Router::registerRoute(^date/(?Pyear\d{4})/(?Pmonth\d{2})/(?Pday\d{2})/?$,locate_template(/path/to/file3.php), );对于参数可以在输出页面时按以下方式获取 名称就是路由中的正则命名分组 print_r(Router::$data[year]); print_r(Router::$data[month]); print_r(Router::$data[day]);问题修复 至此已经实现了路由功能但据我所测试仍存在几个小问题 末尾斜杠 按上面的做法url无法按照Permalink规则跳转到斜杠或非斜杠版本 无论Permalink设置都是默认跳转到斜杠版本 为什么 原因在于add_rewrite_rule跳转到不带参数的index.php最后会被WordPress识别为网站首页($wp_query-is_home true) 根据RFC 7230http请求的path必须以/开头即使它的内容为空。相关资料 因此对于形如https://mysite.com/的站点主页而言最后的斜杠是必须的 虽然目前浏览器都会在访问时自动给你补/ 但WordPress很严谨地遵守了这一规定将is_home视为主页的路径全部补上了斜杠 这是他们redirect_canonical的源码 } elseif ( is_front_page() ) {$redirect[path] trailingslashit( $redirect[path] ); }is_front_page()间接检测了is_home() 然而并不是所有的主页都以空path结束也不是所有is_home的情况它就真的是home 比如我们现在的情况我们需要加入一个不属于任何文章的页面我们只能把它归于is_home 解决办法 找一个$wp_query-is_home被设置完后的钩子尽快将它设置为false WordPress使用$wp_query用作主查询翻看源码后发现查询后会立马调用handle_404() 因此我们可以利用这个过程的pre_handle_404hook将它设置为false add_filter(pre_handle_404, function ($suppress, $wp_query) use ($routePath) {if (Router::atPath($routePath))$wp_query-init_query_flags();return $suppress; }, 10, 2);我们使用了init_query_flags()将所有conditional tags设置为false。 这是合理的因为它本就不属于内置的任何状态 事实上受影响的只有is_home()其它本来就是false 跳过主查询 既然自定义路由页面不存在任何post/page我们其实没必要进行主查询 这个操作可以帮助减少5次左右查询次数 但我们希望尽可能保持WordPress原有的功能和hook只跳过主查询 也就是跳过查询过程文档所述的4.3步骤 4.3 Convert the query specification into a MySQL database query, and run the database query to get the list of posts, in function WP_Query-get_posts(). Save the posts in the $wp_query object to be used in the WordPress Loop. 抑制主查询 因此我们可以选择查询执行前最近的一个hook将查询语句修改成无效 add_filter(posts_request, fn ($request, $query) Router::atPath($routePath) $query-is_main_query() ? false : $request, 10, 2);防止返回404 我们之前不会返回404主要是因为有两个条件 主查询有返回结果$wp_query-is_home true 然而经过我们前面的一堆优化两个条件都不再满足 因此WordPress会在handle_404()直接返回404 not found 那我们抑制它的作用就好了 同样在pre_handle_404hook。修改原有的代码返回true表示抑制404处理 add_filter(pre_handle_404, function ($suppress, $wp_query) use ($routePath) {if (!Router::atPath($routePath))return $suppress;$wp_query-init_query_flags();return true; }, 10, 2);全场最佳pre_handle_404 不起眼、看似毫不相关的hook帮我们解决了一万个问题 条件性回调 上面的做法中我们为每个可能的路由路径都加入了hook并在每个回调函数中先检测自身是否为活跃路由如果时再执行操作。 但其实没有必要为每个路径都加入hook因为一次访问只有1个活跃路径 因此在设置活跃路径时它必然就是本次的路由路径我们只为它加入hook就可以了。 不过需要注意不能重复设置活跃路由否则就乱套了一般也不会出现设置多次的情况吧 代码就留到最后了 最终版本 经历了九九八十一难终于修成了正果 来看看最后版本的Router吧 class Router {/*** 当前活跃的路由路径*/protected static ?string $activePath null;/*** 活跃路由的参数*/public static ?array $data null;/*** 注册一个路由路径* param string $routePath 路径正则表达式站点名后的路径部分* param string $template 加载的php文件* param callable $redirect 可选的重定向逻辑在该路由生效时在template_redirect触发*/public static function registerRoute(string $routePath, string $template, ?callable $redirect null){if (!$routePath)return;/*** 记录到重写规则*/add_action(init, fn () add_rewrite_rule($routePath, index.php, top));/*** 匹配url并设置标记变量使用最早能够获得url的钩子*/add_action(parse_request, function ($wp) use ($routePath, $template, $redirect) {if (preg_match($routePath, $wp-request, $matches)) {Router::setActiveRoute($routePath, $template, $redirect);Router::$data Router::filterMatches($matches);}});}public static function init(){// 如果是初次刷新add_action(after_switch_theme, flush_rewrite_rules);}protected static function setActiveRoute(string $routePath, string $template, ?callable $redirect null){Router::$activePath $routePath;/*** 更改页面模板*/add_filter(template_include, fn () $template);/*** 加入重定向逻辑*/if ($redirect)add_action(template_redirect, fn () $redirect());/*** 抑制主查询*/add_filter(posts_request, fn ($request, $query) $query-is_main_query() ? false : $request, 10, 2);/*** 两件事* 1. 将$wp_query-is_home设置为false以免redirect_canonical中被标志为home页面强行加末尾斜杠* 2. 抑制由于“抑制主查询is_homefalse”产生的404*/add_filter(pre_handle_404, fn ($_, $wp_query) $wp_query-init_query_flags() || true, 10, 2);}protected static function filterMatches($matches){return array_filter($matches, fn ($key) is_string($key), ARRAY_FILTER_USE_KEY);}// 下面的函数没用到但你可能需要这些函数做一些控制public static function atPath($path): bool{return !is_404() Router::$activePath $path;}public static function atAnyPath(): bool{return Router::$activePath ! null;}public static function activePath(): ?string{return Router::$activePath;} }其中init函数用于主题加载时刷新永久链接缓存你也可以加入更多初始化工作 最后再强调一次add_rewrite_rule需要刷新永久链接缓存才生效 如果你还是忘记了那只能祝你好运了:) 参考资料 WordPress: How to create a rewrite rule for a file in a custom pluginDisable the MySQL query in the main queryQuery OverviewTrailing-slash or not in the HomepageDo HTTP paths have to start with a slash?
http://www.dnsts.com.cn/news/79626.html

相关文章:

  • 那家公司做网站免抵退税在哪个网站做
  • 广东网站建设咨询电话深圳 学习网站
  • 商丘企业网站建设团队太康县城乡建设局规划网站
  • 网站开发心路历程wordpress role
  • 淘宝网的网站设计特色网站导航下拉菜单代码
  • 一个网站是如何知道是谁来访问电影网站如何做不侵权
  • 怎样上传网站vue.js2.5 pc网站开发
  • 金泉网做网站电话360个人网站建设
  • 挂号网站建设优化好的网站做企业网站
  • 物流网个人网站建设韶关网站建设墨子
  • 设计师网站登录入口办公室装修费怎么做账
  • 主视觉设计网站软文营销什么意思
  • 南京做企业号微网站营销网站快速过备案
  • 建设一个小游戏网站建筑工程公司组织架构图
  • 营销型网站具备的二大能力织梦建站模板
  • 帝国网站源码手机广安公司网站建设
  • 优化网站结构手把手指导做网站
  • 萍乡网站设计公司o2o平台运营是什么意思
  • 个人展示网站网站根目录验证文件
  • 郑州网站设计报价表做产品推广哪个网站好
  • 域名注册平台的网站怎么做阜阳建设网站
  • 做网站就用建站之星乐清企业网站制作
  • 我的网站百度找不到了动漫设计网站
  • 网站建设用户核心中铁建设集团有限公司华东分公司
  • 临淄关键词网站优化培训中心唐山网站排名推广
  • 怎么在记事本上做网站中国室内设计师联盟网站
  • 黄岐建网站wordpress 屏蔽爬虫
  • 可信网站多少钱全媒体运营技巧和工具
  • 竞价网站单页面wordpress培训模板下载
  • 建设一个房产网站赚钱吗泰安网签查询系统