index.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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 { viteMockServe as viteMockPlugin } from 'vite-plugin-mock';
  20. import { VitePWA } from 'vite-plugin-pwa';
  21. import viteVueDevTools from 'vite-plugin-vue-devtools';
  22. import { viteExtraAppConfigPlugin } from './extra-app-config';
  23. import { viteImportMapPlugin } from './importmap';
  24. import { viteInjectAppLoadingPlugin } from './inject-app-loading';
  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, 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: isBuild && !!visualizer,
  68. plugins: () => [<PluginOption>viteVisualizerPlugin({
  69. filename: './node_modules/.cache/visualizer/stats.html',
  70. gzipSize: true,
  71. open: true,
  72. })],
  73. },
  74. ];
  75. }
  76. /**
  77. * 根据条件获取应用类型的vite插件
  78. */
  79. async function getApplicationConditionPlugins(
  80. options: ApplicationPluginOptions,
  81. ): Promise<PluginOption[]> {
  82. // 单独取,否则commonOptions拿不到
  83. const isBuild = options.isBuild;
  84. const env = options.env;
  85. const {
  86. compress,
  87. compressTypes,
  88. extraAppConfig,
  89. html,
  90. i18n,
  91. importmap,
  92. importmapOptions,
  93. injectAppLoading,
  94. license,
  95. mock,
  96. pwa,
  97. pwaOptions,
  98. turboConsole,
  99. ...commonOptions
  100. } = options;
  101. const commonPlugins = await getCommonConditionPlugins(commonOptions);
  102. return await getConditionEstablishedPlugins([
  103. ...commonPlugins,
  104. {
  105. condition: i18n,
  106. plugins: async () => {
  107. const pkg = await getPackage('@vben/locales');
  108. const include = `${join(pkg?.dir ?? '', isBuild ? 'dist' : 'src', 'langs')}/*.yaml`;
  109. return [
  110. viteVueI18nPlugin({
  111. compositionOnly: true,
  112. fullInstall: true,
  113. include,
  114. runtimeOnly: true,
  115. }),
  116. ];
  117. },
  118. },
  119. {
  120. condition: injectAppLoading,
  121. plugins: async () => [await viteInjectAppLoadingPlugin(!!isBuild, env)],
  122. },
  123. {
  124. condition: license,
  125. plugins: async () => [await viteLicensePlugin()],
  126. },
  127. {
  128. condition: pwa,
  129. plugins: () =>
  130. VitePWA({
  131. devOptions: {
  132. enabled: true,
  133. type: 'module',
  134. },
  135. injectRegister: false,
  136. workbox: {
  137. globPatterns: [],
  138. },
  139. ...pwaOptions,
  140. manifest: {
  141. display: 'standalone',
  142. start_url: '/',
  143. theme_color: '#ffffff',
  144. ...pwaOptions?.manifest,
  145. },
  146. }),
  147. },
  148. {
  149. condition: isBuild && !!compress,
  150. plugins: () => {
  151. const compressPlugins: PluginOption[] = [];
  152. if (compressTypes?.includes('brotli')) {
  153. compressPlugins.push(
  154. viteCompressPlugin({ deleteOriginFile: false, ext: '.br' }),
  155. );
  156. }
  157. if (compressTypes?.includes('gzip')) {
  158. compressPlugins.push(
  159. viteCompressPlugin({ deleteOriginFile: false, ext: '.gz' }),
  160. );
  161. }
  162. return compressPlugins;
  163. },
  164. },
  165. {
  166. condition: !!html,
  167. plugins: () => [viteHtmlPlugin({ minify: true })],
  168. },
  169. {
  170. condition: isBuild && importmap,
  171. plugins: () => {
  172. return [viteImportMapPlugin(importmapOptions)];
  173. },
  174. },
  175. {
  176. condition: isBuild && extraAppConfig,
  177. plugins: async () => [
  178. await viteExtraAppConfigPlugin({ isBuild: true, root: process.cwd() }),
  179. ],
  180. },
  181. {
  182. condition: !isBuild && !!turboConsole,
  183. plugins: () => [viteTurboConsolePlugin()],
  184. },
  185. {
  186. condition: !!mock,
  187. plugins: () => [
  188. viteMockPlugin({
  189. enable: true,
  190. ignore: /^_/,
  191. mockPath: 'mock',
  192. }),
  193. ],
  194. },
  195. ]);
  196. }
  197. /**
  198. * 根据条件获取库类型的vite插件
  199. */
  200. async function getLibraryConditionPlugins(
  201. options: LibraryPluginOptions,
  202. ): Promise<PluginOption[]> {
  203. // 单独取,否则commonOptions拿不到
  204. const isBuild = options.isBuild;
  205. const { dts, injectLibCss, ...commonOptions } = options;
  206. const commonPlugins = await getCommonConditionPlugins(commonOptions);
  207. return await getConditionEstablishedPlugins([
  208. ...commonPlugins,
  209. {
  210. condition: isBuild && !!dts,
  211. plugins: () => [viteDtsPlugin({ logLevel: 'error' })],
  212. },
  213. {
  214. condition: injectLibCss,
  215. plugins: () => [viteLibInjectCss()],
  216. },
  217. ]);
  218. }
  219. export {
  220. getApplicationConditionPlugins,
  221. getLibraryConditionPlugins,
  222. viteCompressPlugin,
  223. viteDtsPlugin,
  224. viteHtmlPlugin,
  225. viteMockPlugin,
  226. viteTurboConsolePlugin,
  227. viteVisualizerPlugin,
  228. };