storybookjs / builder-vite

A builder plugin to run and build Storybooks with Vite
MIT License
886 stars 109 forks source link

[Bug] Missing VITE_ env vars in built storybook #489

Open FezVrasta opened 1 year ago

FezVrasta commented 1 year ago

What version of vite are you using?

3.0.9

System info and storybook versions

  System:
    OS: macOS 12.5.1
    CPU: (10) arm64 Apple M1 Max
  Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    Yarn: 3.1.0 - ~/.nvm/versions/node/v16.16.0/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
  Browsers:
    Chrome: 104.0.5112.101
    Firefox: 103.0.1
    Safari: 15.6.1
  npmPackages:
    @storybook/addon-actions: ^6.5.10 => 6.5.10 
    @storybook/addon-essentials: ^6.5.10 => 6.5.10 
    @storybook/addon-storyshots: ^6.5.10 => 6.5.10 
    @storybook/builder-vite: ^0.2.2 => 0.2.2 
    @storybook/node-logger: ^6.5.10 => 6.5.10 
    @storybook/react: ^6.5.10 => 6.5.10

Describe the Bug

Environment variables are not being injected into import.meta.env on production builds (output of build-storybook), they are available on start-storybook though).

The only variables available are the ones starting with STORYBOOK_, but others starting with VITE_ and the whitelisted ones such as NODE_ENV, STORYBOOK etc are all unset.

I tried to console.log the env variables in build.ts and I see them correctly populated. It's not clear at which point they get removed/ignored.

The only way to access them seems to use the import.meta.env.VARIABLE_NAME literal, the import.meta.env object is missing them.

Interestingly enough, if I add finalConfig.define['import.meta.test'] = finalConfig.define['import.meta.env']; right after finalConfig.define is set with the environment variables, I can then console.log(import.meta.test) and I can see the variables in it.

I feel like Vite is doing something with import.meta.env...

Link to Minimal Reproducible Example

No response

Participation

IanVS commented 1 year ago

Hi, https://github.com/storybookjs/builder-vite/blob/0affa702ec8ef7231e6274fb33a7ff27dc1d01b9/packages/builder-vite/envs.ts#L47 is where we handle stringifying everything for import.meta.env.

Can you share a minimal reproduction that demonstrates the issue you're seeing?

FezVrasta commented 1 year ago

I tried to create a repro but I'm getting a problem on the storybook prod build where Storybook renders itself instead of the sample story I provided. When ran with start-storybook it works as expected.

https://github.com/fezvrasta/storybook-builder-vite-issue-489

CleanShot 2022-08-30 at 2 39 13@2x
limbyungki commented 1 year ago

"vue": "^3.2.39" "@storybook/builder-vite": "^0.2.2"

err

Cannot read properties of undefined (reading 'VITE_KAKAO_MAP_APP_KEY')
TypeError: Cannot read properties of undefined (reading 'VITE_KAKAO_MAP_APP_KEY')
    at http://localhost:6006/main.iframe.bundle.js:1479:89
    at callWithErrorHandling (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:32745:22)
    at callWithAsyncErrorHandling (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:32754:21)
    at hook.__weh.hook.__weh (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:35269:29)
    at flushPostFlushCbs (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:32926:47)
    at render (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:38799:9)
    at mount (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:37004:25)
    at app.mount (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:42194:23)
    at app.mount (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:103825:21)
    at PreviewWeb.renderToDOM (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-node_modules_storybook_addon-backgrou-412778.iframe.bundle.js:25478:25)
IanVS commented 1 year ago

@limbyungki can you share the section of your code where this is coming from?

limbyungki commented 1 year ago
onMounted(() => {
  if (window.kakao && window.kakao.maps) {
    initMap();
  } else {
    const script = document.createElement('script');
    script.onload = () => kakao.maps.load(initMap);
    const appkey = import.meta.env.VITE_KAKAO_MAP_APP_KEY;
    script.src =
      'http://dapi.kakao.com/v2/maps/sdk.js?autoload=false&appkey=' + appkey;
    document.head.appendChild(script);
  }
});
IanVS commented 1 year ago

Thanks. Do you have any kind of envPrefix set in your viteFinal, by chance? https://vitejs.dev/config/shared-options.html#envprefix

limbyungki commented 1 year ago

vite.config.js

import path from 'path';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vuetify from 'vite-plugin-vuetify';
import vueI18n from '@intlify/vite-plugin-vue-i18n';
import { VitePWA } from 'vite-plugin-pwa';

export default defineConfig({
  plugins: [
    vue(),
    vueI18n({
      include: path.resolve(__dirname, './src/locales/**'),
    }),
    VitePWA(),
    vuetify({ autoImport: true }),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'vue-i18n': 'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js',
    },
  },
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: 'vuetify.config.js',
    deps: {
      inline: ['vuetify'],
    },
  },
  server: {
    port: '3000',
  },
});

.storybook/main.js

const path = require('path');
const { mergeConfig } = require('vite');
const vuetify = require('vite-plugin-vuetify');

module.exports = {
  stories: [
    '../src/**/Intro.stories.mdx',
    '../src/components/stories/ui/*.stories.mdx',
    '../src/components/stories/functional/*.stories.mdx',
    '../src/components/stories/app/*.stories.mdx',
    '../src/**/*.stories.mdx',
    '../src/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    'storybook-addon-vuetify3',
  ],
  framework: '@storybook/vue3',
  core: {
    builder: '@storybook/builder-vite',
    //builder: '@storybook/builder-webpack5',
  },
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
    });
    return config;
  },
  async viteFinal(config, { configType }) {
    config.resolve.alias['~storybook'] = path.resolve(__dirname);
    config.resolve.alias['@'] = path.resolve(__dirname, '..', 'src');
    config.plugins = [
      ...config.plugins,
      vuetify({
        autoImport: true,
      }),
    ];
    return mergeConfig(config, {
      // customize the Vite config here
      resolve: {
        alias: {
          '@': path.resolve(__dirname, 'src'),
        },
      },
    });
  },
  features: {
    storyStoreV7: true,
  },
};

.storybook/preview.js

import { withVuetify } from 'storybook-addon-vuetify3/dist/decorators';
import { app } from '@storybook/vue3';
import SgButton from '@/components/common/ui/SgButton.vue';
import SgRadio from '@/components/common/ui/SgRadio.vue';
import SgTitle from '@/components/common/ui/SgTitle.vue';
import SgLabel from '@/components/common/ui/SgLabel.vue';
import SgMap from '@/components/common/functional/SgMap.vue';
import SgImageViewer from '@/components/common/functional/SgImageViewer.vue';
import SgCheckbox from '@/components/common/ui/SgCheckbox.vue';

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

export const decorators = [
  withVuetify,
  (_) => {
    // loadFonts();
    app.component('SgTitle', SgTitle);
    app.component('SgLabel', SgLabel);
    app.component('SgMap', SgMap);
    app.component('SgButton', SgButton);
    app.component('SgRadio', SgRadio);
    app.component('SgImageViewer', SgImageViewer);
    app.component('SgCheckbox', SgCheckbox);
    return {
      template: `<story />`,
    };
  },
];