Skip to content

[Bug]: run storybook crashes because of a TypeError (Vue3 + Webpack 5 + Typescript) #25710

Open

Description

I installed Storybook to a existing project which is using Vue3 and Webpack 5 (npx storybook@latest init):

Install bash log

╭───────────────────────────────────────────────────────╮
│                                                       │
│   Adding Storybook version 7.6.10 to your project..   │
│                                                       │
╰───────────────────────────────────────────────────────╯
 • Detecting project type. ✓
 • Preparing to install dependencies. ✓


 • Installing dependencies

removed 833 packages, changed 1 package, and audited 1010 packages in 10s

120 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
. ✓
 • Adding Storybook support to your "Vue 3" app • Detected webpack project. Setting builder to webpack. ✓

  ✔ Getting the correct version of 11 packages
√ We have detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: https://github.com/storybookjs/eslint-plugin-storybook#readme

Would you like to install it? ... yes
    Configuring Storybook ESLint plugin at .eslintrc.json
  ✔ Installing Storybook dependencies
. ✓
 • Preparing to install dependencies. ✓


 • Installing dependencies

up to date, audited 1843 packages in 2s

261 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
. ✓
╭──────────────────────────────────────────────────────────────────────────────╮
│                                                                              │
│   Storybook was successfully installed in your project! 🎉                   │
│   To run Storybook manually, run npm run storybook. CTRL+C to stop.          │
│                                                                              │
│   Wanna know more about Storybook? Check out https://storybook.js.org/       │
│   Having trouble or want to chat? Join us at https://discord.gg/storybook/   │
│                                                                              │
╰──────────────────────────────────────────────────────────────────────────────╯

Everything went well, until here. But when it comes to start the application, this happens:

Running Storybook

> MY_VUE_PROJECT@1.0.0 storybook
> storybook dev -p 6006 --quiet

@storybook/cli v7.6.10

info => Starting manager..
info => Starting preview..
info Using SWC compiler
info Addon-docs: using MDX2
info => Using implicit CSS loaders
info => Using default Webpack5 setup
=> Failed to build the preview
TypeError: validate is not a function
    at wdm (.\node_modules\webpack-dev-middleware\dist\index.js:171:3)
    at starter (.\node_modules\@storybook\builder-webpack5\dist\index.js:1:8952)
    at async Module.start (.\node_modules\@storybook\builder-webpack5\dist\index.js:1:11672)
    at async storybookDevServer (.\node_modules\@storybook\core-server\dist\index.js:66:2459)
    at async buildOrThrow (.\node_modules\@storybook\core-server\dist\index.js:60:8290)
    at async buildDevStandalone (.\node_modules\@storybook\core-server\dist\index.js:120:1397)
    at async withTelemetry (.\node_modules\@storybook\core-server\dist\index.js:65:3948)
    at async dev (.\node_modules\@storybook\cli\dist\generate.js:503:401)
    at async Command.<anonymous> (.\node_modules\@storybook\cli\dist\generate.js:518:225)

I'm not sure how to fix this. Do I have to update some parts of my TypeScript config? My code does contain a function called validate, but my webpack build does work well.

To Reproduce

I don't want to share my whole project. So, I paste here single parts of it:
Got it now: https://stackblitz.com/edit/fsd7873udj

Source files

vue.config.js

/* eslint-env node */
/* eslint-disable @typescript-eslint/no-var-requires */

// This file is needed for tests to be configured

const path = require('path');

module.exports = {
    pluginOptions: {
        jestSerializer: {
            // All available options: https://github.com/beautify-web/js-beautify/blob/master/js/src/html/options.js
            formatting: {
                indent_char: ' ',
                indent_inner_html: true,
                indent_size: 4,
                inline: [],
                sep: '\n',
                unformatted: ['code', 'pre'],
            },
            removeClassTest: false,
            removeComments: false,
            removeDataTest: true,
            removeDataTestid: true,
            removeDataTestId: true,
            removeDataQa: false,
            removeDataVId: true,
            removeIdTest: false,
            removeServerRendered: true,
            stringifyObjects: false,
        },
    },
};

tsconfig.json

{
    "compilerOptions": {
        "baseUrl": "./",
        "target": "es2021",
        "module": "es2020",
        "moduleResolution": "node",
        "jsx": "preserve",
        "sourceMap": true,
        "strict": true,
        "downlevelIteration": true, // This flag is to enable support for a more accurate implementation of how modern JavaScript iterates through new concepts in older JavaScript runtimes
        "esModuleInterop": true,
        "noImplicitAny": false,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "allowSyntheticDefaultImports": true,
        "lib": ["es6", "dom", "es2017", "es2016.array.include", "es2018.promise", "ES2020.String"],
        "paths": {
            "@VueForms/*": ["../Tts.Portal.VueForms/src/*"],
            "@/*": ["src/*"],
            "*": ["node_modules/*"]
        }
    }
}

