qmhc / vite-plugin-dts

A Vite plugin for generating `.d.ts` files.
MIT License
1.28k stars 88 forks source link

Markdown file not found at build #128

Closed RuBaWa closed 1 year ago

RuBaWa commented 2 years ago

I am building a vue 3 plugin with vite and ts. at build, i get this error:

[vite:dts] Start generate declaration files...
transforming (472) node_modules\lodash\_isKeyable.js[vite:dts] Declaration files built in 32929ms.

[vite:dts] File not found: project/path/CHANGELOG.md?vue&type=script&setup=true&lang.ts
file: project/path/CHANGELOG.md?vue&type=script&setup=true&lang.ts
error during build:
Error: File not found: project/path/CHANGELOG.md?vue&type=script&setup=true&lang.ts
    at DirectoryCoordinator.addSourceFileAtPath (project\path\node_modules\ts-morph\dist\ts-morph.js:18714:19)
    at Project.addSourceFileAtPath (project\path\node_modules\ts-morph\dist\ts-morph.js:20161:51)
    at Object.transform (project\path\node_modules\vite-plugin-dts\dist\index.cjs:172890:17)
    at file:///project/path/node_modules/rollup/dist/es/shared/rollup.js:22710:40
error Command failed with exit code 1.

This file is available and in normal build for web, not plugin, without dts active, this files are included without errors.

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "useDefineForClassFields": true,
    "noImplicitThis": true,
    "target": "ESNext",
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ],
    "strict": true,
    // "preserveValueImports": true,
    "importsNotUsedAsValues": "error",
    "esModuleInterop": true,
    "jsx": "preserve",
    "sourceMap": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "noUnusedLocals": true,
    "importHelpers": true,
    "strictNullChecks": true,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "types": [
      "vitest/globals",
      "vite/client",
      "vue/ref-macros",
      "vite-plugin-pages/client",
      "vite-plugin-vue-layouts/client"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ],
      "@w/*": [
        "src/*"
      ],
      "@root/*": [
        "/*"
      ],
      "@w-root/*": [
        "/*"
      ]
    }
  },
  "exclude": [
    "node_modules"
  ],
  "vueCompilerOptions": {
    "experimentalSuppressInvalidJsxElementTypeErrors": true
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.vue",
    "*.ts"
    //   "tests/**/*.ts"
  ]
}

eslintrc.js

module.exports = {
  root: true,
  env: {
    'browser': true,
    'es6': true,
    'node': true,
    'vue/setup-compiler-macros': true,
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    '@vue/typescript/recommended',
    'prettier',
  ],
  plugins: ['prettier'],
  parserOptions: {
    ecmaVersion: 2021,
    sourceType: 'module',
  },
  ignorePatterns: ['node_modules/'],
  rules: {
    'prettier/prettier': ['warn', { endOfLine: 'auto' }],
    'no-alert': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'arrow-body-style': 'warn',
    'arrow-parens': 'warn',
    'eqeqeq': 'error',
    'generator-star-spacing': 'warn',
    'grouped-accessor-pairs': 'warn',
    'no-caller': 'error',
    'no-duplicate-imports': 'error',
    'no-else-return': 'warn',
    'no-eval': 'error',
    'no-extra-bind': 'warn',
    'no-implied-eval': 'error',
    'no-labels': 'warn',
    'no-lone-blocks': 'warn',
    'no-new-func': 'error',
    'no-new-wrappers': 'error',
    'no-return-await': 'warn',
    'no-template-curly-in-string': 'warn',
    'no-throw-literal': 'error',
    'no-undef-init': 'warn',
    'no-useless-call': 'warn',
    'no-useless-constructor': 'warn',
    'no-useless-rename': 'warn',
    'no-useless-return': 'warn',
    'no-var': 'error',
    'object-shorthand': 'warn',
    'prefer-const': 'warn',
    'prefer-destructuring': 'warn',
    'prefer-numeric-literals': 'warn',
    'prefer-rest-params': 'warn',
    'prefer-spread': 'warn',
    'prefer-template': 'warn',
    'require-atomic-updates': 'warn',
    'rest-spread-spacing': 'warn',
    'sort-imports': [
      'warn',
      {
        ignoreCase: true,
        ignoreDeclarationSort: true,
      },
    ],
    'template-curly-spacing': 'warn',
    'yield-star-spacing': 'warn',
    'yoda': 'warn',
    '@typescript-eslint/no-explicit-any': 'off',
    'vue/require-default-prop': 'off',
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always',
          normal: 'always',
          component: 'always',
        },
        svg: 'always',
        math: 'always',
      },
    ],
  },
};

