index.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import type { PluginOption } from 'vite';
  2. import type {
  3. ApplicationPluginOptions,
  4. CommonPluginOptions,
  5. ConditionPlugin,
  6. LibraryPluginOptions,
  7. } from '../typing';
  8. import { join } from 'node:path';
  9. import { getPackage } from '@vben/node-utils';
  10. import viteVueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
  11. import viteVue from '@vitejs/plugin-vue';
  12. import viteVueJsx from '@vitejs/plugin-vue-jsx';
  13. import { visualizer as viteVisualizerPlugin } from 'rollup-plugin-visualizer';
  14. import viteTurboConsolePlugin from 'unplugin-turbo-console/vite';
  15. import viteCompressPlugin from 'vite-plugin-compression';
  16. import viteDtsPlugin from 'vite-plugin-dts';
  17. import { createHtmlPlugin as viteHtmlPlugin } from 'vite-plugin-html';
  18. import { libInjectCss as viteLibInjectCss } from 'vite-plugin-lib-inject-css';
  19. import { VitePWA } from 'vite-plugin-pwa';
  20. import viteVueDevTools from 'vite-plugin-vue-devtools';
  21. import { viteExtraAppConfigPlugin } from './extra-app-config';
  22. import { viteImportMapPlugin } from './importmap';
  23. import { viteInjectAppLoadingPlugin } from './inject-app-loading';
  24. import { viteMetadataPlugin } from './inject-metadata';
  25. import { viteLicensePlugin } from './license';
  26. /**
  27. * 获取条件成立的 vite 插件
  28. * @param conditionPlugins
  29. */
  30. async function getConditionEstablishedPlugins(
  31. conditionPlugins: ConditionPlugin[],
  32. ) {
  33. const plugins: PluginOption[] = [];
  34. for (const conditionPlugin of conditionPlugins) {
  35. if (conditionPlugin.condition) {
  36. const realPlugins = await conditionPlugin.plugins();
  37. plugins.push(...realPlugins);
  38. }
  39. }
  40. return plugins.flat();
  41. }
  42. /**
  43. * 根据条件获取通用的vite插件
  44. */
  45. async function getCommonConditionPlugins(
  46. options: CommonPluginOptions,
  47. ): Promise<ConditionPlugin[]> {
  48. const { devtools, injectMetadata, isBuild, visualizer } = options;
  49. return [
  50. {
  51. condition: true,
  52. plugins: () => [
  53. viteVue({
  54. script: {
  55. defineModel: true,
  56. // propsDestructure: true,
  57. },
  58. }),
  59. viteVueJsx(),
  60. ],
  61. },
  62. {
  63. condition: !isBuild && devtools,
  64. plugins: () => [viteVueDevTools()],
  65. },
  66. {
  67. condition: injectMetadata,
  68. plugins: async () => [await viteMetadataPlugin()],
  69. },
  70. {
  71. condition: isBuild && !!visualizer,
  72. plugins: () => [<PluginOption>viteVisualizerPlugin({
  73. filename: './node_modules/.cache/visualizer/stats.html',
  74. gzipSize: true,
  75. open: true,
  76. })],
  77. },
  78. ];
  79. }
  80. /**
  81. * 根据条件获取应用类型的vite插件
  82. */
  83. async function getApplicationConditionPlugins(
  84. options: ApplicationPluginOptions,
  85. ): Promise<PluginOption[]> {
  86. // 单独取,否则commonOptions拿不到
  87. const isBuild = options.isBuild;
  88. const env = options.env;
  89. const {
  90. compress,
  91. compressTypes,
  92. extraAppConfig,
  93. html,
  94. i18n,
  95. importmap,
  96. importmapOptions,
  97. injectAppLoading,
  98. license,
  99. pwa,
  100. pwaOptions,
  101. turboConsole,
  102. ...commonOptions
  103. } = options;
  104. const commonPlugins = await getCommonConditionPlugins(commonOptions);
  105. return await getConditionEstablishedPlugins([
  106. ...commonPlugins,
  107. {
  108. condition: i18n,
  109. plugins: async () => {
  110. const pkg = await getPackage('@vben/locales');
  111. const include = `${join(pkg?.dir ?? '', isBuild ? 'dist' : 'src', 'langs')}/*.yaml`;
  112. return [
  113. viteVueI18nPlugin({
  114. compositionOnly: true,
  115. fullInstall: true,
  116. include,
  117. runtimeOnly: true,
  118. }),
  119. ];
  120. },
  121. },
  122. {
  123. condition: injectAppLoading,
  124. plugins: async () => [await viteInjectAppLoadingPlugin(!!isBuild, env)],
  125. },
  126. {
  127. condition: license,
  128. plugins: async () => [await viteLicensePlugin()],
  129. },
  130. {
  131. condition: pwa,
  132. plugins: () =>
  133. VitePWA({
  134. devOptions: {
  135. enabled: true,
  136. type: 'module',
  137. },
  138. injectRegister: false,
  139. workbox: {
  140. globPatterns: [],
  141. },
  142. ...pwaOptions,
  143. manifest: {
  144. display: 'standalone',
  145. start_url: '/',
  146. theme_color: '#ffffff',
  147. ...pwaOptions?.manifest,
  148. },
  149. }),
  150. },
  151. {
  152. condition: isBuild && !!compress,
  153. plugins: () => {
  154. const compressPlugins: PluginOption[] = [];
  155. if (compressTypes?.includes('brotli')) {
  156. compressPlugins.push(
  157. viteCompressPlugin({ deleteOriginFile: false, ext: '.br' }),
  158. );
  159. }
  160. if (compressTypes?.includes('gzip')) {
  161. compressPlugins.push(
  162. viteCompressPlugin({ deleteOriginFile: false, ext: '.gz' }),
  163. );
  164. }
  165. return compressPlugins;
  166. },
  167. },
  168. {
  169. condition: !!html,
  170. plugins: () => [viteHtmlPlugin({ minify: true })],
  171. },
  172. {
  173. condition: isBuild && importmap,
  174. plugins: () => {
  175. return [viteImportMapPlugin(importmapOptions)];
  176. },
  177. },
  178. {
  179. condition: isBuild && extraAppConfig,
  180. plugins: async () => [
  181. await viteExtraAppConfigPlugin({ isBuild: true, root: process.cwd() }),
  182. ],
  183. },
  184. {
  185. condition: !isBuild && !!turboConsole,
  186. plugins: () => [viteTurboConsolePlugin()],
  187. },
  188. ]);
  189. }
  190. /**
  191. * 根据条件获取库类型的vite插件
  192. */
  193. async function getLibraryConditionPlugins(
  194. options: LibraryPluginOptions,
  195. ): Promise<PluginOption[]> {
  196. // 单独取,否则commonOptions拿不到
  197. const isBuild = options.isBuild;
  198. const { dts, injectLibCss, ...commonOptions } = options;
  199. const commonPlugins = await getCommonConditionPlugins(commonOptions);
  200. return await getConditionEstablishedPlugins([
  201. ...commonPlugins,
  202. {
  203. condition: isBuild && !!dts,
  204. plugins: () => [viteDtsPlugin({ logLevel: 'error' })],
  205. },
  206. {
  207. condition: injectLibCss,
  208. plugins: () => [viteLibInjectCss()],
  209. },
  210. ]);
  211. }
  212. export {
  213. getApplicationConditionPlugins,
  214. getLibraryConditionPlugins,
  215. viteCompressPlugin,
  216. viteDtsPlugin,
  217. viteHtmlPlugin,
  218. viteTurboConsolePlugin,
  219. viteVisualizerPlugin,
  220. };