Skip to content

Commit

Permalink
Merge pull request #2 from sensiolabs/better_hmr
Browse files Browse the repository at this point in the history
Hot reload for components and importmap
  • Loading branch information
WebMamba committed Jan 18, 2024
2 parents 9dcf28f + b266a9e commit 4f73955
Show file tree
Hide file tree
Showing 78 changed files with 2,050 additions and 66,134 deletions.
66 changes: 63 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
coverage: none
- name: Validate composer.json
run: composer validate --strict
cs:
cs-php:
name: Check coding standards
runs-on: ubuntu-latest
steps:
Expand All @@ -34,7 +34,7 @@ jobs:
tools: php-cs-fixer
- name: Run PHP-CS-Fixer
run: php-cs-fixer fix . --dry-run --diff
sca:
sca-php:
name: PHPStan
runs-on: ubuntu-latest
steps:
Expand All @@ -46,5 +46,65 @@ jobs:
php-version: 8.2
- name: Install composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Run PHPStan
run: vendor/bin/phpstan analyse
run: vendor/bin/phpstan analyse
cs-js:
name: JavaScript Coding Style
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get yarn cache directory path
working-directory: ./storybook
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-yarn-
- working-directory: ./storybook
run: yarn --frozen-lockfile
- working-directory: ./storybook
run: yarn check-lint
- working-directory: ./storybook
run: yarn check-format
tests-php:
name: PHPUnit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
- name: Install composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run PHPUnit
run: vendor/bin/simple-phpunit
tests-js:
name: Vitest
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get yarn cache directory path
working-directory: ./storybook
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-yarn-
- working-directory: ./storybook
run: yarn --frozen-lockfile
- working-directory: ./storybook
run: yarn test
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/yarn.lock

/.phpunit.result.cache
/phpunit.xml.dist
/phpunit.xml

.php-cs-fixer.cache

182 changes: 146 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@ Clone this repo and install the bundle in your project.
Install Storybook in your project:

```shell
yarn add @storybook/cli
yarn run sb init -t server
yarn add -D @storybook/cli @storybook/addon-essentials @storybook/addon-links @storybook/blocks react react-dom
```

Add the bundled NPM package for Symfony integration:

```shell
yarn add link:vendor/sensiolabs/storybook-bundle/storybook
yarn add -D @sensiolabs/storybook-symfony-webpack5@file:vendor/sensiolabs/storybook-bundle/storybook
```

Remove the auto generated `src/stories` directory, and replace the content of `.storybook/main.js|ts` with:
Create Storybook configuration in `.storybook/`:

```ts
import type { StorybookConfig } from "@storybook/symfony-webpack5";
// .storybook/main.ts

import type { StorybookConfig } from "@sensiolabs/storybook-symfony-webpack5";

const config: StorybookConfig = {
stories: ["../stories/**/*.stories.[tj]s"],
Expand All @@ -34,16 +35,16 @@ const config: StorybookConfig = {
"@storybook/addon-essentials",
],
framework: {
// 👇 Here tell storybook to use the Symfony framework
name: "@storybook/symfony-webpack5",
// 👇 Here tell Storybook to use the Symfony framework
name: "@sensiolabs/storybook-symfony-webpack5",
options: {
builder: {
useSWC: true
},
// 👇 Here configure the framework
symfony: {
server: 'https://localhost:8000', // This is mandatory, the URL of your Symfony dev server
proxyPaths: [ // Setup here paths to resolve your assets
proxyPaths: [ // Setup here paths to resolve your assets. Those paths are proxied to your Symfony server.
'/assets'
]
}
Expand All @@ -56,34 +57,69 @@ const config: StorybookConfig = {
export default config;
```

Initialize Storybook bundle with:
```ts
// .storybook/preset.ts

import { Preview } from '@storybook/server';

const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};

export default preview;

```shell
bin/console storybook:init
```

Register the route for Storybook in your symfony project:

```yaml
# config/routes/storybook.yaml

