PHP Laravel NGINX html css Bootstrap Python Symfony Apache Windows linux jquery Django ASP vanilla Slim vagrant docker Homestead MySQL Redis Git SVN ssh Root vim PhpStorm Pycharm sass less PHP Laravel android html css Vue Angular React NGINX html css Javascript

Laravel 如何使用 React.js + HMR(Hot Module Replacement)

原创

原创不易 ~ 转载请注明出处哦

Laravel作为一款强大的PHP框架,从2018年开始看到国内越来越多的朋友希望接触与使用它。后端开发的教程在官方文档上已经写的很详细了,那么如果要在Laravel项目中进行前端开发呢?

Laravel的官方文章中,我们看到,官方推荐使用Vue.js来进行前端开发,而Vue.js在国内确实是如日中天,在github10w+的星星数,也确实代表了它的受欢迎程度(虽然可能有一部分是国人基数庞大的原因,不过说实话,Vue在国外也是非常受欢迎的)。

然而,今天我并不打算介绍LaravelVue的开发流程,因为Laravel默认前端presets其实已经是Vue了。今天我要来介绍一下,在Laravel中如何使用React.js进行开发。

不知道React朋友请先面壁3分钟再回来。与VueAngular不同,React采用的是数据单向绑定,开发中多使用jsx(极为好用),个人认为代码更为干净与舒服。

由于我们今天主要讲解的是如何在Laravel中使用React进行开发,并使用HMR进行即时加载,对比不同框架和库的话我就不多说了。

好了,那么我们这就开始。我把文章分两个步骤来进行讲解。


创建并运行一个新的React应用


首先,我们新建一个Laravel项目:

$ laravel new eagles_new_project

完成后,我们进入我们的项目根目录输入以下命令:

$ php artisan preset react

由于默认的前端presetsVue,我们需要使用上面的明令将presets变更成react

完成后,我们发现resources/js文件夹下,app.jscomponents中的样本组件都发生了变化。

我们直接把app.js清空,并将components中的组件删除。别担心,我们会重新写新的组件。

components文件夹,我们新建一个名为NameCard的组件

//resources/components/NameCard.js
import React from 'react'

const NameCard = () => (
    <div>
        <div>
            <h1>My name is Eagle L!</h1>
        </div>
    </div>
)

export default NameCard

这里有两个点需要注意。
第一由于我们使用了JSX,所以必须引入React
第二我们使用了React中的Function Component

接下来,我们将app.js里写入以下代码:

import React from 'react'
import ReactDOM from 'react-dom'
import NameCard from './components/NameCard'

if (document.getElementById('root')) {
  ReactDOM.render(<NameCard />, document.getElementById('root'));
}

现在我们基本的组件和入口app.js都已经有了,我们需要增加一条路由。打开routes/web.php,增加以下路由:

Route::view('react-hmr', 'react-hmr');

这里我们使用了Route::view()/react-hmr这条路径使用react-hmr这个view文件来渲染。

注意,默认的View文件全部存放在resources/views这个目录下,也就是说,我们需要在目录下,创建一个名为react-hmr.blade.php的文件:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <meta content="Eagle L." name="author" />

    <title>Having fun with React.js</title>
</head>
<body>
    <div id="root"></div>
    <script src="{{ mix('js/app.js') }}"></script>
</body>
</html>

可以看到,React中不能直接将组件写到我们的View中,我们需要使用ReactDOM.render()将我们的组件加载出来。

注意<script src="{{ mix('js/app.js') }}"></script>一行是我们应用的入口,即我们之前创建的含有ReactDOM.render()app.js文件。

目前我们有了路由,页面以及js文件,我们还无法访问我们的应用。细心的你一定注意到了mix('js/app.js')这个函数。

mix函数是一个名为Laravel Mix的插件提供的,用于集成及封装Webpack功能,让我们不用人工地去创建webpack.config.js这个配置文件,快速实现编译及打包。

mix('js/app.js')这行代码会输出我们编译过的app.js地址,但是我们需要在mix的配置中指明我们的编译路径。

在我们的项目根目录里,找到webpack.mix.js,在里面添加如下代码:

let mix = require('laravel-mix');


/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.react('resources/js/app.js', 'public/js')

可以看到,我们将resources/js/app.js编译后输出到public/js文件夹中,所以mix('js/app.js')输出的路径其实就是我们编译后的这个地址。

那么现在我们输入以下命令进行编译

$ npm run dev

编译完成后,我们打开浏览器,访问我们的项目地址,就可以看到我们刚刚创建的React项目了。注意,Laravel的项目访问地址请参考

Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead)

安装react-hot-loader并启动webpack-dev-server


上一步我们已经完成了React应用的基本配置,现在我们想要在修改我们的组件时,组件自动实时刷新,不需要手动刷新浏览器,并且组件的state不丢失,这样可以极大地提高我们的开发效率。

那么首先我们安装react-hot-loader

# 推荐使用yarn
$ yarn add react-hot-loader -D

# 或着
$ npm install react-hot-loader

注意我们安装时可以不需要加上-D或者--save-dev,因为官方指明了:

Note: You can safely install react-hot-loader as a regular dependency instead of a dev dependency as it automatically ensures it is not executed in production and the footprint is minimal.

接下来我们在项目根目录下创建一个名为.babelrc的文件(注意有.)并添加以下配置:

{
  "plugins": ["react-hot-loader/babel"]
}

完成后,我们需要修改我们的组件。我们的根组件是NameCard,而我们需要将其包裹在hotHOC中:

//resources/components/NameCard.js
import { hot } from 'react-hot-loader/root'
import React from 'react'

const NameCard = () => (
    <div>
        <div>
            <h1>My name is Eagle L!</h1>
        </div>
    </div>
)

export default hot(NameCard)

这样我们的准备工作就完成了!接下来我们只需要启动webpack-dev-server就可以了。

mix很周到地已经为我们准备好了命令:

$ npm run hot

现在我们再次访问我们的项目地址,打开开发者工具,切换到console中,你会看到如下图中的信息:

hmr.png

这说明HMR已经生效了!我们更改一下我们的组件试试:

const NameCard = () => (
    <div>
        <div>
            <h1>My english name is Eagle!</h1>
        </div>
    </div>
)

保存切换回浏览器,我们会看到我们的组件内容已经自动刷新了,开发者工具的console中,我们看到HMR的更新信息:

hmr-update.png

这样一来,我们就不需要手动刷新浏览器了,非常地方便!

最后要说明的几点,
第一,我们的入口文件一定要使用mix函数来指定路径,否则HMR无法正常工作。
第二,不能在homestead虚拟机环境中运行npm run hot,必须在虚拟机环境外运行,
第三,Windows下用户需要在webpack.mix.js中添加以下代码修复路劲多一个斜杠的问题。

Mix.listen('configReady', (webpackConfig) => {
  if (Mix.isUsing('hmr')) {
    // Remove leading '/' from entry keys
    webpackConfig.entry = Object.keys(webpackConfig.entry).reduce((entries, entry) => {
      entries[entry.replace(/^\//, '')] = webpackConfig.entry[entry];
      return entries;
    }, {});

    // Remove leading '/' from ExtractTextPlugin instances
    webpackConfig.plugins.forEach((plugin) => {
      if (plugin.constructor.name === 'ExtractTextPlugin') {
        plugin.filename = plugin.filename.replace(/^\//, '');
      }
    });
  }
});

好了,今天的教程就写到这里,欢迎留言探讨;)


正在加载验证码......
请先完成验证