vite.config.mts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { defineConfig, loadEnv } from "vite";
  2. import react from "@vitejs/plugin-react";
  3. import svgrPlugin from "vite-plugin-svgr";
  4. import { ViteEjsPlugin } from "vite-plugin-ejs";
  5. import { VitePWA } from "vite-plugin-pwa";
  6. import checker from "vite-plugin-checker";
  7. import { createHtmlPlugin } from "vite-plugin-html";
  8. import { woff2BrowserPlugin } from "../scripts/woff2/woff2-vite-plugins";
  9. // To load .env.local variables
  10. const envVars = loadEnv("", `../`);
  11. // https://vitejs.dev/config/
  12. export default defineConfig({
  13. server: {
  14. port: Number(envVars.VITE_APP_PORT || 3000),
  15. // open the browser
  16. open: true,
  17. },
  18. // We need to specify the envDir since now there are no
  19. //more located in parallel with the vite.config.ts file but in parent dir
  20. envDir: "../",
  21. build: {
  22. outDir: "build",
  23. rollupOptions: {
  24. output: {
  25. assetFileNames(chunkInfo) {
  26. if (chunkInfo?.name?.endsWith(".woff2")) {
  27. // put on root so we are flexible about the CDN path
  28. return "[name]-[hash][extname]";
  29. }
  30. return "assets/[name]-[hash][extname]";
  31. },
  32. // Creating separate chunk for locales except for en and percentages.json so they
  33. // can be cached at runtime and not merged with
  34. // app precache. en.json and percentages.json are needed for first load
  35. // or fallback hence not clubbing with locales so first load followed by offline mode works fine. This is how CRA used to work too.
  36. manualChunks(id) {
  37. if (
  38. id.includes("packages/excalidraw/locales") &&
  39. id.match(/en.json|percentages.json/) === null
  40. ) {
  41. const index = id.indexOf("locales/");
  42. // Taking the substring after "locales/"
  43. return `locales/${id.substring(index + 8)}`;
  44. }
  45. },
  46. },
  47. },
  48. sourcemap: true,
  49. },
  50. plugins: [
  51. woff2BrowserPlugin(),
  52. react(),
  53. checker({
  54. typescript: true,
  55. eslint:
  56. envVars.VITE_APP_ENABLE_ESLINT === "false"
  57. ? undefined
  58. : { lintCommand: 'eslint "./**/*.{js,ts,tsx}"' },
  59. overlay: {
  60. initialIsOpen: envVars.VITE_APP_COLLAPSE_OVERLAY === "false",
  61. badgeStyle: "margin-bottom: 4rem; margin-left: 1rem",
  62. },
  63. }),
  64. svgrPlugin(),
  65. ViteEjsPlugin(),
  66. VitePWA({
  67. registerType: "autoUpdate",
  68. devOptions: {
  69. /* set this flag to true to enable in Development mode */
  70. enabled: false,
  71. },
  72. workbox: {
  73. // Don't push fonts and locales to app precache
  74. globIgnores: ["fonts.css", "**/locales/**", "service-worker.js"],
  75. runtimeCaching: [
  76. {
  77. urlPattern: new RegExp("/.+.(ttf|woff2|otf)"),
  78. handler: "CacheFirst",
  79. options: {
  80. cacheName: "fonts",
  81. expiration: {
  82. maxEntries: 50,
  83. maxAgeSeconds: 60 * 60 * 24 * 90, // <== 90 days
  84. },
  85. },
  86. },
  87. {
  88. urlPattern: new RegExp("fonts.css"),
  89. handler: "StaleWhileRevalidate",
  90. options: {
  91. cacheName: "fonts",
  92. expiration: {
  93. maxEntries: 50,
  94. },
  95. },
  96. },
  97. {
  98. urlPattern: new RegExp("locales/[^/]+.js"),
  99. handler: "CacheFirst",
  100. options: {
  101. cacheName: "locales",
  102. expiration: {
  103. maxEntries: 50,
  104. maxAgeSeconds: 60 * 60 * 24 * 30, // <== 30 days
  105. },
  106. },
  107. },
  108. ],
  109. },
  110. manifest: {
  111. short_name: "Excalidraw",
  112. name: "Excalidraw",
  113. description:
  114. "Excalidraw is a whiteboard tool that lets you easily sketch diagrams that have a hand-drawn feel to them.",
  115. icons: [
  116. {
  117. src: "android-chrome-192x192.png",
  118. sizes: "192x192",
  119. type: "image/png",
  120. },
  121. {
  122. src: "apple-touch-icon.png",
  123. type: "image/png",
  124. sizes: "180x180",
  125. },
  126. {
  127. src: "favicon-32x32.png",
  128. sizes: "32x32",
  129. type: "image/png",
  130. },
  131. {
  132. src: "favicon-16x16.png",
  133. sizes: "16x16",
  134. type: "image/png",
  135. },
  136. ],
  137. start_url: "/",
  138. display: "standalone",
  139. theme_color: "#121212",
  140. background_color: "#ffffff",
  141. file_handlers: [
  142. {
  143. action: "/",
  144. accept: {
  145. "application/vnd.excalidraw+json": [".excalidraw"],
  146. },
  147. },
  148. ],
  149. share_target: {
  150. action: "/web-share-target",
  151. method: "POST",
  152. enctype: "multipart/form-data",
  153. params: {
  154. files: [
  155. {
  156. name: "file",
  157. accept: [
  158. "application/vnd.excalidraw+json",
  159. "application/json",
  160. ".excalidraw",
  161. ],
  162. },
  163. ],
  164. },
  165. },
  166. screenshots: [
  167. {
  168. src: "/screenshots/virtual-whiteboard.png",
  169. type: "image/png",
  170. sizes: "462x945",
  171. },
  172. {
  173. src: "/screenshots/wireframe.png",
  174. type: "image/png",
  175. sizes: "462x945",
  176. },
  177. {
  178. src: "/screenshots/illustration.png",
  179. type: "image/png",
  180. sizes: "462x945",
  181. },
  182. {
  183. src: "/screenshots/shapes.png",
  184. type: "image/png",
  185. sizes: "462x945",
  186. },
  187. {
  188. src: "/screenshots/collaboration.png",
  189. type: "image/png",
  190. sizes: "462x945",
  191. },
  192. {
  193. src: "/screenshots/export.png",
  194. type: "image/png",
  195. sizes: "462x945",
  196. },
  197. ],
  198. },
  199. }),
  200. createHtmlPlugin({
  201. minify: true,
  202. }),
  203. ],
  204. publicDir: "../public",
  205. });