storybook:
resource: '@StorybookBundle/config/routes.php'
```
Run Storybook with:
```shell
yarn run storybook
yarn run sb dev -p 6006
```

Additionally, you can add custom scripts to your `package.json` file:

```json
{
"scripts": {
"storybook": "sb dev -p 6006",
"build-storybook": "sb build"
}
}
```

## Symfony configuration

### CORS

As the Symfony integration relies on the Storybook's server renderer, it makes requests to your Symfony server to render Twig components. These requests are cross origins, so you have to configure Symfony to accept them from your Storybook instance.
As the Symfony integration relies on the Storybook's server renderer, it makes requests to your Symfony server to render your stories. These requests are cross origins, so you have to configure Symfony to accept them from your Storybook instance.

There is two options to achieve this. You can either configure the Storybook host in the bundle, or use the popular NelmioCORS bundle.
There is two options to achieve this. You can either configure the Storybook host in the bundle, or use the popular [NelmioCorsBundle](https://symfony.com/bundles/NelmioCorsBundle/current/index.html).

In the bundle:
In the StorybookBundle:

```yaml
# config/storybook.yaml
storybook:
server: http://localhost:6006
```
With NelmioCORS:
With NelmioCorsBundle:
```yaml
# config/storybook.yaml
storybook:
Expand All @@ -100,52 +136,91 @@ nelmio_cors:
allow_methods: ['GET']
```
### Global assets
## Customizing the preview iframe
To import global assets in the Storybook's preview iframe, you have to declare a custom template that acts like your usual `base.html.twig`, but for Storybook. First create the template:
To customize the iframe where your stories are rendered, you can create a preview template:
```twig
{# templates/storybook/preview.html.twig #}

{% extends '@Storybook/preview.html.twig' %}

{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('styles/app.css') }}">
{% block previewHead %}
{# render additional tags to <head> #}
{% endblock %}

{% block javascripts %}
{{ importmap() }}
{% block previewBody %}
{# render additional tags to <body> #}
{% endblock %}
```

Then tell the bundle it should use this file to render the preview:
Then enable it in the bundle configuration:

```yaml
# config/storybook.yaml
storybook:
preview_template: storybook/preview.html.twig
storybook:
preview: storybook/preview.html.twig
```
And generate the preview:
```shell
bin/console storybook:init
The rendered content of these blocks will be injected in the preview iframe, similarly to the [previewHead](https://storybook.js.org/docs/configure/story-rendering#adding-to-head) and [previewBody](https://storybook.js.org/docs/configure/story-rendering#adding-to-body) configurations.
> Note:
> \
> The template doesn't strictly need to extend `@Storybook/preview.html.twig`, but the rendered content needs to be a valid HTML document, and this inheritance facilitates this requirement.

### AssetMapper integration

To use Storybook with a project that uses the [AssetMapper component](https://symfony.com/doc/current/frontend/asset_mapper.html), you need to render your importmap in the preview template:

```twig
{# templates/storybook/preview.html.twig #}
{% extends '@Storybook/preview.html.twig' %}
{% block previewHead %}
{{ importmap('app') }}
{% endblock %}
```

> Important:
>
> For the moment, you have to run `bin/console storybook:init` each time you update those global assets.
Though, standard HMR will not work properly with AssetMapper. To register additional paths to watch and re-trigger the iframe compilation, update your `main.ts|js` configuration:

```ts
// .storybook/main.ts
// ...
const config: StorybookConfig = {
framework: {
name: "@sensiolabs/storybook-symfony-webpack5",
options: {
// ...
symfony: {
// 👇 Add more paths to watch
additionalWatchPaths: [
'assets', // Directories
'assets/app.js', // Files
'assets/**/*.js' // Glob patterns
],
},
},
},
};
```

## Writing stories

Example:

```js
import { twig } from '@storybook/symfony-webpack5';
// stories/Button.stories.js
import { twig } from '@sensiolabs/storybook-symfony-webpack5';
const Button = twig`<twig:Button>{{ args.label }}</twig:Button>`;
const Button = twig`<twig:Button btnType="{{ args.primary ? 'primary' : 'secondary' }}">{{ args.label }}</twig:Button>`;

export default {
title: 'Bar',
component: Button
title: 'Button',
template: Button
};

export const Primary = {
Expand All @@ -160,10 +235,45 @@ export const Secondary = {
...Primary.args,
primary: false
},
component: Button, // You can pass a specific component for a story
template: Button, // You can pass a specific template for a story
};

```
# Troubleshooting

## Conflicting `string-width` module

When you install storybook, you might encounter the following warnings:

```
warning Pattern ["string-width-cjs@npm:string-width@^4.2.0"] is trying to unpack in the same destination "/home/john/.cache/yarn/v6/npm-string-width-cjs-4.2.3-269c7117d27b05ad2e536830a8ec895ef9c6d010-integrity/node_modules/string-width-cjs" as pattern ["string-width@^4.2.0"]. This could result in non-deterministic behavior, skipping.
warning Pattern ["strip-ansi-cjs@npm:strip-ansi@^6.0.1"] is trying to unpack in the same destination "/home/john/.cache/yarn/v6/npm-strip-ansi-cjs-6.0.1-9e26c63d30f53443e9489495b2105d37b67a85d9-integrity/node_modules/strip-ansi-cjs" as pattern ["strip-ansi@^6.0.0"]. This could result in non-deterministic behavior, skipping.
warning Pattern ["string-width@^4.1.0"] is trying to unpack in the same destination "/home/john/.cache/yarn/v6/npm-string-width-cjs-4.2.3-269c7117d27b05ad2e536830a8ec895ef9c6d010-integrity/node_modules/string-width-cjs" as pattern ["string-width@^4.2.0"]. This could result in non-deterministic behavior, skipping.
```


When trying to run storybook, if you get the following error:
```
🔴 Error: It looks like you are having a known issue with package hoisting.
Please check the following issue for details and solutions: https://github.com/storybookjs/storybook/issues/22431#issuecomment-1630086092
/home/john/Projects/storybook/node_modules/cli-table3/src/utils.js:1
const stringWidth = require('string-width');
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /home/john/Projects/storybook/node_modules/string-width/index.js from /home/john/Projects/storybook/node_modules/cli-table3/src/utils.js not supported.
```

Then you have to clean the yarn cache for the conflicting module and reinstall:

```
yarn cache clean string-width-cjs@npm:string-width@^4.2.0
rm -rf yarn.lock
yarn install --force
```

# License

MIT License (MIT): see [LICENSE](./LICENSE).
Expand Down
13 changes: 8 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@
"symfony/filesystem": "^7.0"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"symfony/framework-bundle": "^7.0",
"symfony/phpunit-bridge": "^7.0",
"symfony/twig-bundle": "^7.0",
"symfony/ux-twig-component": "^2.13"
"nelmio/cors-bundle": "^2.4",
"phpstan/phpstan": "^1.10",
"symfony/asset-mapper": "^7.0",
"symfony/browser-kit": "^7.0",
"symfony/framework-bundle": "^7.0",
"symfony/phpunit-bridge": "^7.0",
"symfony/twig-bundle": "^7.0",
"symfony/ux-twig-component": "^2.13"
}
}
Loading

0 comments on commit 4f73955

Please sign in to comment.