Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue] storybook build throws Parse error @:1:1 while storybook dev works #570

Open
1 task
oxypomme opened this issue Apr 4, 2023 · 6 comments
Open
1 task
Labels
bug Something isn't working

Comments

@oxypomme
Copy link

oxypomme commented Apr 4, 2023

What version of vite are you using?

4.2.1

System info and storybook versions

System:
OS: Linux 5.14 Ubuntu 20.04.2 LTS (Focal Fossa)
CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
Binaries:
Node: 18.15.0 - ~/.nvm/versions/node/v18.15.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v18.15.0/bin/yarn
npm: 8.19.4 - ~/Documents/Work/ezreeport/node_modules/.bin/npm
Browsers:
Firefox: 111.0.1
npmPackages:
@storybook/addon-essentials: ^7.0.0 => 7.0.2
@storybook/addon-interactions: ^7.0.0 => 7.0.2
@storybook/addon-links: ^7.0.0 => 7.0.2
@storybook/addons: ^7.0.0 => 7.0.2
@storybook/blocks: ^7.0.0 => 7.0.2
@storybook/testing-library: ^0.0.13 => 0.0.13
@storybook/vue: ^7.0.0 => 7.0.2
@storybook/vue-vite: ^7.0.0 => 7.0.2

Describe the Bug

I've got an issue where running storybook dev works and I can access storybook through a web browser with no problems ...

> storybook dev -p 6006

@storybook/cli v7.0.2

info => Starting manager..
building in dev mode
╭─────────────────────────────────────────────────────╮
│                                                     │
│   Storybook 7.0.2 for vue-vite started              │
│   261 ms for manager and 406 ms for preview         │
│                                                     │
│    Local:            http://localhost:6006/         │
│    On your network:  http://172.16.101.136:6006/    │
│                                                     │
╰─────────────────────────────────────────────────────╯
Neither '~/mixins/ezr.vue' nor '~/mixins/ezr.js(x)' or '~/mixins/ezr/index.js(x)' or '~/mixins/ezr/index.ts(x)' could be found in '/home/sublet/Documents/Work/ezreeport/src/vue/src/components/public/tasks'
09:40:10 [vite] ✨ new dependencies optimized: vuetify/lib, vuedraggable
09:40:10 [vite] ✨ optimized dependencies changed. reloading

... while running storybook build throws an error Parse error @:1:1 by vite:build-import-analysis.

> storybook build

@storybook/cli v7.0.2

info => Cleaning outputDir: /storybook-static
info => Loading presets
info => Building manager..
info => Manager built (221 ms)
info => Copying static files: <rootDir>/node_modules/@storybook/manager/static at <rootDir>/storybook-static/sb-common-assets
vite v4.2.1 building for production...

