manyou/inertia-bundle

Symfony 对 Inertia.js 的适配器

安装: 44

依赖者: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 38

类型:symfony-bundle

v2.4.4 2024-05-17 09:35 UTC

README

CI StyleCI

这是一个基于 inertia-laravel 的 Inertia.js 服务器端适配器,但适用于 Symfony 5 和 6。

警告

寻找新的所有者

由于我不再使用 Symfony 或 PHP,我在寻找想接管这个项目开发的人。目前该项目未维护。

安装

首先,确保您已经安装了 twig、encore 和 serializer 食谱

composer require twig encore symfony/serializer-pack

使用 Composer 安装

composer require rompetomp/inertia-bundle
yarn add @inertiajs/inertia

设置根模板

使用 Inertia 的第一步是创建一个根模板。我们建议使用 app.html.twig。此模板应包括您的资产,以及 inertia(page) 函数

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    {% block stylesheets %}
        {{ encore_entry_link_tags('app') }}
    {% endblock %}
    {{ inertiaHead(page) }}
</head>
<body>
{{ inertia(page) }}
{% block javascripts %}
    {{ encore_entry_script_tags('app') }}
{% endblock %}
</body>
</html>

inertia(page) 函数是一个创建基础 div 的辅助函数。它包括一个包含初始页面信息的 data-page 属性。它看起来像这样

<div id="app" data-page="<?php echo htmlspecialchars(json_encode($page)); ?>"></div>

如果您想使用不同的根视图,可以通过创建一个 config/packages/rompetomp_inertia.yaml 文件并包括此配置来更改它

rompetomp_inertia:
  root_view: 'name.html.twig'

设置前端适配器

在此处找到您想要使用的任何前端适配器 https://github.com/inertiajs。README 中使用了 Laravel 的 Webpack Mix。将其转换为 Webpack Encore 不会很困难,只需遵循此处的文档:https://symfony.com.cn/doc/current/frontend.html

Webpack Encore 示例

对于 Vue

yarn add @inertiajs/inertia-vue
const Encore = require('@symfony/webpack-encore')
const path = require('path')

if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}

Encore
  .setOutputPath('public/build/')
  .setPublicPath('/build')
  .enableVueLoader()
  .addAliases({
    vue$: 'vue/dist/vue.runtime.esm.js',
    '@': path.resolve('assets/js')
  })
  .addEntry('app', './assets/js/app.js')
  .splitEntryChunks()
  .cleanupOutputBeforeBuild()
  .enableSourceMaps(!Encore.isProduction())
  .enableVersioning(Encore.isProduction())
  .disableSingleRuntimeChunk()
  .configureBabel(() => {}, {
    useBuiltIns: 'usage',
    corejs: 3
  })
  .enableSassLoader()

module.exports = Encore.getWebpackConfig()
//assets/app.js
import { createInertiaApp } from '@inertiajs/inertia-vue'
import Vue from "vue";

createInertiaApp({
    resolve: name => require(`./Pages/${name}`),
    setup({ el, app, props }) {
        new Vue({
            render: h => h(app, props),
        }).$mount(el)
    },
})

对于 React

const Encore = require('@symfony/webpack-encore')
const path = require('path')

if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}

Encore
  .setOutputPath('public/build/')
  .setPublicPath('/build')
  .enableReactPreset()
  .addAliases({
    '@': path.resolve('assets/js')
  })
  .addEntry('app', './assets/js/app.js')
  .splitEntryChunks()
  .cleanupOutputBeforeBuild()
  .enableSourceMaps(!Encore.isProduction())
  .enableVersioning(Encore.isProduction())
  .disableSingleRuntimeChunk()
  .configureBabel(() => {}, {
    useBuiltIns: 'usage',
    corejs: 3
  })
  .enableSassLoader()

module.exports = Encore.getWebpackConfig()

对于 Svelte

const Encore = require('@symfony/webpack-encore')
const path = require('path')

if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}

Encore
  .setOutputPath('public/build/')
  .setPublicPath('/build')
  .addLoader({
    test: /\.(svelte)$/,
    use: {
      loader: 'svelte-loader',
      options: {
        emitCss: true,
        hotReload: true,
      },
    },
  })
  .addAliases({
    '@': path.resolve('assets/js')
  })
  .addEntry('app', './assets/js/app.js')
  .splitEntryChunks()
  .cleanupOutputBeforeBuild()
  .enableSourceMaps(!Encore.isProduction())
  .enableVersioning(Encore.isProduction())
  .disableSingleRuntimeChunk()
  .configureBabel(() => {}, {
    useBuiltIns: 'usage',
    corejs: 3
  })
  .enableSassLoader()

const config = Encore.getWebpackConfig()
config.resolve.mainFields = ['svelte', 'browser', 'module', 'main']
config.resolve.extensions =  ['.wasm', '.mjs', '.js', '.json', '.jsx', '.vue', '.ts', '.tsx', '.svelte']