webpack.config.js

/* eslint-env node */
/* eslint-disable @typescript-eslint/no-var-requires */

const path = require('path');
const webpack = require('webpack');

const VueLoaderPlugin = require('vue-loader/dist/plugin').default;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const ncp = require('ncp').ncp;
const sass = require('sass');
const Dotenv = require('dotenv-webpack');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const vueFormsBundlesDir = '../web/vue-forms-bundles';

const config = {
    entry: {
        'cart-page': './src/bundles/cartPage.ts',
        'checkout-page': './src/bundles/checkoutPage.ts',
        'confirmation-commerce-page': './src/bundles/confirmationCommercePage.ts',
        'shipping-hint': './src/bundles/shippingHint.ts',
        'cart-service': './src/bundles/cartService.ts',
        'products-teaser-slider': './src/bundles/productsTeaserSlider.ts',
        'product-price-information': './src/bundles/productPriceInformationContainer.ts',
        'similar-jobs': './src/bundles/jobDetailsPage.ts',
        'global-vue-frontend-container': './src/bundles/globalContainer.ts',
        'order-overview-page': './src/bundles/orderOverviewPage.ts',
        'order-quick-view': './src/bundles/orderQuickView.ts',
        'order-detail-page': './src/bundles/orderDetailPage.ts',
    },
    output: {
        path: path.resolve(__dirname, vueFormsBundlesDir),
        filename: '[name]-bundle.js',
    },
    resolve: {
        extensions: ['.ts', '.js', '.vue', '.json'],
        modules: [path.resolve(__dirname, 'node_modules')],
        alias: {
            'fuse.js': 'fuse.js/dist/fuse.min.js',
            '@': path.resolve('src'),
        },
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    compilerOptions: {
                        isCustomElement: (tag) => tag === 'lottie-player',
                    },
                },
            },
            {
                test: /\.ts$/,
                exclude: /node_modules/,
                use: {
                    loader: 'ts-loader',
                    options: {
                        onlyCompileBundledFiles: true,
                        appendTsSuffixTo: [/\.vue$/],
                        transpileOnly: true,
                    },
                },
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            implementation: sass,
                            sourceMap: false, // On chrome there is an issue that when changing css in dev console, it breaks page. No source map fixes it.
                            sassOptions: {
                                quietDeps: true, // Disable warning messages from dependencies
                            },
                        },
                    },
                ],
            },
        ],
    },
    watchOptions: {
        ignored: /node_modules/,
        aggregateTimeout: 150,
    },
    plugins: [
        new webpack.DefinePlugin({
            __VUE_OPTIONS_API__: true,
            __VUE_PROD_DEVTOOLS__: false,
        }),
        new ForkTsCheckerWebpackPlugin({
            async: true,
            typescript: {
                extensions: {
                    vue: {
                        enabled: true,
                        compiler: '@vue/compiler-sfc',
                    },
                },
            },
            issue: { exclude: [{ code: 'TS1192' }] }, // ignore `no default export` errors as known plugin issue
        }),
        // new BundleAnalyzerPlugin(),
    ],
    optimization: {
        splitChunks: {
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]((?!(awesome-phonenumber)).*)[\\/]/,
                    name: 'vendors-vue-3',
                    chunks: 'all',
                    minChunks: 3,
                    reuseExistingChunk: true,
                },
            },
        },
    },
};

module.exports = (env, argv) => {
    config.plugins.push(
        new Dotenv({
            path: `./.env`,
        })
    );

    if (argv.mode === 'development') {
        config.devtool = 'source-map';
        config.watch = true;
        config.watchOptions = {
            aggregateTimeout: 250,
            ignored: ['node_modules'],
        };
    }

    return config;
};

package.json

