From e05d2bab75bc6d3462f0a581a46cfe50b1a902ce Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 5 Oct 2024 00:37:08 +0800 Subject: [PATCH] refactor: vite config and re-optimize chunks Signed-off-by: Innei --- apps/renderer/package.json | 3 - apps/renderer/src/pages/(external)/debug.tsx | 33 ---- configs/vite.render.config.ts | 142 +----------------- eslint.config.mjs | 6 +- .../{ => eslint}/eslint-check-i18n-json.js | 0 plugins/{ => eslint}/eslint-no-debug.js | 0 plugins/{ => eslint}/eslint-recursive-sort.js | 0 plugins/vite/custom-asset.ts | 39 +++++ plugins/vite/deps.ts | 33 ++++ plugins/vite/html-inject.ts | 29 ++++ plugins/vite/i18n-hmr.ts | 24 +++ plugins/vite/locales.ts | 64 ++++++++ plugins/vite/short-alias.ts | 57 +++++++ plugins/vite/tw-macro.ts | 54 +++++++ .../vite/utils}/i18n-completeness.ts | 6 +- pnpm-lock.yaml | 33 ---- vite.config.ts | 75 +++++---- 17 files changed, 358 insertions(+), 240 deletions(-) delete mode 100644 apps/renderer/src/pages/(external)/debug.tsx rename plugins/{ => eslint}/eslint-check-i18n-json.js (100%) rename plugins/{ => eslint}/eslint-no-debug.js (100%) rename plugins/{ => eslint}/eslint-recursive-sort.js (100%) create mode 100644 plugins/vite/custom-asset.ts create mode 100644 plugins/vite/deps.ts create mode 100644 plugins/vite/html-inject.ts create mode 100644 plugins/vite/i18n-hmr.ts create mode 100644 plugins/vite/locales.ts create mode 100644 plugins/vite/short-alias.ts create mode 100644 plugins/vite/tw-macro.ts rename {configs => plugins/vite/utils}/i18n-completeness.ts (87%) diff --git a/apps/renderer/package.json b/apps/renderer/package.json index 0854d9b8f1..a96edd51cc 100644 --- a/apps/renderer/package.json +++ b/apps/renderer/package.json @@ -20,7 +20,6 @@ "@lottiefiles/dotlottie-react": "0.9.0", "@microflash/remark-callout-directives": "4.3.1", "@mozilla/readability": "^0.5.0", - "@radix-ui/react-alert-dialog": "1.1.1", "@radix-ui/react-avatar": "1.1.0", "@radix-ui/react-checkbox": "1.1.1", "@radix-ui/react-context-menu": "2.2.1", @@ -39,7 +38,6 @@ "@radix-ui/react-toast": "1.2.1", "@radix-ui/react-tooltip": "1.1.2", "@sentry/react": "8.32.0", - "@sentry/vite-plugin": "2.22.4", "@shikijs/transformers": "1.20.0", "@t3-oss/env-core": "^0.11.1", "@tanstack/query-sync-storage-persister": "5.56.2", @@ -68,7 +66,6 @@ "immer": "10.1.1", "jotai": "2.10.0", "lethargy": "1.0.9", - "linkedom": "^0.18.5", "lodash-es": "4.17.21", "masonic": "4.0.1", "nanoid": "5.0.7", diff --git a/apps/renderer/src/pages/(external)/debug.tsx b/apps/renderer/src/pages/(external)/debug.tsx deleted file mode 100644 index 87853ec894..0000000000 --- a/apps/renderer/src/pages/(external)/debug.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Versions from "../../components/Versions" - -export function Component() { - if (!import.meta.env.DEV) return null - const ipcHandle = (): void => window.electron?.ipcRenderer.send("ping") - - return ( - <> -
Powered by electron-vite
-
- - Build an Electron app with React -  and TypeScript -
-

- Please try pressing F12 to open the devTool -

-
-
- - Documentation - -
-
- - Send IPC - -
-
- - - ) -} diff --git a/configs/vite.render.config.ts b/configs/vite.render.config.ts index 6cac5dba41..0e6567d187 100644 --- a/configs/vite.render.config.ts +++ b/configs/vite.render.config.ts @@ -1,96 +1,19 @@ -import fs, { readFileSync } from "node:fs" -import path, { resolve } from "node:path" +import { readFileSync } from "node:fs" +import { resolve } from "node:path" -import * as babel from "@babel/core" -import generate from "@babel/generator" -import { parse } from "@babel/parser" -import * as t from "@babel/types" import { sentryVitePlugin } from "@sentry/vite-plugin" import react from "@vitejs/plugin-react" -import { set } from "lodash-es" import { prerelease } from "semver" -import type { Plugin, UserConfig } from "vite" +import type { UserConfig } from "vite" +import { customI18nHmrPlugin } from "../plugins/vite/i18n-hmr" +import { localesPlugin } from "../plugins/vite/locales" +import { twMacro } from "../plugins/vite/tw-macro" +import i18nCompleteness from "../plugins/vite/utils/i18n-completeness" import { getGitHash } from "../scripts/lib" -import i18nCompleteness from "./i18n-completeness" const pkg = JSON.parse(readFileSync("package.json", "utf8")) const isCI = process.env.CI === "true" || process.env.CI === "1" -function localesPlugin(): Plugin { - return { - name: "locales-merge", - enforce: "post", - generateBundle(_options, bundle) { - const localesDir = path.resolve(__dirname, "../locales") - const namespaces = fs.readdirSync(localesDir).filter((dir) => dir !== ".DS_Store") - const languageResources = {} - - namespaces.forEach((namespace) => { - const namespacePath = path.join(localesDir, namespace) - const files = fs.readdirSync(namespacePath).filter((file) => file.endsWith(".json")) - - files.forEach((file) => { - const lang = path.basename(file, ".json") - const filePath = path.join(namespacePath, file) - const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) - - if (!languageResources[lang]) { - languageResources[lang] = {} - } - - const obj = {} - - const keys = Object.keys(content as object) - for (const accessorKey of keys) { - set(obj, accessorKey, (content as any)[accessorKey]) - } - - languageResources[lang][namespace] = obj - }) - }) - - Object.entries(languageResources).forEach(([lang, resources]) => { - const fileName = `locales/${lang}.js` - - const content = `export default ${JSON.stringify(resources)};` - - this.emitFile({ - type: "asset", - fileName, - source: content, - }) - }) - - // Remove original JSON chunks - Object.keys(bundle).forEach((key) => { - if (key.startsWith("locales/") && key.endsWith(".json")) { - delete bundle[key] - } - }) - }, - } -} - -function customI18nHmrPlugin(): Plugin { - return { - name: "custom-i18n-hmr", - handleHotUpdate({ file, server }) { - if (file.endsWith(".json") && file.includes("locales")) { - server.ws.send({ - type: "custom", - event: "i18n-update", - data: { - file, - content: readFileSync(file, "utf-8"), - }, - }) - - // return empty array to prevent the default HMR - return [] - } - }, - } -} export const viteRenderBaseConfig = { resolve: { @@ -130,7 +53,7 @@ export const viteRenderBaseConfig = { }), localesPlugin(), - viteTwToRawString(), + twMacro(), customI18nHmrPlugin(), ], define: { @@ -147,52 +70,3 @@ export const viteRenderBaseConfig = { I18N_COMPLETENESS_MAP: JSON.stringify({ ...i18nCompleteness, en: 100 }), }, } satisfies UserConfig - -function viteTwToRawString(): Plugin { - return { - name: "vite-plugin-tw-to-raw-string", - - transform(code, id) { - // Only Process .tsx .ts .jsx .js files - if (!/\.[jt]sx?$/.test(id)) { - return null - } - // Parse the code using Babel's parser with TypeScript support - const ast = parse(code, { - sourceType: "module", - plugins: ["jsx", "typescript"], // Add typescript support - }) - - babel.traverse(ast, { - TaggedTemplateExpression(path) { - if (t.isIdentifier(path.node.tag, { name: "tw" })) { - const { quasi } = path.node - if (t.isTemplateLiteral(quasi)) { - // Create a new template literal by combining quasis and expressions - const quasis = quasi.quasis.map((q) => q.value.raw) - - // Replace the tagged template expression with the new template literal as a string - path.replaceWith( - t.templateLiteral( - quasis.map((q, i) => - t.templateElement({ raw: q, cooked: q }, i === quasis.length - 1), - ), - quasi.expressions, - ), - ) - } - } - }, - }) - - // Generate the transformed code from the modified AST - // @ts-expect-error - const output = generate.default(ast, {}, code) - - return { - code: output.code, - map: null, // Source map generation can be added if necessary - } - }, - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs index 1fa926d369..b09b7d8144 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,9 +1,9 @@ // @ts-check import { defineConfig } from "eslint-config-hyoban" -import checkI18nJson from "./plugins/eslint-check-i18n-json.js" -import noDebug from "./plugins/eslint-no-debug.js" -import recursiveSort from "./plugins/eslint-recursive-sort.js" +import checkI18nJson from "./plugins/eslint/eslint-check-i18n-json.js" +import noDebug from "./plugins/eslint/eslint-no-debug.js" +import recursiveSort from "./plugins/eslint/eslint-recursive-sort.js" export default defineConfig( { diff --git a/plugins/eslint-check-i18n-json.js b/plugins/eslint/eslint-check-i18n-json.js similarity index 100% rename from plugins/eslint-check-i18n-json.js rename to plugins/eslint/eslint-check-i18n-json.js diff --git a/plugins/eslint-no-debug.js b/plugins/eslint/eslint-no-debug.js similarity index 100% rename from plugins/eslint-no-debug.js rename to plugins/eslint/eslint-no-debug.js diff --git a/plugins/eslint-recursive-sort.js b/plugins/eslint/eslint-recursive-sort.js similarity index 100% rename from plugins/eslint-recursive-sort.js rename to plugins/eslint/eslint-recursive-sort.js diff --git a/plugins/vite/custom-asset.ts b/plugins/vite/custom-asset.ts new file mode 100644 index 0000000000..5fa0ccd57d --- /dev/null +++ b/plugins/vite/custom-asset.ts @@ -0,0 +1,39 @@ +import path from "node:path" + +import fs from "fs-extra" +import type { Plugin } from "vite" + +export default function customAssetOutput(options: { + dependencies: Record +}): Plugin { + const { dependencies = {} } = options + + return { + name: "vite-plugin-custom-asset-output", + + async generateBundle(_, bundle) { + for (const [dependencyName, config] of Object.entries(dependencies)) { + const { sourceDir, targetDir } = config + + for (const fileName in bundle) { + const file = bundle[fileName] + + if ( + file.type === "asset" && + file.name && + file.name.startsWith(`${dependencyName}/${sourceDir}`) + ) { + const newFileName = file.name.replace(`${dependencyName}/${sourceDir}`, targetDir) + + file.fileName = newFileName + + await fs.ensureDir(path.dirname(newFileName)) + + bundle[newFileName] = file + delete bundle[fileName] + } + } + } + }, + } +} diff --git a/plugins/vite/deps.ts b/plugins/vite/deps.ts new file mode 100644 index 0000000000..ebf8ee6fdf --- /dev/null +++ b/plugins/vite/deps.ts @@ -0,0 +1,33 @@ +import type { Plugin, UserConfig } from "vite" + +export function createDependencyChunksPlugin(dependencies: string[] | string[][]): Plugin { + return { + name: "dependency-chunks", + config(config: UserConfig) { + config.build = config.build || {} + config.build.rollupOptions = config.build.rollupOptions || {} + config.build.rollupOptions.output = config.build.rollupOptions.output || {} + + const { output } = config.build.rollupOptions + const outputConfig = Array.isArray(output) ? output[0] : output + outputConfig.manualChunks = outputConfig.manualChunks || {} + outputConfig.assetFileNames = "assets/[name].[hash][extname]" + outputConfig.chunkFileNames = (chunkInfo) => { + return chunkInfo.name.startsWith("vendor/") ? "[name].[hash].js" : "assets/[name].[hash].js" + } + + const manualChunks = Array.isArray(output) ? output[0].manualChunks : output.manualChunks + + if (typeof manualChunks !== "object") return + + dependencies.forEach((dep, index) => { + if (Array.isArray(dep)) { + const chunkName = `vendor/a${index}` + manualChunks[chunkName] = dep + } else { + manualChunks[`vendor/${dep}`] = [dep] + } + }) + }, + } +} diff --git a/plugins/vite/html-inject.ts b/plugins/vite/html-inject.ts new file mode 100644 index 0000000000..6a3f338729 --- /dev/null +++ b/plugins/vite/html-inject.ts @@ -0,0 +1,29 @@ +import type { PluginOption } from "vite" + +import type { env as EnvType } from "../../packages/shared/src/env" + +export function htmlInjectPlugin(env: typeof EnvType): PluginOption { + return { + name: "html-transform", + enforce: "post", + transformIndexHtml(html) { + return html.replace( + "", + ``, + ) + }, + } +} diff --git a/plugins/vite/i18n-hmr.ts b/plugins/vite/i18n-hmr.ts new file mode 100644 index 0000000000..c9ce5e5a86 --- /dev/null +++ b/plugins/vite/i18n-hmr.ts @@ -0,0 +1,24 @@ +import { readFileSync } from "node:fs" + +import type { Plugin } from "vite" + +export function customI18nHmrPlugin(): Plugin { + return { + name: "custom-i18n-hmr", + handleHotUpdate({ file, server }) { + if (file.endsWith(".json") && file.includes("locales")) { + server.ws.send({ + type: "custom", + event: "i18n-update", + data: { + file, + content: readFileSync(file, "utf-8"), + }, + }) + + // return empty array to prevent the default HMR + return [] + } + }, + } +} diff --git a/plugins/vite/locales.ts b/plugins/vite/locales.ts new file mode 100644 index 0000000000..45b7b24331 --- /dev/null +++ b/plugins/vite/locales.ts @@ -0,0 +1,64 @@ +import fs from "node:fs" +import path, { dirname } from "node:path" +import { fileURLToPath } from "node:url" + +import { set } from "lodash-es" +import type { Plugin } from "vite" + +export function localesPlugin(): Plugin { + return { + name: "locales-merge", + enforce: "post", + generateBundle(_options, bundle) { + const __dirname = dirname(fileURLToPath(import.meta.url)) + + const localesDir = path.resolve(__dirname, "../../locales") + + const namespaces = fs.readdirSync(localesDir).filter((dir) => dir !== ".DS_Store") + const languageResources = {} + + namespaces.forEach((namespace) => { + const namespacePath = path.join(localesDir, namespace) + const files = fs.readdirSync(namespacePath).filter((file) => file.endsWith(".json")) + + files.forEach((file) => { + const lang = path.basename(file, ".json") + const filePath = path.join(namespacePath, file) + const content = JSON.parse(fs.readFileSync(filePath, "utf-8")) + + if (!languageResources[lang]) { + languageResources[lang] = {} + } + + const obj = {} + + const keys = Object.keys(content as object) + for (const accessorKey of keys) { + set(obj, accessorKey, (content as any)[accessorKey]) + } + + languageResources[lang][namespace] = obj + }) + }) + + Object.entries(languageResources).forEach(([lang, resources]) => { + const fileName = `locales/${lang}.js` + + const content = `export default ${JSON.stringify(resources)};` + + this.emitFile({ + type: "asset", + fileName, + source: content, + }) + }) + + // Remove original JSON chunks + Object.keys(bundle).forEach((key) => { + if (key.startsWith("locales/") && key.endsWith(".json")) { + delete bundle[key] + } + }) + }, + } +} diff --git a/plugins/vite/short-alias.ts b/plugins/vite/short-alias.ts new file mode 100644 index 0000000000..988219cafa --- /dev/null +++ b/plugins/vite/short-alias.ts @@ -0,0 +1,57 @@ +import type { Plugin } from "vite" + +export function shortAliasPlugin(): Plugin { + const aliasMap = new Map() + let aliasCounter = 0 + + function generateShortAlias(): string { + const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + let result = "_" + let counter = aliasCounter++ + + do { + result += chars[counter % chars.length] + counter = Math.floor(counter / chars.length) + } while (counter > 0) + + return result + } + + return { + name: "short-alias", + renderChunk(code, chunk) { + if (chunk.fileName.startsWith("vendor/")) return code + const importRegex = /import\s*(\{[^}]+\})\s*from\s*(['"])([^'"]+)\2/g + + return code.replaceAll(importRegex, (match, imports, quote, source) => { + // Only process imports with curly braces + if (!imports.startsWith("{") || !imports.endsWith("}")) { + return match + } + + const newImports = imports + .slice(1, -1) // Remove the curly braces + .split(",") + .map((imp) => { + const [original, alias] = imp.trim().split(/\s+as\s+/) + if (alias) { + // If an alias already exists, keep it or shorten it if it's too long + if (alias.length > 3) { + let shortAlias = aliasMap.get(alias) + if (!shortAlias) { + shortAlias = generateShortAlias() + aliasMap.set(alias, shortAlias) + } + return `${original} as ${shortAlias}` + } + return imp.trim() + } + return imp.trim() + }) + .join(", ") + + return `import {${newImports}} from ${quote}${source}${quote}` + }) + }, + } +} diff --git a/plugins/vite/tw-macro.ts b/plugins/vite/tw-macro.ts new file mode 100644 index 0000000000..5207e09818 --- /dev/null +++ b/plugins/vite/tw-macro.ts @@ -0,0 +1,54 @@ +import * as babel from "@babel/core" +import generate from "@babel/generator" +import { parse } from "@babel/parser" +import * as t from "@babel/types" +import type { Plugin } from "vite" + +export function twMacro(): Plugin { + return { + name: "vite-plugin-tw-to-raw-string", + + transform(code, id) { + // Only Process .tsx .ts .jsx .js files + if (!/\.[jt]sx?$/.test(id)) { + return null + } + // Parse the code using Babel's parser with TypeScript support + const ast = parse(code, { + sourceType: "module", + plugins: ["jsx", "typescript"], // Add typescript support + }) + + babel.traverse(ast, { + TaggedTemplateExpression(path) { + if (t.isIdentifier(path.node.tag, { name: "tw" })) { + const { quasi } = path.node + if (t.isTemplateLiteral(quasi)) { + // Create a new template literal by combining quasis and expressions + const quasis = quasi.quasis.map((q) => q.value.raw) + + // Replace the tagged template expression with the new template literal as a string + path.replaceWith( + t.templateLiteral( + quasis.map((q, i) => + t.templateElement({ raw: q, cooked: q }, i === quasis.length - 1), + ), + quasi.expressions, + ), + ) + } + } + }, + }) + + // Generate the transformed code from the modified AST + // @ts-expect-error + const output = generate.default(ast, {}, code) + + return { + code: output.code, + map: null, // Source map generation can be added if necessary + } + }, + } +} diff --git a/configs/i18n-completeness.ts b/plugins/vite/utils/i18n-completeness.ts similarity index 87% rename from configs/i18n-completeness.ts rename to plugins/vite/utils/i18n-completeness.ts index 3de328b319..479e7790a5 100644 --- a/configs/i18n-completeness.ts +++ b/plugins/vite/utils/i18n-completeness.ts @@ -1,5 +1,6 @@ import fs from "node:fs" -import path from "node:path" +import path, { dirname } from "node:path" +import { fileURLToPath } from "node:url" type LanguageCompletion = Record @@ -55,6 +56,7 @@ function calculateCompleteness(localesDir: string): LanguageCompletion { return completeness } +const __dirname = dirname(fileURLToPath(import.meta.url)) -const i18n = calculateCompleteness(path.resolve(__dirname, "../locales")) +const i18n = calculateCompleteness(path.resolve(__dirname, "../../../locales")) export default i18n diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bf0241123..dd479186d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -351,9 +351,6 @@ importers: '@mozilla/readability': specifier: ^0.5.0 version: 0.5.0(patch_hash=fgkvsbckled47trggkhdkimzbm) - '@radix-ui/react-alert-dialog': - specifier: 1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': specifier: 1.1.0 version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -408,9 +405,6 @@ importers: '@sentry/react': specifier: 8.32.0 version: 8.32.0(react@18.3.1) - '@sentry/vite-plugin': - specifier: 2.22.4 - version: 2.22.4(encoding@0.1.13) '@shikijs/transformers': specifier: 1.20.0 version: 1.20.0 @@ -2398,19 +2392,6 @@ packages: '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} - '@radix-ui/react-alert-dialog@1.1.1': - resolution: {integrity: sha512-wmCoJwj7byuVuiLKqDLlX7ClSUU0vd9sdCeM+2Ls+uf13+cpSJoMgwysHq1SGVVkJj5Xn0XWi1NoRCdkMpr6Mw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-arrow@1.1.0': resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==} peerDependencies: @@ -11099,20 +11080,6 @@ snapshots: '@radix-ui/primitive@1.1.0': {} - '@radix-ui/react-alert-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.10)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.10)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.10)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.10 - '@types/react-dom': 18.3.0 - '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) diff --git a/vite.config.ts b/vite.config.ts index 559d8fe526..e4481e761c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,38 +9,14 @@ import { analyzer } from "vite-bundle-analyzer" import mkcert from "vite-plugin-mkcert" import { viteRenderBaseConfig } from "./configs/vite.render.config" -import type { env as EnvType } from "./src/env" +import type { env as EnvType } from "./packages/shared/src/env" +import { createDependencyChunksPlugin } from "./plugins/vite/deps" +import { htmlInjectPlugin } from "./plugins/vite/html-inject" const __dirname = fileURLToPath(new URL(".", import.meta.url)) const isCI = process.env.CI === "true" || process.env.CI === "1" const ROOT = "./apps/renderer" -function htmlPlugin(env: typeof EnvType): PluginOption { - return { - name: "html-transform", - enforce: "post", - transformIndexHtml(html) { - return html.replace( - "", - ``, - ) - }, - } -} - const devPrint = (): PluginOption => ({ name: "dev-print", configureServer(server: ViteDevServer) { @@ -78,10 +54,6 @@ export default ({ mode }) => { main: resolve(ROOT, "/index.html"), __debug_proxy: resolve(ROOT, "/__debug_proxy.html"), }, - output: { - // 10KB - experimentalMinChunkSize: 10_000, - }, }, }, server: { @@ -99,12 +71,51 @@ export default ({ mode }) => { modernTargets: ">0.3%, last 2 versions, Firefox ESR, not dead", modernPolyfills: ["es.array.find-last-index", "es.array.find-last"], }), - htmlPlugin(typedEnv), + htmlInjectPlugin(typedEnv), mkcert(), devPrint(), + createDependencyChunksPlugin([ + ["react", "react-dom"], + ["zustand", "jotai", "use-context-selector", "immer", "dexie"], + [ + "remark-directive", + "remark-gfm", + "remark-parse", + "remark-stringify", + "remark-rehype", + "@microflash/remark-callout-directives", + "remark-gh-alerts", + ], + [ + "rehype-parse", + "rehype-sanitize", + "rehype-stringify", + "rehype-infer-description-meta", + "hast-util-to-jsx-runtime", + "hast-util-to-text", + ], + ["vfile", "unified"], + ["lodash-es"], + ["framer-motion"], + ["clsx", "tailwind-merge", "class-variance-authority"], + ["@radix-ui/react-dialog", "re-resizable"], + ["i18next", "i18next-browser-languagedetector", "react-i18next"], + [ + "@tanstack/react-query", + "@tanstack/react-query-persist-client", + "@tanstack/query-sync-storage-persister", + ], + ["blurhash", "react-blurhash"], + ["tldts"], + ["shiki", "@shikijs/transformers"], + ["@sentry/react", "posthog-js"], + ["zod", "react-hook-form", "@hookform/resolvers"], + ]), + // shortAliasPlugin(), process.env.ANALYZER && analyzer(), ], + define: { ...viteRenderBaseConfig.define, ELECTRON: "false",