./sb-common-assets/fonts.css doesn't exist at build time, it will remain unchanged to be resolved at runtime
transforming (79) .storybook/plugins/vuetify.tsNeither '~/mixins/ezr.vue' nor '~/mixins/ezr.js(x)' or '~/mixins/ezr/index.js(x)' or '~/mixins/ezr/index.ts(x)' could be found in '<rootDir>/src/components/internal/history'
✓ 299 modules transformed.
✓ built in 2.84s
[vite:build-import-analysis] Parse error @:1:1
file: <rootDir>/src/components/public/EzrProvider.vue
ERR! Error: Parse error @:1:1
ERR!     at parse$e (file://<rootDir>/node_modules/vite/dist/node/chunks/dep-79892de8.js:16018:355)
ERR!     at Object.transform (file://<rootDir>/node_modules/vite/dist/node/chunks/dep-79892de8.js:45421:27)
ERR!  Error: Parse error @:1:1
ERR!     at parse$e (file://<rootDir>/node_modules/vite/dist/node/chunks/dep-79892de8.js:16018:355)
ERR!     at Object.transform (file://<rootDir>/node_modules/vite/dist/node/chunks/dep-79892de8.js:45421:27) {
ERR!   idx: 0,
ERR!   id: '<rootDir>/src/components/public/EzrProvider.vue',
ERR!   hook: 'transform',
ERR!   code: 'PLUGIN_ERROR',
ERR!   plugin: 'vite:build-import-analysis',
ERR!   watchFiles: [
ERR!     ... 728 more items
ERR!   ]
ERR! }

(I skipped watchFiles and hidden paths because it doesn't seems revelent and yes, I tried to fix the issue with ~/mixins/ezr.vue and it didn't solve my problem)

From what I understand, the issue may be from EzrProvider.vue while it that seems perfectly right :

// src/EzrProvider.vue
<template>
  <div v-if="ready">
    <slot />
  </div>
</template>

<script lang="ts">
import { defineComponent, type PropType } from 'vue';
import * as sdk from 'ezreeport-sdk-js';
import { type InjectedEzReeport, InjectionEzReeportKey } from '~/mixins/ezr';

export default defineComponent({
  props: {
    token: {
      type: String as PropType<string | undefined>,
      default: undefined,
    },
    apiUrl: {
      type: String,
      default: import.meta.env.VITE_REPORT_API,
    },
    namespaceLogoUrl: {
      type: String,
      default: import.meta.env.VITE_NAMESPACES_LOGO_URL,
    },
    namespaceLabel: {
      type: Object as PropType<Record<string, string>>,
      default: () => {},
    },
  },
  data: (): InjectedEzReeport['data'] => ({
    ready: false,
    auth: {
      permissions: undefined,
      user: undefined,
    },
    namespaces: {
      data: [],
      logoUrl: '',
    },
  }),
  watch: {
    apiUrl(value: string) {
      sdk.setup.setURL(value);
    },
    namespaceLogoUrl(value: string) {
      this.namespaces.logoUrl = value;
    },
    // eslint-disable-next-line func-names
    '$i18n.locale': function () {
      this.registerNamespaceLocalization();
    },
    token(value?: string) {
      if (value) {
        this.login(value);
        return;
      }
      this.logout();
    },
  },
  provide() {
    const $ezReeport = {
      sdk,

      tcNamespace: (capitalize?: boolean, choice?: number) => {
        const res = this.$tc('namespace', choice).toString();

        if (capitalize) {
          return `${res.at(0)?.toLocaleUpperCase() ?? ''}${res.slice(1)}`;
        }
        return res;
      },

      fetchNamespaces: (force?: boolean) => this.fetchNamespaces(force),
      login: (token: string) => this.login(token),
      logout: () => this.logout(),
      hasGeneralPermission: (permission: string) => this.hasGeneralPermission(permission),
      hasNamespacedPermission: (
        permission: string,
        namespaces: string[],
      ) => this.hasNamespacedPermission(permission, namespaces),
    };

    Object.defineProperties(
      $ezReeport,
      {
        data: {
          enumerable: true,
          get: () => this.$data,
        },
        isLogged: {
          enumerable: true,
          get: () => this.auth.user !== undefined,
        },
      },
    );

    return {
      [InjectionEzReeportKey]: $ezReeport,
    };
  },
  mounted() {
    sdk.setup.setURL(this.apiUrl);
    this.namespaces.logoUrl = this.namespaceLogoUrl;
    this.registerNamespaceLocalization();
    if (this.token) {
      this.login(this.token);
    }

    // Rendering childrens will trigger requests to API
    // and it can be before we set the correct URL.
    // ? maybe a v-if on each public component is better than here
    this.ready = true;
  },
  methods: {
    registerNamespaceLocalization() {
      // eslint-disable-next-line no-restricted-syntax
      for (const [locale, label] of Object.entries(this.namespaceLabel)) {
        this.$i18n.mergeLocaleMessage(locale, { namespace: label });
      }
    },
    /**
     * Add token into SDK, fetch permissions & current user
     *
     * @param token The API token for ezMESURE
     */
    login(token: string) {
      sdk.auth.login(token);

      Promise.allSettled([
        sdk.auth.getCurrentPermissions()
          .then(({ content }) => { this.auth.permissions = content; }),

        sdk.auth.getCurrentUser()
          .then(({ content }) => { this.auth.user = content; }),
      ]).then((results) => {
        // eslint-disable-next-line no-restricted-syntax
        for (const res of results) {
          if (res.status === 'rejected') {
            console.error('[ezReeport-vue]', res.reason.message);
          }
        }
      });
    },
    /**
     * Remove token from SDK, clear permissions & current user
     */
    logout() {
      sdk.auth.logout();
      this.auth.permissions = undefined;
      this.auth.user = undefined;
    },
    /**
     * Shorthand to fetch namespaces and make it available into whole Vue.
     *
     * If namespaces was already fetched before, it will not re-fetch
     *
     * @param force Force reload
     */
    async fetchNamespaces(force = false): Promise<sdk.namespaces.Namespace[]> {
      if (force || this.namespaces.data.length <= 0) {
        if (this.hasNamespacedPermission('auth-get-namespaces', [])) {
          const { content } = await sdk.auth.getCurrentNamespaces();
          if (!content) {
            throw new Error(this.$t('errors.no_data').toString());
          }

          this.namespaces.data = content;
        } else {
          this.namespaces.data = [];
        }
      }
      return this.namespaces.data;
    },
    /**
     * Check if logged user have permission to do some action
     *
     * @param permission The permission name
     *
     * @returns If the user have the permission
     */
    hasGeneralPermission(permission: string) {
      return !!this.auth.permissions?.general[permission];
    },
    /**
     * Check if logged user have permission in namespaces to do some action
     *
     * @param permission The permission name
     * @param namespaces The concerned namespaces. If empty will attempt
     * to find at least one in all possibles
     *
     * @returns If the user have the permission
     */
    hasNamespacedPermission(permission: string, namespaces: string[]) {
      let entries = Object.entries(this.auth.permissions?.namespaces ?? {});

      if (namespaces.length > 0) {
        entries = entries.filter(([namespace]) => namespaces.includes(namespace));
      }
      return !!entries.find(([, perms]) => perms[permission]);
    },
  },
});
</script>

<style scoped>

</style>

<i18n lang="yaml">
en:
  namespace: 'namespace'
  errors:
    no_data: 'An error occurred when fetching data'
fr:
  namespace: 'espace'
  errors:
    no_data: 'Une erreur est survenue lors de la récupération des données'
</i18n>

I also suspect that the issue may come from .storybook/preview.ts or .storybook/main.ts :

// .storybook/main.ts
/* eslint-disable import/no-import-module-exports */
import { mergeConfig } from 'vite';
import type { StorybookConfig } from '@storybook/types';
import type { StorybookConfigVite } from '@storybook/builder-vite';

const config: StorybookConfig & StorybookConfigVite = {
  stories: [
    // '../src/**/*.mdx',
    '../src/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
  ],
  framework: {
    name: '@storybook/vue-vite',
    options: {},
  },
  docs: {
    autodocs: 'tag',
  },
  core: {
    builder: '@storybook/builder-vite',
  },
  typescript: {
    check: false,
  },
  viteFinal: (cfg) => mergeConfig(cfg, {
    optimizeDeps: {
      include: [
        'vuetify',
        'vue-i18n',
        'vuetify/src/locale',
        '@storybook/addon-essentials/docs/mdx-react-shim',
        '@storybook/blocks',
      ],
    },
  }),
};

module.exports = config;
// .storybook/preview.ts
/// <reference types="../src/types/env" />

import Vue, { defineComponent } from 'vue';
import Vuetify from 'vuetify';
import type { Decorator, Parameters } from '@storybook/vue';
import i18n from './plugins/i18n';
import vuetify from './plugins/vuetify';
import ezReeport from '../src';

// Setup Vuetify
Vue.use(Vuetify);

// Setup i18n
// eslint-disable-next-line no-underscore-dangle
Vue.prototype._i18n = i18n;

// Setup ezReeport plugin
Vue.use(ezReeport);
if (!import.meta.env.VITE_AUTH_TOKEN) {
  console.warn('[ezReeport-storybook] Auth token not found');
}

export const parameters: Parameters = {};

export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme for components',
    defaultValue: 'light',
    toolbar: {
      icon: 'paintbrush',
      items: ['light', 'dark'],
      dynamicTitle: true,
    },
  },
  locale: {
    name: 'Locale',
    description: 'Internationalization locale',
    defaultValue: 'en',
    toolbar: {
      icon: 'globe',
      items: [
        { value: 'en', title: 'English' },
        { value: 'fr', title: 'Français' },
      ],
    },
  },
};

export const decorators: Decorator[] = [
  (story, context) => defineComponent({
    name: 'StorybookPreview',
    vuetify,
    i18n,
    components: { story },
    props: {
      theme: {
        type: String,
        default: context.globals.theme,
      },
      locale: {
        type: String,
        default: context.globals.locale,
      },
    },
    data: () => ({
      token: import.meta.env.VITE_AUTH_TOKEN,
    }),
    watch: {
      theme: {
        immediate: true,
        handler(val) {
          this.$vuetify.theme.dark = val === 'dark';
        },
      },
      locale: {
        immediate: true,
        handler(val) {
          this.$i18n.locale = val;
        },
      },
    },
    computed: {
      namespaceLabel() {
        return {
          en: 'namespace | namespaces',
          fr: 'établissement | établissements',
        };
      },
    },
    template: `
        <v-app>
          <ezr-provider :token="token" :namespaceLabel="namespaceLabel">
            <v-container fluid>
              <story />
            </v-container>
          </ezr-provider>
        </v-app>
      `,
  }),
];

I think this issue is very specific to my setup, so I can't really reproduce in a codesandbox or something (tho I really like to) so I linked to the repo at a commit where the issue happens.

Link to Minimal Reproducible Example

https://github.com/ezpaarse-project/ezreeport/tree/19622bb039ef22177222b50f01eb57f683f39c1e/src/vue

Participation

  • I am willing to submit a pull request for this issue.
@oxypomme oxypomme added the bug Something isn't working label Apr 4, 2023
@IanVS
Copy link
Member

IanVS commented Apr 4, 2023

Hi, Storybook 7 has been released, could you try upgrading using npx sb upgrade and letting us know if that fixes your issue?

@oxypomme
Copy link
Author

oxypomme commented Apr 4, 2023

I just did and it only changed the core section by removing @storybook/builder-vite

- core: {
-    builder: '@storybook/builder-vite',
- },
+ core: {},

And set versions of storybook to ^7.0.2 in package.json & package-lock.json.
The result of storybook dev and storybook build are the same

@IanVS
Copy link
Member

IanVS commented Apr 4, 2023

It should have also added a framework to your main.js. But regardless, are you able to create a reproduction of the issue that we can look into?

@oxypomme
Copy link
Author

oxypomme commented Apr 5, 2023

It should have also added a framework to your main.js.

Yeah, framework was already in the config.

But regardless, are you able to create a reproduction of the issue that we can look into?

When trying to replicate the issue, I found out that issue is from using import.meta.env in the default value of a prop. So doing the following will crash :

export default defineComponent({
  props: {
    firstProp: {
      type: String,
      default: import.meta.env.FIRST_ENV_VAR,
    },
    secondProp: {
      type: String,
      default: 'some kind of prop',
    },
  },
 });

But I can use env vars in other places, so I found a workaround by using a variable :

export default defineComponent({
 props: {
   firstProp: {
     type: String,
-     default: import.meta.env.FIRST_ENV_VAR,
+     default: ''
   },
   secondProp: {
     type: String,
     default: 'some kind of prop',
   },
 },
+ computed: {
+  // Actual value of firstProp
+  firstPropValue() {
+    return this.firstProp ||  import.meta.env.FIRST_ENV_VAR;
+  }, 
+ },
});

I don't think this is an issue with vite or vue (as storybook dev or vite build works) but it's kinda weird.

@kenny-f
Copy link

kenny-f commented Nov 23, 2023

Am also seeing this issue with vite and react
dev works fine, but as soon as I try to run storybook build it errors with Unexpected token (Note that you need plugins to import files that are not JavaScript) whenever it comes across import.meta.env.VITE_XXX

@1361751025
Copy link

Thank you for oxypomme!you helped me fix the error!!!good guy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants