Configuring Storybook for Vue with TypeScript

August 14th 2020 Vue.js TypeScript

Storybook is a great tool for component development. But although it supports many frameworks, it still sometimes gives the appearance of being React-first. For example, the default configuration for Vue.js doesn't have TypeScript support.

The init command recognizes a Vue.js project and sets everything up:

npx -p @storybook/cli sb init

You could try writing a story in TypeScript:

export default {
  title: "components/Button",
};

export const Demo = () => ({
  components: { Button },
  template: `<Button text="Click me!"></Button>`,
});

However, Storybook will simply ignore it. To fix that, you first need to change the pattern in .storybook/main.js which only includes JavaScript files by default:

module.exports = {
  stories: ["../src/**/*.stories.ts"],
  // ...
};

Now, the TypeScript file will be processed, but will immediately fail with an error:

Module parse failed: Unexpected character '@' (10:0)
File was processed with these loaders:
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.

The error message is very informative. The problem can be fixed by customizing Storybook's Webpack configuration with Vue TypeScript loader:

module.exports = {
  // ...
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.ts$/,
      loader: "ts-loader",
      options: { appendTsSuffixTo: [/\.vue$/] },
    });
    return config;
  },
};

This will fix the problem. But there's another issue with Storybook's TypeScript configuration. A new Vue.js project includes a path alias configuration:

"paths": {
  "@/*": [
    "src/*"
  ]
},

Storybook will not yet recognize such paths:

ERROR in ./src/components/Button.stories.ts
Module not found: Error: Can't resolve '@/components/Button.vue

There's a Webpack plugin to help with that:

npm i -D tsconfig-paths-webpack-plugin

Of course, it must be included in Storybook's Webpack configuration:

const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");

module.exports = {
  // ...
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.ts$/,
      loader: "ts-loader",
      options: { appendTsSuffixTo: [/\.vue$/] },
    });
    config.resolve.plugins = config.resolve.plugins || [];
    config.resolve.plugins.push(new TsconfigPathsPlugin({}));
    return config;
  },
};

For reference, you can check the full configuration in my repository on GitHub.

Although Storybook's default configuration for Vue.js doesn't include support for TypeScript, it can be added by customizing its Webpack configuration with the well-documented missing TypeScript bits.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License