diff --git a/.gitignore b/.gitignore index 463794e..b4c3368 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,34 @@ .idea +.vs +.code vendor composer.lock *.phar +/dist + +views-mappings.php + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +package-lock.json + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/Documentation/assets/SampleForm.tsx-request-404.png b/Documentation/assets/SampleForm.tsx-request-404.png new file mode 100644 index 0000000..9bae7e7 Binary files /dev/null and b/Documentation/assets/SampleForm.tsx-request-404.png differ diff --git a/Documentation/assets/browser-network-inspection.png b/Documentation/assets/browser-network-inspection.png new file mode 100644 index 0000000..3aff1ff Binary files /dev/null and b/Documentation/assets/browser-network-inspection.png differ diff --git a/Documentation/assets/form-rendered.png b/Documentation/assets/form-rendered.png new file mode 100644 index 0000000..7d37357 Binary files /dev/null and b/Documentation/assets/form-rendered.png differ diff --git a/Documentation/assets/npm-start.png b/Documentation/assets/npm-start.png new file mode 100644 index 0000000..91f3f56 Binary files /dev/null and b/Documentation/assets/npm-start.png differ diff --git a/Documentation/assets/php-server-config.png b/Documentation/assets/php-server-config.png new file mode 100644 index 0000000..cb886c8 Binary files /dev/null and b/Documentation/assets/php-server-config.png differ diff --git a/Documentation/assets/render-react-php-file-processed.png b/Documentation/assets/render-react-php-file-processed.png new file mode 100644 index 0000000..fe7158d Binary files /dev/null and b/Documentation/assets/render-react-php-file-processed.png differ diff --git a/Documentation/assets/staging-server-render-react-php-file-processed.png b/Documentation/assets/staging-server-render-react-php-file-processed.png new file mode 100644 index 0000000..08c3555 Binary files /dev/null and b/Documentation/assets/staging-server-render-react-php-file-processed.png differ diff --git a/Documentation/data.puml b/Documentation/data.puml index 90a7929..0ad5135 100755 --- a/Documentation/data.puml +++ b/Documentation/data.puml @@ -68,4 +68,4 @@ class Color { + getValue(): int } -@enduml +@enduml \ No newline at end of file diff --git a/Documentation/how-to-dev.md b/Documentation/how-to-dev.md new file mode 100644 index 0000000..88e9d75 --- /dev/null +++ b/Documentation/how-to-dev.md @@ -0,0 +1,150 @@ +This documentation file explains how to start a development server on your +machine, and how it works under the hood. + +# How to run the project on my local computer + + +1) Use phpstorm to run a local php server: +* Go to configuration > add new configuration +* Select "PHP Built-in Web Server", then enter options as follow: +![](assets/php-server-config.png) + - port 8080 + - name the configuration "RunServer" to be more explicit + - place the "Document Root" in `/public` + - host is localhost +* Click apply, OK +* Now run it. + +If you go to `http://localhost:8080` you'll see a blank page. +This is expected ! On your browser, open inspection tab (ctrl+shift+i) go to network and refresh the page. +![](assets/browser-network-inspection.png) + +We can see that the browser requested the `SampleForm.tsx` react view (located in `/front/views`), but the server could not find it. +But, on what server was it requested ? +Remember that the `localhost:8080` is a _php_ server, and thus not able to handle requests about our react / typescript files. +If we take a look at the request, we'll see that the url does not targets `localhost:8080`, but `localhost:5173`. + +![](assets/SampleForm.tsx-request-404.png) + +`localhost:5173` is the react development server, it is able to serve our react front view files. +Let's run the react development server. +It is a simple as running `npm start` in a new terminal (be sure to run it in the repository's directory). +![](assets/npm-start.png) + +You should see something like this, it says that the server was opened on port `5173`, thats our react development server ! +Now refresh your page, you should now see all request being fulfilled and a form appearing ! + +![](assets/form-rendered.png) + +Caution: **NEVER** directly connect on the `localhost:5173` node development server, always pass through the php (`localhost:8080`) server. + +# How it works +I'm glad you are interested in how that stuff works, it's a bit tricky, lets go. +If you look at our `index.php` (located in `/public` folder), you'll see that it is our gateway, it uses an `AltoRouter` that dispatches the request's process to a controller. +We can see that there are two registered routes, the `GET:/` (that then calls `SampleFormController#displayForm()`) and `POST:/result` (that calls `SampleFormController#displayResults()`). +Implementation of those two methods are very simple: there is no verification to make nor model to control, thus they directly sends the view back to the client. + +here's the implementation of the `SampleFormController` +```php +require_once "react-display.php"; +class SampleFormController { + public function displayForm() { + send_react_front("views/SampleForm.tsx", []); + } + + public function displayResults(array $request) { + send_react_front("views/DisplayResults.tsx", $request); + } +} +``` + +As our views are now done using react (and defined under the `front/views` folder), we need to use the `send_react_front($viewURI, $viewArguments)` php function (located in the `src/react-render.php` file) to render a react view. + +If you look at the `send_react_front($viewURI, $viewArguments)` function, you'll see that is simply loads the file `src/react-display-file.php` with given arguments. +The file is a simple html5 template with a ` +``` + +here's how it renders if you do a request to `http://localhost:8080/`. + +![](assets/render-react-php-file-processed.png) +The index.php's router says that for a `GET` on the `/` url, we call the `SampleFormController#displayForm` method. +This method then uses the `send_react_front`, to render the `views/SampleForm.tsx` react element, with no arguments (an empty array). +The view file **must export by default its react function component**. + +## Server Profiles +If you go on the staging server, you'll see that, for the exact same request equivalent, the generated `src/render-display-file` file changes : +![](assets/staging-server-render-react-php-file-processed.png) +(we can also see that much less files are downloaded than with our localhost aka development server). + +Remember that react components and typescript files needs to be transpiled to javascript before being executable by a browser. +The generated file no longer requests the view to a `localhost:5173` or a `maxou.dev:5173` server, +now our react components are directly served by the same server, as they have been pre-compiled by our CI (see `/ci/.drone.yml` and `/ci/build_react.msh`) into valid js files that can directly be send to the browser. +If you go back to our `index.php` file, you'll see that it requires a `../config.php` file, if you open it, +you'll see that it defines the `asset(string $uri)` function that is used by the `src/react-display-file.php`, +in the ` + + "> + + + + Document + + + +
+ + + + + + + + \ No newline at end of file diff --git a/src/react-display.php b/src/react-display.php new file mode 100644 index 0000000..b965a3a --- /dev/null +++ b/src/react-display.php @@ -0,0 +1,13 @@ + { + if (fs.lstatSync(`${dirname}/${file_name}`).isFile()) { + return [[`${dirname}/${file_name}`, `${dirname}/${file_name}`]] + } else { + return resolve_entries(`${dirname}/${file_name}`) + } + }) +} + +export default defineConfig({ + root: 'front', + base: '/front', + build: { + target: 'es2021', + assetsDir: '', + outDir: "../dist", + manifest: true, + rollupOptions: { + input: Object.fromEntries(resolve_entries("front")), + preserveEntrySignatures: "allow-extension" + } + }, + plugins: [ + react() + ] +})