vite.config.js

...
/// <reference types="vitest" />

import { resolve } from 'path';
import { defineConfig, type PluginOption } from 'vite';
import Vue from '@vitejs/plugin-vue';
import Pages from 'vite-plugin-pages';
import Layouts from 'vite-plugin-vue-layouts';
import Components from 'unplugin-vue-components/vite';
import AutoImport from 'unplugin-auto-import/vite';
import VueI18n from '@intlify/vite-plugin-vue-i18n';
import VueTypeImports from 'vite-plugin-vue-type-imports';
import Markdown from 'vite-plugin-md';
import { DirResolverHelper } from 'vite-auto-import-resolvers';
import svgLoader from 'vite-svg-loader';
import { visualizer } from 'rollup-plugin-visualizer';
import dts from 'vite-plugin-dts';

//import { BootstrapVueResolver } from './src/plugins/bootstrap';

export default defineConfig({
  base: '',

  // comment build out to get regular html dist files
  build:
    process.env.TARGET_WEB === undefined
      ? {
          minify: true,
          target: 'modules',
          lib: {
            entry: resolve(__dirname, 'src/WWBase.ts'),
            name: 'ww-base',
            fileName: (format) => `ww-base.${format}.js`,
          },
          rollupOptions: {
            external: [
              'bootstrap',
              'bootstrap/js/dist/alert',
              'bootstrap/js/dist/collapse',
              'bootstrap/js/dist/modal',
              'bootstrap/js/dist/offcanvas',
              'bootstrap/js/dist/popover',
              'bootstrap/js/dist/carousel',
              'bootstrap/js/dist/dropdown',
              'bootstrap/js/dist/tooltip',
              'vue',
            ],
            output: {
              globals: {
                'vue': 'Vue',
                'bootstrap': 'Bootstrap',
                'bootstrap/js/dist/collapse': 'Collapse',
                'bootstrap/js/dist/alert': 'Alert',
                'bootstrap/js/dist/carousel': 'Carousel',
                'bootstrap/js/dist/dropdown': 'Dropdown',
                'bootstrap/js/dist/modal': 'Modal',
                'bootstrap/js/dist/offcanvas': 'Offcanvas',
                'bootstrap/js/dist/popover': 'Popover',
                'bootstrap/js/dist/tooltip': 'Tooltip',
              },
              exports: 'named',
            },
          },
        }
      : {
          minify: true,
        },

  css: {
    devSourcemap: true,
    preprocessorOptions: {
      scss: {
        charset: false,
      },
    },
  },

  resolve: {
    alias: {
      '@/': `${resolve(__dirname, './src')}/`,
      '@w/': `${resolve(__dirname, './src')}/`,
      '@root/': `${resolve(__dirname, '.')}/`,
      '@w-root/': `${resolve(__dirname, '.')}/`,
    },
  },

  plugins: [
    Vue({
      include: [/\.vue$/, /\.md$/],
      reactivityTransform: false,
    }),

    process.env.TARGET_WEB === undefined
      ? dts({
          skipDiagnostics: false,
          logDiagnostics: true,
        })
      : null,

    VueTypeImports(),

    // https://github.com/hannoeru/vite-plugin-pages
    Pages({
      extensions: ['vue', 'md'],
    }),

    // https://github.com/JohnCampionJr/vite-plugin-vue-layouts
    Layouts({
      defaultLayout: 'default',
      //layoutsDirs: ['src/layouts', 'node_modules/ww-base/src/layouts']
      layoutsDirs: ['src/layouts'],
    }),

    // https://github.com/dishait/vite-auto-import-resolvers
    DirResolverHelper(),

    // https://github.com/antfu/unplugin-auto-import
    AutoImport({
      imports: ['vue', 'vue-router', 'vue-i18n', 'vue/macros', '@vueuse/head', '@vueuse/core'],
      dirs: [
        './src/composables',
        //'./src/services'
      ],
      dts: true,
    }),

    // https://github.com/antfu/vite-plugin-md
    Markdown(),

    // https://github.com/antfu/unplugin-vue-components
    // allow auto import and register components
    Components({
      extensions: ['vue'],
      deep: true,
      dts: true,
      directoryAsNamespace: true,
    }),

    // https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n
    VueI18n({
      runtimeOnly: true,
      compositionOnly: true,
      include: [resolve(__dirname, 'locales/**')],
    }),

    // https://github.com/jpkleemans/vite-svg-loader
    svgLoader({
      defaultImport: 'component',
      svgoConfig: {
        multipass: true,
        plugins: [
          {
            name: 'preset-default',
            params: {
              overrides: {
                removeViewBox: false,
              },
            },
          },
        ],
      },
    }),

    // vite bundle size analyzer
    // https://github.com/btd/rollup-plugin-visualizer
    process.env.ANALYZE
      ? (visualizer({
          open: true,
        }) as PluginOption)
      : null,
  ],

  // https://github.com/vitest-dev/vitest
  test: {
    include: ['test/**/*.test.ts'],
    environment: 'jsdom',
    deps: {
      inline: ['@vue', '@vueuse', 'vue-demi'],
    },
  },
});

