Laravel 集成 React

2019-07-25 11:33:16 Laravel React

Laravel 最为目前最受欢迎的web框架,提供了构建前端的解决方案,旧版的exilir,到目前版本支持的mix,都是帮助开发者快速开发应用。默认使用的前端框架是 vue,这个前端框架是国人写的,门槛低、易上手,很受欢迎,但作为一个后端开发者来说,前端框架已有的三方扩展成熟度是最影响开发效率的,显然 vue 还有很长的路要走,所以准备换用 react 来构建前端。

另外作为个人开发者,打包编译react及其他依赖包会对web服务的网络造成压力,现在有很多免费开放的前端资源 cdn 服务商,我个人很喜欢使用 bootcdn,所以我选择只打包自己的业务逻辑,一些公用的比如 lodash、react、axios 等扩展使用开发cdn提供的。

使用 laravel-cli 创建的项目中已经包含了这些配置,本篇文章不考虑这些自动生成的配置文件,而是从零开始在laravel中加入前端开发链,学习才是主要目的。

使用laravel-mix

laravel-mix 是基于webpack二次开发的工具包,最大的优势就是简化配置,可以快速进入业务开发。laravel-cli创建的项目已经内置了mix,所以这一步的所有操作框架已经帮我们做了,我们看下框架都做了什么:

创建mix配置

mix配置就相当于原来的webpack配置,只不过是简化再简化后的结果:

在项目根目录中创建文件 webpack.mix.js,内容为:

const mix = require('laravel-mix')

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

上面的代码逻辑很明了,将 resources/js/app.js 编译打包并写入 public/js 目录(文件名不变), 将 resources/sass/app.scss 进行 scss 转换后写入 'public/css 目录(文件名不变)。

初始化node环境

直接使用npm或yarn进行初始化,这里我使用了yarn:

yarn init

执行完成后根目录下多了几个文件:

  • package.json node项目配置
  • node_models/ node依赖的包
  • yarn.lock yarn依赖配置

安装必要依赖

我们只需要安装 laravel-mix 一个依赖,其运行过程中会自动安装其他需要的依赖包:

yarn add laravel-mix

配置编译辅助命令

编译静态资源需要配置一些参数,可以将常用的命令配置到 package.json 文件中的 scripts 下:

"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },

开始编译

打包开发包:

yarn dev

打包优化包:

yarn prod

打包并监听文件变化:

yarn watch

使用 React

加入cdn资源

web 中使用 react 需要用到两个包,react 和 react-dom,需要将这两个包加入到 HTML 中。

在 cdn 文件列表中可能会看到有两种类型的脚本: cjs 和 umd,浏览器中直接引用必须使用umd版本。

创建一个简单的 React 组件

js 目录下创建一个文件 Hello.jsx,在里面创建 Hello 组件。

由于 react 是通过cdn引入的,所以不能像node应用中一样通过require来引入依赖包,而是应在通过全局作用域 window.React 来引用

const {Component} = require('React')

export default class Hello extends Component {
    render() {
        return (
            <div>hello, React</div>
        )
    }
}

然后在 app.js 中引入这个文件

const Hello = require('./Hello')

修改 mix 配置

直接进行打包的话会报错,因为打包器不认识jsx的语法,我们只需要将 mix.js 调用改为 mix.react 即可。

另外这样打包会将 React 也打包进目标文件,会导致目标文件的体积增大,可以使用 webpack 的 externals 配置将依赖包排除在打包流程之外。

注意:所有需要排除的包必须全部使用require方式引入,而不能使用ES6中的import

// mix.js('resources/js/app.js', 'public/js')
mix.webpackConfig({
    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM',
    }
}).react('resources/js/app.js', 'public/js')

使用 React 组件

将组件打包后就可以使用了

在页面中使用定义的组件

ReactDOM.render(<Hello />, document.getElementById('app'))

刷新页面打开 console 会看到报错了,提示 Hello 不存在,原因是 webpack 将打包文件中所有全局的定义都封装到了一个函数中,在外面是无法访问这些函数中的定义的。

app.js 引入 Hello 类之后将其设置为 window 的属性,这样就相当于全局可见了:

const Hello = require('./Hello')
window.Hello = Hello

后记

欢欢喜喜的将react环境搭建好,到修改原有的逻辑时傻了眼。原来使用 vue 可以很自然的使用 html 中的元素作为模板,这样可以可 laravel-blade 模板完美结合,react 是完全重新渲染某个节点,模板要在js中定义(jsx),相当于和blade渲染的html无法互通。不得已还是要是用 Vue。

使用 Vue 的 mix 配置更为简单,不再赘述。