在 Laravel 应用中使用 pjax 进行页面加速

说明

PHPHub 使用 pjax 来加速网页的加载, 这篇文章是在开发完此功能后做的笔记.

什么是 Pjax

        .--.
       /    \
      ## a  a
      (   '._)
       |'-- |
     _.\___/_   ___pjax___
   ."\> \Y/|<'.  '._.-'
  /  \ \_\/ /  '-' /
  | --'\_/|/ |   _/
  |___.-' |  |`'`
    |     |  |
    |    / './
   /__./` | |
      \   | |
       \  | |
       ;  | |
       /  | |
 jgs  |___\_.\_
      `-"--'---'

项目地址见 这里, 官方的介绍:

pushState + ajax = pjax

详细的解释请看 知乎上的这个问题, 或者自己去查阅资料.

简单点描述, 就是利用 ajax 技术去服务器获取文档, 在不刷新浏览器页面的情况下, 更新当前页面, 并且能保证页面的 jscssassets 文件不会被重复加载, 然后利用浏览器提供的 pushState 功能, 对 URL 进行更新, 并能保证用户通过点击 back 按钮回溯到历史页面.

注意: 并不是所有浏览器都支持 pushState, 关于浏览器的兼容请见这里, 当浏览器不兼容的时候, 会自动使用原始的浏览方式进行访问.

为什么要使用 Pjax

因为不需要整个页面刷新, 并且 assets 文件都不需要重新加载, 很大程度上提高了页面的加载速度.

服务端安装 rcrowe/Turbo

使用 package rcrowe/Turbo .

安装 rcrowe/Turbo

composer.json 里的 require 属性下添加:

"rcrowe/turbo": "0.2.*"

然后 composer update 或者 composer install

配置 Providers

编辑 app/config/app.php 文件, 在选项 providers 数组里面添加:

"Turbo\Provider\Laravel\TurboServiceProvider",

下载 pjax.js

public\js 文件夹下

wget https://raw.github.com/defunkt/jquery-pjax/master/jquery.pjax.js

然后在模版里面加载此文件

<script src="{{ cdn('js/jquery.pjax.js') }}"></script>

最后页面里调用:

$(document).ready(function()
{
    $(document).pjax('a', 'body');
});

上面的代码解释是, 把所有的 a 标签的点击事件截获, 如果当前浏览器支持 pjax 的话, 发送一个 ajax 请求, 并把参数 _pjax=body 带过去.

如果一起顺利的话, 在 Chrome 的 debuger 里能看到类似于这样的请求:

至此, 已经顺利配置完毕.

添加加载动画

接下来要来添加一个页面加载的动画, 效果如下:

添加 nprogress

使用 rstacruz/nprogress 来实现.

添加的方法是 下载 文件, 然后把 nprogress.jsnprogress.css 添加到页面中:

    <script src='nprogress.js'></script>
    <link rel='stylesheet' href='nprogress.css'/>

调用

修改上面的代码, 修改后的代码如以下:

$(document).ready(function()
{
    $(document).pjax('a', 'body');

    $(document).on('pjax:start', function() {
      NProgress.start();
  });
  $(document).on('pjax:end', function() {
      NProgress.done();
      self.siteBootUp();
  });
});

这样的话, 每一次点击页面的时候就会有很酷炫的效果了. :dancer:


关于此次的代码修改, 见这个 commit.

--- EOF --


欢迎关注 LaravelTips, 这是一个专注于为 Laravel 开发者服务, 致力于帮助开发者更好的掌握 Laravel 框架, 提升开发效率的微信公众号.

摈弃世俗浮躁,追求技术精湛
本帖已被设为精华帖!
Summer
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 12
Summer

@Cooper 貌似改了挺久的了, 考虑到 seo 友好.

9年前 评论
Summer

@isPythoner 你是在说访问 phphub 的时候吗?

9年前 评论
Summer

@isPythoner ?_pjax=body 这个参数是 pjax 自动添加的, TA 会判断浏览器是否支持, 如果支持的话, 就添加, 否的话就如正常的访问.

至于外部 js 加载慢的, 尽量把 js 放到页面底部, 这样就不影响页面渲染.

9年前 评论
Summer

@lovecn 好建议.

9年前 评论
Summer

@baocaixiong 刚刚解决了这个问题, 原因见这里: Github issue

9年前 评论
Summer

@liball 你可以去 http://segmentfault.com/t/pjax 发个问题, 详细描述, 然后把链接贴给我.

9年前 评论

我也来学习学习

7年前 评论
Mantis

不支持laravel5.1吗?会报错。。。

7年前 评论

我点击左侧菜单中的a链接,载入指定连接的页面后,当我再次f5刷新页面后,只能显示载入的页面内容。这时候样式,js,其他页面内容都没了。这应该怎么解决啊

7年前 评论
sunrui318 3年前

这个需要后端识别_pjax请求吗,或者说_pjax请求和普通请求后端返回的数据是不是不一样的?前者返回的是页面的部分内容,后者返回的是整个页面,是这样理解吗?那后端应该如何处理这个逻辑呢?

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!