Vue template

<script setup lang="ts">
import Changelog from '@root/CHANGELOG.md';
</script>

<template>
  <Changelog />
</template>
qmhc commented 2 years ago

Did you declare a module for markdown files in a dts file? Just like:

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, any>
  export default component
}

declare module '*.md' {
  const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, any>
  export default component
}
RuBaWa commented 2 years ago

Yes, here is my env.d.ts file in src folder:

/// <reference types="vite-plugin-pages/client" />
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />

declare interface Window {
  // extend the window
}

// with vite-plugin-md, markdown files can be treated as Vue components
declare module '*.md' {
  import { type DefineComponent } from 'vue';
  const component: DefineComponent<{}, {}, any>;
  export default component;
}

declare module 'mqtt/dist/mqtt.min' {
  import MQTT from 'mqtt';
  export = MQTT;
}

declare module '*.vue' {
  import type { DefineComponent } from 'vue';
  // eslint-disable-next-line @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>;
  export default component;
}
qmhc commented 2 years ago

Maybe you can try to add CHANGELOG.md and env.d.ts into tsconfig.json include (In my impression, *.ts does not include dts files).

But I don't understand why do you ship CHANGELOG.md into the exports for library? Will somebody use your project's CHANGELOG.md?

RuBaWa commented 2 years ago

The idea is, that i have a component, which automatically include CHANGELOG and README md files from root, to have standarized pages at our company projects. So users of this plugin should not need to import this md files on there own.

The files are included in plugin project, but are also placed in root folde rof projects, which uses this plugin. With vite aliases the path should be rewritten und reverence the local files. With webpack this was no problem. I am new to vite, maybe this is a bad practice?

I think, the best would be, if dts generation would ignore md files. But i will try add d.ts manually to tsconfig.

Thank you, for your help :-)

RuBaWa commented 2 years ago

It is not working. Now i have to remove all .md files. But thanks anyway