{"id":28413320,"url":"https://github.com/vikbert/react-symfony5-starter","last_synced_at":"2025-06-24T20:30:56.346Z","repository":{"id":54319693,"uuid":"341873853","full_name":"vikbert/react-symfony5-starter","owner":"vikbert","description":null,"archived":false,"fork":false,"pushed_at":"2021-02-24T11:16:33.000Z","size":501,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-03T15:26:25.046Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vikbert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-24T11:11:48.000Z","updated_at":"2021-02-24T11:16:36.000Z","dependencies_parsed_at":"2022-08-13T12:00:18.931Z","dependency_job_id":null,"html_url":"https://github.com/vikbert/react-symfony5-starter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vikbert/react-symfony5-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikbert%2Freact-symfony5-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikbert%2Freact-symfony5-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikbert%2Freact-symfony5-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikbert%2Freact-symfony5-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vikbert","download_url":"https://codeload.github.com/vikbert/react-symfony5-starter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikbert%2Freact-symfony5-starter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261751434,"owners_count":23204423,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-03T04:33:53.114Z","updated_at":"2025-06-24T20:30:56.338Z","avatar_url":"https://github.com/vikbert.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Symfony5 Starter\n| stacks           | description                                  |\n|------------------|----------------------------------------------|\n| symfony5         | symfony 5 latest                             |\n| react.js         | react.js framework                           |\n| react.js         | react.js framework                           |\n| TypeScript       | TypeScript for react.js                      |\n| Jest             | Jest test runner                             |\n| enzyme           | the Test framework                           |\n| sass             | support sass for stylesheet                  |\n| webpack notifier | Notifier for the package building in browser |\n\n## Usage\n\nCreate local repository and clone the code:\n\n```sh\n$ git clone https://github.com/vikbert/react-symfony5-starter.git\n```\n\nInstall dependencies:\n\n```sh\n$ composer install\n$ npm install\n```\n\nRun the app:\n\n```sh\n$ symfony server:start\n$ npm run watch\n```\n\nNavigating to https://localhost:{port} you should see the app main page.\n\n\nThis simple project starter shows how to wire up Symfony 5 with React and how to test the front part of the app with Jest \u0026 Enzyme.\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eReact Symfony5 Starter\u003c/h1\u003e\n\u003c/div\u003e\n\n\n## Stack: step by step by yourself\nBackend of the starter is based on Symfony 5 and uses Webpack Encore shipped with the framework to integrate frontend libraries and styles.\n\n```sh\n$ symfony new react-symfony5-starter\n```\n### Backend dependencies\nInstallation of additional dependencies was required in order to embed js part of the tool inside regular Symfony/Twig template:\n\n```\n$ composer require annotations twig asset\n$ composer require symfony/webpack-encore-bundle\n```\n\n### Installation of Frontend libraries\n\n```sh\n$ npm install react react-dom prop-types react-router-dom\n$ npm install @babel/preset-react --save-dev\n$ npm install @babel/preset-typescript --save-dev\n$ npm install @babel/plugin-syntax-jsx --save-dev\n$ npm install typescript ts-loader --save-dev\n$ npm install sass-loader@^8.0.0 node-sass --save-dev\n```\n\nTypescript params were placed inside `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"es2017\",\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"jsx\": \"react\",\n    \"esModuleInterop\": true,\n    \"removeComments\": true,\n    \"declaration\": false,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"suppressImplicitAnyIndexErrors\": true,\n    \"allowSyntheticDefaultImports\": true,\n    //Removes IDE TS errors while importing modules\n    \"noImplicitAny\": false\n  },\n  \"compileOnSave\": true,\n  \"exclude\": [\n    \"node_modules\"\n  ]\n}\n```\n\n### Wiring React \u0026 Symfony\n```text\napp/\n├─ templates/\n│ ├─ default/\n│ │    └─ index.html.twig\n│ └─ base.html.twig\n\n```\n\n```html\n{# base.html.twig #}\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003ctitle\u003e{% block title %}{% endblock %}\u003c/title\u003e\n    {% block stylesheets %}\n        {{ encore_entry_link_tags('app') }}\n    {% endblock %}\n\u003c/head\u003e\n\u003cbody\u003e\n    {% block body %}{% endblock %}\n    {% block javascripts %}\n        {{ encore_entry_script_tags('app') }}\n    {% endblock %}\n\u003c/body\u003e\n\u003c/html\u003e\n```\n    \n```html\n{# index.html.twig #}\n{% extends 'base.html.twig' %}\n{% block title %} Symfony React Jest Enzyme {% endblock %}\n{% block body %}\n    \u003cdiv id=\"root\"\u003e\u003c/div\u003e\n{% endblock %}\n```\n\n### Overriding default Encore configuration\n\nWebpack Encore fills in `webpack.config.js` file with initial instructions to configure the asset system.\nWe need to modify the file slightly, cause Jest \u0026 Enzyme require instructions from `babel.config.js` to load js modules.\nTo do so, remove or just comment the lines below:\n\nWebpack Encore amendment inside `webpack.config.js`\n```diff\n {\n    enables @babel/preset-env polyfills\n-  .configureBabelPresetEnv((config) =\u003e {\n-       config.useBuiltIns = 'usage';\n-       config.corejs = 3;\n-    })\n }\n```\n\nExternal Babel configuration with `babel.config.js`\n\n```js\nmodule.exports = {\n    presets: [\n        [\n            '@babel/preset-env',\n            {\n                targets: {\n                    node: 'current',\n                    browsers: [\n                        \"\u003e 0.5%\",\n                        \"last 2 versions\",\n                        \"IE 11\"\n                    ]\n                },\n                useBuiltIns: 'usage',\n                corejs : {\n                    version: \"3\",\n                    proposals : true\n                }\n            },\n        ],\n        ['@babel/preset-react'],\n        ['@babel/preset-typescript']\n    ],\n    plugins: [\"@babel/plugin-syntax-jsx\"]\n};\n```\n\n### Jest \u0026 Enzyme integration\n\n```sh\n$ npm install jest enzyme enzyme-adapter-react-16 --save-dev\n```\n\nJest configuration was defined inside `jest.config.js` and points to a test `setup.js` setup file:\n\n```text\napp/\n├─ assets/\n│ ├─ js/\n│ ├─ ...\n│ ├─ tests/\n│     └─ setup.js\n├─ jest.config.js\n├─ ...\n```\n\n```js\n//jest.config.js\n\nmodule.exports = {\n    rootDir: './assets',\n    testRegex: './assets/js/.*test\\\\.tsx',\n    setupFiles: ['\u003crootDir\u003e/tests/setup.js'],\n    //Generate coverage reports as HTML\n    //inside /assets/coverage directory\n    //\"coverageReporters\": [\"json\", \"html\"],\n    collectCoverageFrom: [\n        \"\u003crootDir\u003e/js/**/*.{js,jsx,ts,tsx}\"\n    ],\n    coverageThreshold: {\n        global: {\n            branches: 90,\n            functions: 90,\n            lines: 90,\n            statements: 90\n        },\n    }\n};\n```\n\n```js\n//setup.js\n\nimport React from 'react';\n\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-react-16';\n\nconfigure({ adapter: new Adapter() });\n```\n## Directory aliases\n\nAdding aliases will help you to navigate between nested directories/components inside the project:\n\n```diff\n+ import App from '@components/App';\n- //import App from './../../App';\n```\n\n- jest.config.js - define aliases for tests\n- webpack.config.js - ships aliases for development\n- tsconfig.js - ships aliases for IDE (removes unwanted errors while importing modules using aliases)\n\n```diff\n//jest.config.js\n\nmodule.exports = {\n    rootDir: './assets',\n    testRegex: './assets/js/.*test\\\\.tsx',\n    setupFiles: ['\u003crootDir\u003e/tests/setup.js'],\n+   moduleNameMapper: {\n+       '^@containers(.*)$': '\u003crootDir\u003e/js/containers/$1',\n+       '^@components(.*)$': '\u003crootDir\u003e/js/components$1',\n+       '^@styles(.*)$': '\u003crootDir\u003e/styles'\n+   },\n    collectCoverageFrom: [\n        \"\u003crootDir\u003e/js/**/*.{js,jsx,ts,tsx}\"\n    ],\n    coverageThreshold: {\n        global: {\n            branches: 90,\n            functions: 90,\n            lines: 90,\n            statements: 90\n        },\n    }\n};\n```\n\n```diff\n//webpack.config.js\n\n...\nEncore\n    // directory where compiled assets will be stored\n    .setOutputPath('public/build/')\n    // public path used by the web server to access the output path\n    .setPublicPath('/build')\n    // only needed for CDN's or sub-directory deploy\n    //.setManifestKeyPrefix('build/')\n    .enableTypeScriptLoader()\n\n+   .addAliases({\n+       '@containers': path.resolve(__dirname, './assets/js/containers'),\n+       '@components': path.resolve(__dirname, './assets/js/components'),\n+       '@styles': path.resolve(__dirname, './assets/styles')\n+   })\n...\n```    \n    \n```diff\n//tsconfig.js\n\n{\n  \"compilerOptions\": {\n    //Removes IDE TS errors while importing modules\n    \"noImplicitAny\": false,\n+    \"baseUrl\": \"./assets\",\n+    \"paths\": {\n+      \"@styles/*\": [\"js/styles/*\"],\n+      \"@containers/*\": [\"js/containers/*\"],\n+      \"@components/*\": [\"js/components/*\"]\n+    }\n  },\n...\n}\n```\n\n## Final directory structure\n\n```text\napp/\n├─ assets/\n│ ├─ js/\n│ ├─ components/\n│ ├─ ...\n│ ├─ styles/\n│ ├─ tests/\n│ │   └─ setup.js\n│ └─ app.tsx\n│\n├─ ... default Symfony directories\n│\n├─ templates/\n│ ├─ default/\n│ │   └─ index.html.twig\n│ └─ base.html.twig\n│ \n├─ .env\n├─ package.json\n├─ tsconfig.json\n├─ babel.config.js\n├─ jest.config.js\n├─ webpack.config.js\n│\n└─ ... other files\n```\n## Tests\nProject have two test files `Home.test.tsx` and `App.test.tsx` to run Jest out of the box:\n\n```text\napp/\n├─ assets/\n│ ├─ js/\n│ ├─ components/\n│ ├─  ├─ Home/\n│ ├─  ├─  ├─ Home.test.tsx\n│ ├─  ├─  ├─ Home.tsx\n│ ├─  ├─  └─ index.tsx\n│ ├─  ├─ App.test.tsx\n│ ├─  └─ App.tsx\n...\n```\n\n```sh\n$ npm run test\n```\n![Jest test](jest-test.png)\n\n```sh\n$ npm run test --coverage\n```\n![Jest test coverage](jest-test-coverage.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvikbert%2Freact-symfony5-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvikbert%2Freact-symfony5-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvikbert%2Freact-symfony5-starter/lists"}