问题描述
我无法在 SPA 设置中让 Symfony 4 正常工作.
I've not been able to have Symfony 4 work properly in a SPA setup.
特别是,当我使用 React-router 链接导航时,一切正常.
Specifically, while I navigate using React-router links everything works as it should.
但是如果我尝试直接访问任何路由(除了 home ),Symfony 会拦截它,当然,会抛出一个找不到路由的错误.
But if I try accessing any of the routes ( except home ) directly, Symfony intercepts it and, of course, throws an error for route not found.
将 Symfony 放在子域中并仅将其用作 API 的替代方案是不可行的,因为我需要框架提供的所有用户和会话管理工具.
The alternative of placing Symfony in a sub-domain and using it only as an API is not viable, as I need all the user and session management tools provided by the framework.
当然,我将需要 Symfony 的所有 API 调用路由到后端.
Of course I will need Symfony's routing for all API calls to the back-end.
我使用的是 Symfony 4 的默认目录结构,只在顶层为所有 react/redux 代码添加一个目录/client.
I am using Symfony 4's default directory structure, only adding a directory /client at top level for all react/redux code.
构建代码放在/public/build 下.
The build code is placed under /public/build.
我还尝试使用以下代码在/public 上放置一个 .htaccess 文件,但这没有帮助.
I also tried placing a .htaccess file on /public with below code, but that did not help.
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
谢谢
推荐答案
可能有以下解决方案.
带有路由注解的控制器,无论路由可能有多少个参数,所有路由都会通过这个注解来处理:
The controller with route annotation, all routes will be handled by react with this annotation, no matter how many parameters the route might have:
namespace App\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
class DefaultController extends Controller
{
/**
* @Template("default/index.html.twig")
* @Route("/{reactRouting}", name="index", requirements={"reactRouting"=".+"}, defaults={"reactRouting": null})
*/
public function index()
{
return [];
}
}
如果你有不应该被 react 处理的路由,你的注解可以像下面这样排除它们 - 所有以 api 开头的路由都不会被 react 处理:
If you have routes that shouldn't be handled by react, your annotation could exclude them like as follows - all routes that start with api will not be handled by react:
@Route("/{reactRouting}", name="index", requirements={"reactRouting"="^(?!api).+"}, defaults={"reactRouting": null})
Twig 模板,带有根元素:
Twig Template, with root element:
{% extends 'base.html.twig' %}
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('build/js/app.css') }}">
{% endblock %}
{% block body %}
<div id="root"><div>
{% endblock %}
{% block javascripts %}
<script type="text/javascript" src="{{ asset('build/js/app.js') }}"></script>
{% endblock %}
反应索引文件:
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import Home from "./containers/Home";
import AboutUs from "./containers/AboutUs";
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route path="/" component={Home}/>
<Route path="/about-us" component={AboutUs}/>
</Switch>
</BrowserRouter>,
document.getElementById('root'));
还有我的 Encore 配置:
And my encore config:
var Encore = require('@symfony/webpack-encore');
Encore
// the project directory where compiled assets will be stored
.setOutputPath('public/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/build')
.cleanupOutputBeforeBuild()
.enableSourceMaps(!Encore.isProduction())
// uncomment to create hashed filenames (e.g. app.abc123.css)
// .enableVersioning(Encore.isProduction())
// uncomment to define the assets of the project
// .addEntry('js/app', './assets/js/app.js')
// .addStyleEntry('css/app', './assets/css/app.scss')
// uncomment if you use Sass/SCSS files
// .enableSassLoader()
// uncomment for legacy applications that require $/jQuery as a global variable
// .autoProvidejQuery()
.enableReactPreset()
.addEntry('js/app', './react/index.js')
.configureBabel((config) => {
config.presets.push('stage-1');
})
;
module.exports = Encore.getWebpackConfig();
这篇关于Symfony 4 如何使用 React 设置 SPA(单页应用程序)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!