Do you want to use Storybook in your Laravel App using Jetstream and Inertia ?
Have you met some resistance and gave up because of Webpack ?
Then this post might help you. It is the result of frustrating search over the web to make it work. Hope you'll enjoy it.
Foreword
Before we begin, I'd like to emphasis that my knowledge in frontend is extremely limited. As Jon Stark, I know nothing Webpack-related and this post is really here to help people struggling to make Storybook work with Jetstream, Inertia and Tailwind. If you spot some horrendeous mistakes or anything that could be improved, please contact me through Twitter and I'll gladly update this post.
I wrote this post using this stack:
- Laravel v9.2
- Jetstream v2.7
- Inertia v0.11
- TailwindCSS v3
- Storybook v6.4.21
Install Storybook
npx sb init
This command will snoop inside your package.json
dependencies in order to determine which starting scripts Storybook will use. It will also install some dependencies, build a default configuration and sprinkle some default stories to begin with.
After installing it, you'll realize running Storybook will fail dramatically.
info @storybook/vue3 v6.4.21
info
info => Loading presets
info => Using implicit CSS loaders
info => Using prebuilt manager
info => Using default Webpack4 setup
ERR! TypeError: Cannot read property 'NormalModule' of undefined
It is using the wrong version of Webpack. Let's fix this.
Use the proper Webpack version
Let's start by adding two dependencies that sb init
missed while snooping our project.
In package.json
, I'll add these two devDependencies
:
"@storybook/manager-webpack5": "^6.4.21",
"@storybook/builder-webpack5": "^6.4.21",
Then, we tell Storybook to use the proper builder by adding a new key in the object declared in .storybook/main.js
:
"core": {
"builder": "webpack5",
},
Let's run npm install && npm run storybook
and this time, you should be able to check your brand new Storybook !
Now let's add a story for a Jetstream's component, let's say.. the button.
Create a story
Remove the default stories that come by installing Storybook and inside a stories/Button.stories.js
let's create our button's story:
import Button from '@/Jetstream/Button.vue';
export default {
title: 'Jetstream/Button',
component: Button,
};
const Template = (args) => ({
components: { Button },
setup() {
return { args };
},
template: '<Button v-bind="args">Test Button</Button>',
});
export const MyButton = Template.bind({});
It shouldn't work because Storybook can't resolve '@/Jetstream/Button.vue'
.
Let's fix this.
Fixing aliases
Inside .storybook/main.js
, right after the core
key we declared some steps ago, we'll add a new one called webpackFinal
and put the aliases we have in our webpack.mix.js
, like this:
"webpackFinal": async (config) => {
config.resolve = {
...config.resolve,
alias: {
...config.resolve?.alias,
'@': '../resources/js',
}
}
return config;
}
Now we can restart our Storybook with npm run storybook
and it should be good !
Well.. not totally. Where is Tailwind ?
Importing Tailwind
We need to tell Storybook to do some fancy stuff with postcss
because.. well I don't know and frankly I'm afraid to ask. But adding this rule to the webpackFinal
key we added previously makes it work. It's cool right? Right..?
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {
implementation: 'postcss',
plugins: {
tailwindcss,
}
},
},
},
],
include: path.resolve(__dirname, '../'),
});
config.resolve = {
...config.resolve,
alias: {
...config.resolve?.alias,
'@': '../resources/js',
}
}
return config;
}
I assume it is telling webpack to use postcss with a Tailwind's plugin to compile our css. Let me know if you got a better definition of what's going on here and I'll update it.
For this to work, we need to import some stuff, so at the top of the file:
const path = require('path');
const tailwindcss = require('../tailwind.config');
And we'll also import the app.css
inside .storybook/preview.js
:
import '../resources/css/app.css';
Now we restart again Storybook et voilà! Bim! You've got your story-nertia-wind up and running.
Final files
Get a look at the final files here
Bonus: Use Storybook on Lando
You're using Lando ? I wrote a little post to make Storybook works with Lando.
Top comments (1)
Many thanks to you good sir! Ran into exactly the same issues myself plus an additional one that required me to define the version of Webpack I wanted to use in package.json after npx sb init stopped my Inertia app from running.
Found the solution to the second issue here (github.com/laravel-mix/laravel-mix...) if anyone else has the same problem.