module.exports = config

制作 Inertia 响应

要制作 Inertia 响应,在控制器中注入 Rompetomp\InertiaBundle\Service\InertiaInterface $inertia 类型提示,并使用该服务上的 render 函数

<?php
namespace App\Controller;

use Rompetomp\InertiaBundle\Service\InertiaInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DashboardController extends AbstractController
{
    public function index(InertiaInterface $inertia)
    {
        return $inertia->render('Dashboard', ['prop' => 'propValue']);
    }
}

共享数据

要与其他所有组件共享数据,请使用 $inertia->share($key, $data)。这可以在 EventSubscriber 中完成

<?php

namespace App\EventSubscriber;

use Rompetomp\InertiaBundle\Service\InertiaInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class InertiaSubscriber implements EventSubscriberInterface
{
    /** @var \Rompetomp\InertiaBundle\Service\InertiaInterface */
    protected $inertia;

    /**
     * AppSubscriber constructor.
     *
     * @param \Rompetomp\InertiaBundle\Service\InertiaInterface $inertia
     */
    public function __construct(InertiaInterface $inertia)
    {
        $this->inertia = $inertia;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => 'onControllerEvent',
        ];
    }

    public function onControllerEvent($event)
    {
        $this->inertia->share(
            'Auth::user', 
            [
                'name' => 'Hannes', // Synchronously
                'posts' => function () {
                    return [1 => 'Post'];
                }   
            ]
        );
    }
}

视图数据

如果您想将数据传递给根模板,可以通过将第三个参数传递给 render 函数来实现

return $inertia->render('Dashboard', ['prop' => 'propValue'], ['title' => 'Page Title']);

您也可以使用 viewData 函数传递这些数据,就像传递给 share 函数的数据一样

$this->inertia->viewData('title', 'Page Title');

您可以在布局文件中的 viewData 变量下访问这些数据。

资产版本化

与 Laravel 一样,您也可以通过调用来传递版本到 Inertia 服务

$inertia->version($version);

懒加载属性

当使用部分重载时,在服务器端使用懒数据评估更有效。

要使用懒数据,您需要使用 Rompetomp\InertiaBundle\Service\Inertia::lazy

示例用法

<?php
namespace App\Controller;

use Rompetomp\InertiaBundle\Service\InertiaInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DashboardController extends AbstractController
{
    public function index(InertiaInterface $inertia)
    {
        return $inertia->render('Dashboard', [
            // using array
            'usingArray' => $inertia->lazy(['SomeClass', 'someMethod']),
            // using string
            'usingString' => $inertia->lazy('SomeClass::someMethod'),
            // using callable
            'usingCallable' => $inertia->lazy(function () { return [...]; }),
        ]);
    }
}

lazy 方法可以接受可调用对象、数组和字符串。当使用字符串或数组时,服务将尝试检查它是否是容器中的现有服务;如果不是,它将直接调用该函数

服务器端渲染

对于前端配置,只需遵循文档 https://inertia.laravel.net.cn/server-side-rendering#setting-up-ssr

设置 Encore / webpack

要正常运行 webpack,请安装 webpack-node-externals

npm install webpack-node-externals

接下来,我们将创建一个名为 webpack.ssr.config.js 的新文件。这与您的 webpack.config.js 几乎相同。请记住您需要保留这两个配置文件。

touch webpack.ssr.mix.js

以下是一个示例文件,用于 webpack.ssr.config.js

const Encore = require('@symfony/webpack-encore')
const webpackNodeExternals = require('webpack-node-externals')
const path = require('path')

if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}

Encore
    .setOutputPath('public/build-ssr/')
    .setPublicPath('/build-ssr')
    .enableVueLoader(() => {}, { version: 3 })
    .addEntry('ssr', './assets/ssr.js')
    .cleanupOutputBeforeBuild()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())
    .enableSassLoader()

const config = Encore.getWebpackConfig();
config.target = 'node';
config.externals = [webpackNodeExternals()];

module.exports = config

启用 SSR

要启用 SSR,您需要在您的包配置文件中添加配置 config/packages/rompetomp_inertia.yaml

rompetomp_inertia:
  ssr:
    enabled: true
    url: 'http://127.0.0.1:13714/render'

构建您的应用

您现在有两个构建过程需要运行——一个用于客户端包,另一个用于服务器端包

encore build
encore build -- -c ./webpack.ssr.config.js

SSR 的构建文件夹将位于 public/build-ssr/ssr.js。您可以通过更改输出路径(setOutputPath)在您的 ./webpack.ssr.config.js 中更改此路径

运行 Node.js 服务

要运行 SSR 服务,您需要通过 node 运行它。

node public/build-ssr/ssr.js

它将可在 http://127.0.0.1:13714 上访问,这里的路径需要放在我们的 ssr.url

使用此捆绑包的项目