Skip to content

Commit

Permalink
feat: improvement of the web perf
Browse files Browse the repository at this point in the history
  • Loading branch information
fpasquet committed Apr 11, 2023
1 parent 8780763 commit 1cd22f3
Show file tree
Hide file tree
Showing 187 changed files with 3,226 additions and 3,047 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/deploy-storybook.yml
@@ -0,0 +1,34 @@
name: Build and Deploy Storybook
on:
push:
branches:
- master
jobs:
build-and-deploy-storybook:
runs-on: ubuntu-latest
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install modules
run: yarn install --frozen-lockfile
- name: Build Storybook
run: yarn build:storybook
- name: Deploy Storybook
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./storybook-static
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -24,7 +24,8 @@ dist-ssr
*.sw?

# Custom
public/data
reports/*
storybook-static
public/imgs/posts
public/imgs/authors
public/feed.xml
Expand Up @@ -11,7 +11,7 @@ slug: how-to-be-best-friend-with-the-http-cache
oldCategoriesAndTags: []
permalink: /en/how-to-be-best-friend-with-the-http-cache/
---
I am currently lead developer for a French press website with very high traffic. Along my previous work experiences, I was able to perform development on several other high volumetry sites as well.
I am currently lead developer for a French press website with very high traffic. Along my previous work experiences, I was able to perform development on several other high volumetry sites as well.

When with only a dozen or so servers you need to contain traffic peaks between 100,000 and 300,000 short term visitors, the cache ceases to be optional: it becomes an absolute necessity !
Your application may have the best performance possible, you will always be limited by your physical machines - even if this is no longer true in the cloud (with an unlimited budget) – Consequently you must make friends with the cache.
Expand All @@ -27,23 +27,23 @@ You must have often heard, or said yourself, "empty your cache", when testing th
</tr>
<tr>
<td><a class="mw-redirect" title="Firefox" href="https://fr.wikipedia.org/wiki/Firefox">Firefox</a></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd></td>
</tr>
<tr>
<td><a title="Chrome" href="https://fr.wikipedia.org/wiki/Chrome">Chrome</a></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd> ou Shift + <kbd>F5</kbd> ou <kbd>Ctrl</kbd> + Shift + <kbd>N </kbd></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd> ou Shift + <kbd>F5</kbd> ou <kbd>Ctrl</kbd> + Shift + <kbd>N </kbd></td>
</tr>
<tr>
<td><a class="mw-redirect" title="Safari (logiciel)" href="https://fr.wikipedia.org/wiki/Safari_(logiciel)">Safari</a></td>
<td><kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>E</kbd></td>
<td><kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>E</kbd></td>
</tr>
<tr>
<td><a title="Internet Explorer" href="https://fr.wikipedia.org/wiki/Internet_Explorer">Internet Explorer</a></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd></td>
<td><kbd>Ctrl</kbd> + <kbd>F5</kbd></td>
</tr>
<tr>
<td><a title="Opera" href="https://fr.wikipedia.org/wiki/Opera">Opera</a></td>
<td><kbd>Ctrl</kbd> + <kbd>F12</kbd></td>
<td><kbd>Ctrl</kbd> + <kbd>F12</kbd></td>
</tr>
</tbody>
</table>
Expand Down Expand Up @@ -122,7 +122,7 @@ This also allows you to manage response 304 which allows the server to send only
There is another header with the same principle; it is the Etag header, which is configured with a 'string' generated by the server which changes according to the content of the page.

```sh
Etag: home560
Etag: home560
```

Be careful, the calculation of the ETag must be very carefully considered because it governs the cache time of the page, so it must be calculated with the dynamic data of the page.
Expand Down
34 changes: 17 additions & 17 deletions _posts/en/2016-07-19-behat-structure-functional-tests.md
Expand Up @@ -21,7 +21,7 @@ In order to ensure that your application is running well, it's important to writ

Behat is the most used tool with Symfony to handle your functional tests and that's great because it's really a complete suite.

You should nevertheless know how to use it wisely in order to cover useful and complete test cases and that's the goal of this blog post.
You should nevertheless know how to use it wisely in order to cover useful and complete test cases and that's the goal of this blog post.

# Introduction

Expand All @@ -33,14 +33,14 @@ However, it is important to write the following test types to cover the function
* `Integration tests`: Goal of these tests is to ensure that sour code (already unit-tested) which makes the application running is acting as it should when all components are linked together.

Idea is to develop and run both integration tests and interface tests with Behat.
Before we can go, please note that we will use a `Selenium` server which will receive orders by `Mink` (a Behat extension) and will pilot our browser (Chrome in our configuration).
Before we can go, please note that we will use a `Selenium` server which will receive orders by `Mink` (a Behat extension) and will pilot our browser (Chrome in our configuration).

To be clear on the architecture we will use, here is a scheme that will resume the role of all elements:

!["Behat architecture schema"](/_assets/posts/2016-07-19-behat-structure-functional-tests/behat_en.jpg)

## Behat set up
First step is to install Behat and its extensions as dependencies in our `composer.json` file:
First step is to install Behat and its extensions as dependencies in our `composer.json` file:

```json
"require-dev": {
Expand All @@ -53,7 +53,7 @@ First step is to install Behat and its extensions as dependencies in our `compos
}
```

In order to make your future contexts autoloaded, you also have to add this little `PSR-4` section:
In order to make your future contexts autoloaded, you also have to add this little `PSR-4` section:

```json
"autoload-dev": {
Expand All @@ -63,7 +63,7 @@ In order to make your future contexts autoloaded, you also have to add this litt
}
```

Now, let's create our **behat.yml** file in our project root directory in order to define our tests execution.
Now, let's create our **behat.yml** file in our project root directory in order to define our tests execution.

Here is the configuration file we will start with:

Expand Down Expand Up @@ -91,20 +91,20 @@ default:
output_path: %paths.base%/web/reports/behat
```

We will talk of all of these sections in their defined order so let's start with the **suites** section which is empty at this time but we will implement it later when we will have some contexts to add into it.
We will talk of all of these sections in their defined order so let's start with the **suites** section which is empty at this time but we will implement it later when we will have some contexts to add into it.

Then, we load some Behat extensions:

* `Behat\Symfony2Extension` will allow us to inject Symfony services into our contexts (useful for integrations tests mostly),
* `Behat\MinkExtension` will allow us to pilot Selenium (drive itself the Chrome browser) so we fill in all the necessary information like the hostname, the Selenium server port number and the base URL we will use for testing,
* `emuse\BehatHTMLFormatter\BehatHTMLFormatterExtension` will generate a HTML report during tests execution (which is great to show to our customer for instance).
* `Behat\MinkExtension` will allow us to pilot Selenium (drive itself the Chrome browser) so we fill in all the necessary information like the hostname, the Selenium server port number and the base URL we will use for testing,
* `emuse\BehatHTMLFormatter\BehatHTMLFormatterExtension` will generate a HTML report during tests execution (which is great to show to our customer for instance).

Finally, in the `formatters` section we keep the `pretty` formatter in order to keep an output in our terminal and the HTML reports will be generated at the same time in the `web/reports/behat` directory in order to make them available over HTTP (it should not be a problem as you should not execute functional tests in production, be careful to restrict access in this case).
Now that Behat is ready and configured we will prepare our functional tests that we will split into two distinct Behat suites: `integration` and `interface`.
Finally, in the `formatters` section we keep the `pretty` formatter in order to keep an output in our terminal and the HTML reports will be generated at the same time in the `web/reports/behat` directory in order to make them available over HTTP (it should not be a problem as you should not execute functional tests in production, be careful to restrict access in this case).
Now that Behat is ready and configured we will prepare our functional tests that we will split into two distinct Behat suites: `integration` and `interface`.

# Writing functional tests (features)
In our example, we will write tests in order to ensure that a new user can register over a registration page.
We will have to start by writing our tests scenarios (in a `.feature` file) that we will put into a `features/` directory located at the project root directory.
We will have to start by writing our tests scenarios (in a `.feature` file) that we will put into a `features/` directory located at the project root directory.

So for instance, we will have the following scenario:

Expand Down Expand Up @@ -278,7 +278,7 @@ The only difference here is that in this context we ask Mink to ask to Selenium

# Context definition

One more thing now, we have to add previously created contexts in our `suites` section in the `behat.yml` configuration file.
One more thing now, we have to add previously created contexts in our `suites` section in the `behat.yml` configuration file.

{% raw %}
```yaml
Expand All @@ -298,19 +298,19 @@ suites:
```
{% endraw %}

It is important to see here that we can clearly split these kind of tests into two distinct parts `integration` and `interface`: each one will be executed with its own contexts.
It is important to see here that we can clearly split these kind of tests into two distinct parts `integration` and `interface`: each one will be executed with its own contexts.

Also, as we have loaded the Symfony2 extension during the Behat set up, we have the possibility to inject Symfony services in our contexts and that case occurs here with the `acme.registration.registerer` service.
Also, as we have loaded the Symfony2 extension during the Behat set up, we have the possibility to inject Symfony services in our contexts and that case occurs here with the `acme.registration.registerer` service.

# Tests execution

In order to run all tests, simply execute in the project root directory: `bin/behat -c behat.yml`.
If you want to run the integration tests only: `bin/behat -c behat.yml --suite=integration`.
HTML report will be generated under the `web/reports/behat/` as specified in the configuration that will allow you to have a quick overview of failed tests which is cool when you have a lot of tests.
HTML report will be generated under the `web/reports/behat/` as specified in the configuration that will allow you to have a quick overview of failed tests which is cool when you have a lot of tests.

# Link multiple contexts together

At last, sometime you could need information from another context. For instance, imagine that you have a second step just after the register step. You will have to create two new `IntegrationProfileContext` and `MinkProfileContext` contexts.
At last, sometime you could need information from another context. For instance, imagine that you have a second step just after the register step. You will have to create two new `IntegrationProfileContext` and `MinkProfileContext` contexts.

We will only talk about integration context in the following to simplify understanding.

Expand Down Expand Up @@ -352,7 +352,7 @@ class IntegrationProfileContext implements Context
```
{% endraw %}

You now have an accessible property **$registerContext** and can access informations from this context.
You now have an accessible property **$registerContext** and can access informations from this context.

# Conclusion

Expand Down
20 changes: 10 additions & 10 deletions _posts/en/2016-09-08-php-7-1-dummies-candidates.md
Expand Up @@ -18,7 +18,7 @@ permalink: /en/php-7-1-dummies-candidates/
---
Some time ago, well almost one year ago (time just flies!), I wrote about PHP 7.0\. Ten months later, things are moving again: PHP 7.1 is in RC1 stage.

This article doesn't pretend to be a list of all the modifications, but points out the new interesting features (you'll find at the bottom a link to all PHP 7.1 RFC's which have been used to write this article). Moreover, you need to know and understand all features introduced in PHP 7.0.
This article doesn't pretend to be a list of all the modifications, but points out the new interesting features (you'll find at the bottom a link to all PHP 7.1 RFC's which have been used to write this article). Moreover, you need to know and understand all features introduced in PHP 7.0.

# RC1?

Expand All @@ -30,9 +30,9 @@ As far as we know, PHP 7.1 should be released anytime soon, at least before the

## Nullable types

In my opinion, it's the most interesting feature of PHP 7.1\. As you might know (I hope so!), PHP 7.0 allowed to type hint scalar in parameters of functions, but also type hint returns (both classes and scalars). However, there was something missing: the ability to pass or return null when using type hinting.
In my opinion, it's the most interesting feature of PHP 7.1\. As you might know (I hope so!), PHP 7.0 allowed to type hint scalar in parameters of functions, but also type hint returns (both classes and scalars). However, there was something missing: the ability to pass or return null when using type hinting.

Since an image (ok it's a video) is worth a thousand words, you can see above the behavior of PHP 7.0 when giving null to type hinted methods or functions (it's also the case with PHP5):
Since an image (ok it's a video) is worth a thousand words, you can see above the behavior of PHP 7.0 when giving null to type hinted methods or functions (it's also the case with PHP5):

[![](https://asciinema.org/a/84925.png)](https://asciinema.org/a/84925){:rel="nofollow"}

Expand All @@ -48,25 +48,25 @@ As you can see, we can now, without using default parameters (such as = null), g

## Multi-Catch

It has long been possible to do multi-catching with the use of multiple catch blocks, one by one. Yet, it can be redundant, especially when we want to handle the same way two exceptions which have nothing in common. Here is how you should use it:
It has long been possible to do multi-catching with the use of multiple catch blocks, one by one. Yet, it can be redundant, especially when we want to handle the same way two exceptions which have nothing in common. Here is how you should use it:

[![](https://asciinema.org/a/84954.png)](https://asciinema.org/a/84954){:rel="nofollow"}

As you can see, I only used two exceptions, but I could have used much more if needed.

## Void type

Another new type has been introduced, the void type. Here is its behavior:
Another new type has been introduced, the void type. Here is its behavior:

[![](https://asciinema.org/a/84952.png)](https://asciinema.org/a/84952){:rel="nofollow"}

As shown in this video, it's okay to use a return with nothing behind, but it's strictly forbidden to return null. From this previous test, I asked myself a weird and useless question: is it possible to prefix our void type with our nullable operator? The video proves that it luckily can't be.
As shown in this video, it's okay to use a return with nothing behind, but it's strictly forbidden to return null. From this previous test, I asked myself a weird and useless question: is it possible to prefix our void type with our nullable operator? The video proves that it luckily can't be.

At first sight, the use of void may seem useless (mainly in this precise exemple) but it is not. Used in an interface, it ensures that implementations deflect too much from the original purpose of the interface.

## Iterable type

Following the same pattern of void, an iterable type has also been introduced. Again, its use might not be obvious at first sight because we have the native Traversable interface. Since we move forward type hinting (and embrace it right ? RIGHT ?!), we had no solution to represent both scalar arrays and traversable objects. It was inconsistent since then, because we could pass arrays or traversable objects the same way before type hinting.
Following the same pattern of void, an iterable type has also been introduced. Again, its use might not be obvious at first sight because we have the native Traversable interface. Since we move forward type hinting (and embrace it right ? RIGHT ?!), we had no solution to represent both scalar arrays and traversable objects. It was inconsistent since then, because we could pass arrays or traversable objects the same way before type hinting.

It's usable in type hinting of parameters and returns.

Expand All @@ -76,7 +76,7 @@ Something I found missing the whole time, and which is now solved. Class constan

You might want to know that if you don't indicate visibility, it will be public by default, to be compliant with older versions of PHP behaviors.

##  Miscellaneous
## Miscellaneous

We can also add randomly in the list of interesting features the following:

Expand All @@ -90,7 +90,7 @@ We can also add randomly in the list of interesting features the following:

You first want to know that you shouldn't use it in production environments! It's a RC for duck's sake! And to answer:

* compile it from source, this [guide](http://php.net/manual/fr/install.windows.building.php){:rel="nofollow"} explains it very clearly;
* compile it from source, this [guide](http://php.net/manual/fr/install.windows.building.php){:rel="nofollow"} explains it very clearly;
* use phpenv, which is basically compiling it from source in an automated way.

I recommend using the second solution on dev environments since it's not rare professionnally to handle projects not using same PHP versions. PHPEnv allows you to run multiple versions of PHP in CLI, based on the project. I'll certainly do a post to explain how to plug Nginx, PHP-FPM and PHPEnv to have multiple versions of PHP in a HTTP way (on dev env, right ? RIGHT ?!).
Expand All @@ -99,7 +99,7 @@ I recommend using the second solution on dev environments since it's not rare pr

This version, even being minor, comes with a lot of changes.

I'm aware that PHP is not the perfect language, and has many missing features. But we can hope that, one day, we will have native annotations or enumerations for example. The community is constantly moving, and tries really hard to improve PHP and its reputation.
I'm aware that PHP is not the perfect language, and has many missing features. But we can hope that, one day, we will have native annotations or enumerations for example. The community is constantly moving, and tries really hard to improve PHP and its reputation.

If you want to know more about PHP 7.1 features, I invite you to read [RFC's](https://wiki.php.net/rfc#php_71){:rel="nofollow"}.

Expand Down

0 comments on commit 1cd22f3

Please sign in to comment.