Skip to content

histoire

1、在monorepo中使用

方案1:

  • 1.1、在根目录下创建一个histoire.config.ts文件,然后使用histoire的api来配置histoire
  • 1.2、但是涉及到packages中,有vue2和vue3情况,写两个histoire.config.ts文件,分别走不同的配置
    js
    const mode = process.env.MODE || 'vue3'
    import histoireConfigVue2 from './histoire.config.vue2.js'
    import histoireConfigVue3 from './histoire.config.vue3.js'
    
    export default mode === 'vue2' ? histoireConfigVue2 : histoireConfigVue3
  • 1.3、plugins配置:走不同的vue2 @histoire/plugin-vue2和vue3 @histoire/plugin-vue的插件
  • 1.4、vite配置:vue插件使用不同的插件 vue3 @vitejs/plugin-vue vue2 @vitejs/plugin-vue2
  • 1.5、但是应该是依旧报错,vue如何区分是一个问题,使用包别名来区分,还是?尝试各种配置无果,改用方案2

方案2:

  • 2.1、在packages vue3、vue2的文件夹中配置histoire.config.ts文件、并且安装histoire
  • 2.2、在根目录下创建一个使用pnpm --filter @play/vue3 dev:story 调用内部执行
  • 2.3、这样就避免的了冲突报错

2、histoire 配置

vue2中的配置

  • histoire.config.js
js
import { defineConfig } from 'histoire'
import { HstVue } from '@histoire/plugin-vue2'
export default defineConfig({
  plugins: [
    HstVue(),
  ],
  outDir: '../../docs/vue2',
  storyMatch: [
    '**/src/**/*.story.vue',
  ],
  storyIgnored: [
    '**/node_modules/**',
    '**/dist/**',
  ],
  vite: {
    base: '/play/vue2/',
  },
  setupFile: './histoire.setup.js',
})
  • histoire.setup.js
js
import { defineSetupVue2 } from '@histoire/plugin-vue2'
// 给histoire 中的vue2添加全局样式 以及 其他全局配置
import 'element-ui/lib/theme-chalk/index.css'
import 'vxe-table/lib/style.css'
import '@/directives/index'
import store from '@/store'
import EventBus from '@/utils/eventBus'
import Vue from 'vue'

Vue.prototype.$EventBus = EventBus

export const setupVue2 = defineSetupVue2(({ story, variant }) => {
  return {
    store,
  }
})

vue3中的配置

  • histoire.config.ts
ts
import { defineConfig } from 'histoire'
import { HstVue } from '@histoire/plugin-vue'

export default defineConfig({
  plugins: [
    HstVue(),
  ],
  outDir: '../../docs/vue3',
  storyMatch: [
    '**/src/**/*.story.vue',
  ],
  storyIgnored: [
    '**/node_modules/**',
    '**/dist/**',
  ],
  vite: {
    base: '/play/vue3/',
    // optimizeDeps: {
    //   include: ['vueuc','date-fns-tz'], // 不起作用
    // },
    ssr: {
      // 因为引入ui组件,naive-ui在histoire build 的时候报错
      // vueuc 和 date-fns-tz 都是按照commonjs 加载了
      // 这里要错一层处理
      /*
        Histoire 在收集 stories 时,其实是跑在 Node ESM 环境下(类似 SSR)。
        默认情况下,Vite 会把 node_modules 的依赖标记为 external,也就是 Node 自己去解析。
        这条配置告诉 Vite:
        “不要把这些包当外部模块,让 Vite 直接打包/编译成 ESM 再给 Node 用。”
        因为 date-fns-tz 的 ESM 包和 CommonJS 包混合,Node 直接去解析目录导入就会报错 (ERR_UNSUPPORTED_DIR_IMPORT)。
        加了 noExternal 后,Vite 自己处理成干净的 ESM,Node 就能直接执行,不再报错。 */
      /*
        为什么本地没问题,CI 报错
        本地 Windows/macOS 文件系统大小写不敏感,Node 对导入目录有容错。
        CI 是 Linux,大小写敏感,Node 的 ESM loader 对目录导入严格检查 → 如果不经过 Vite 编译,就会报 ERR_UNSUPPORTED_DIR_IMPORT。
        ssr.noExternal 让 Vite 在收集 stories 阶段先把模块打包成 ESM → Node 就能正确加载。

        https://chatgpt.com/c/68ba9b4a-d4a4-832c-9167-642e78450e25
      */
      noExternal: ['naive-ui', 'vueuc', 'date-fns-tz'], // 确保 SSR / 构建时不会当作 CJS 起作用
    },
    // resolve: {
    //   alias: {
    //     'date-fns-tz/dist/esm': 'date-fns-tz/dist/esm/index.js', // 不起作用
    //   },
    // },
  },
  setupFile: './histoire.setup.ts',
})
  • histoire.setup.ts
ts
import { defineSetupVue3 } from '@histoire/plugin-vue'
import { setupDirectives } from '@/directives'
import { setupStore } from '@/store'
import AppProvider from '@/common/AppProvider/index.vue'

export const setupVue3 = defineSetupVue3(({ app,addWrapper }) => {
  // 添加 provider
  addWrapper(AppProvider);
  // 添加 store
  setupStore(app);
  // 添加 directive
  setupDirectives(app);
})