{
  "name": "MY_VUE_PROJECT",
  "version": "1.0.0",
  "scripts": {
    "format": "npm run format:templates && npm run lint:fix",
    "format:templates": "html-beautify --replace ./src/**/*.vue",
    "lint": "eslint ./src/** --color --config ../../.eslintrc.json",
    "lint:quiet": "eslint ./src/** --quiet --config ../../.eslintrc.json",
    "lint:fix": "eslint ./src/** --fix --config ../../.eslintrc.json",
    "npm-auth": "npx vsts-npm-auth -T \"%USERPROFILE%/.npmrc\" -C ./.npmrc",
    "webpack:dev": "webpack --mode=development --progress --stats normal",
    "webpack:prod": "webpack --mode=production --progress --stats errors-only",
    "webpack:inspect": "webpack --profile --json > stats.json",
    "test:unit": "jest",
    "test:update": "jest -u",
    "test:watch": "jest --watch",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ],
  "private": true,
  "devDependencies": {
    "@babel/core": "^7.23.7",
    "@babel/helper-compilation-targets": "^7.23.6",
    "@babel/preset-env": "^7.23.8",
    "@paypal/paypal-js": "^5.1.1",
    "@storybook/addon-essentials": "^7.6.10",
    "@storybook/addon-interactions": "^7.6.10",
    "@storybook/addon-links": "^7.6.10",
    "@storybook/blocks": "^7.6.10",
    "@storybook/test": "^7.6.10",
    "@storybook/vue3": "^7.6.10",
    "@storybook/vue3-webpack5": "^7.6.10",
    "@stripe/stripe-js": "^1.48.0",
    "@types/googlemaps": "^3.43.3",
    "@types/jest": "^29.5.11",
    "@types/jquery": "^3.5.16",
    "@typescript-eslint/eslint-plugin": "^5.46.1",
    "@typescript-eslint/parser": "^5.46.1",
    "@vee-validate/rules": "4.5.11",
    "@vue/babel-preset-app": "^5.0.8",
    "@vue/compiler-sfc": "^3.4.15",
    "@vue/test-utils": "2.4.1",
    "@vue/vue3-jest": "^29.2.6",
    "awesome-phonenumber": "^3.2.0",
    "axios": "^0.27.2",
    "babel-jest": "^29.7.0",
    "css-loader": "^6.7.1",
    "dotenv-webpack": "^7.0.3",
    "eslint": "^8.29.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-jest": "^27.1.6",
    "eslint-plugin-prettier-vue": "^4.2.0",
    "eslint-plugin-storybook": "^0.6.15",
    "eslint-plugin-vue": "^9.19.2",
    "fork-ts-checker-webpack-plugin": "^6.5.2",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "jest-serializer-vue-tjw": "^3.20.0",
    "jest-transform-stub": "^2.0.0",
    "jest-watch-typeahead": "^2.2.0",
    "js-beautify": "^1.14.7",
    "jwt-decode": "^3.1.2",
    "lodash": "^4.17.21",
    "mini-css-extract-plugin": "^2.6.0",
    "ncp": "^2.0.0",
    "nswag": "^13.15.10",
    "prettier": "^2.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.51.0",
    "sass-loader": "^12.6.0",
    "storybook": "^7.6.10",
    "ts-jest": "^29.1.1",
    "ts-loader": "^9.5.1",
    "tslib": "^2.6.2",
    "typescript": "5.3.3",
    "vee-validate": "4.5.11",
    "vue": "3.4.7",
    "vue-loader": "^17.4.2",
    "vue-style-loader": "^4.1.3",
    "vuex": "^4.1.0",
    "webpack": "^5.72.1",
    "webpack-bundle-analyzer": "^4.5.0",
    "webpack-cli": "^4.9.2",
    "yup": "^0.32.11"
  },
  "devDependenciesComments": "@vue/test-utils version 2.4.2 breaks setProps. Should be fixed with https://github.com/vuejs/test-utils/pull/2242",
  "files": [
    "/dist/**"
  ],
  "engines": {
    "node": ">=14.0.0",
    "npm": ">=7.0.0",
    "vscode": "^1.57.0"
  }
}

System

Storybook Environment Info:

  System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 12th Gen Intel(R) Core(TM) i7-1270P
  Binaries:
    Node: 20.5.0 - C:\Program Files\nodejs\node.EXE
    npm: 9.8.0 - C:\Program Files\nodejs\npm.CMD <----- active
  Browsers:
    Edge: Chromium (120.0.2210.144)
  npmPackages:
    @storybook/addon-essentials: ^7.6.10 => 7.6.10
    @storybook/addon-interactions: ^7.6.10 => 7.6.10
    @storybook/addon-links: ^7.6.10 => 7.6.10
    @storybook/blocks: ^7.6.10 => 7.6.10
    @storybook/test: ^7.6.10 => 7.6.10
    @storybook/vue3: ^7.6.10 => 7.6.10
    @storybook/vue3-webpack5: ^7.6.10 => 7.6.10
    eslint-plugin-storybook: ^0.6.15 => 0.6.15
    storybook: ^7.6.10 => 7.6.10

Additional context

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions