Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
196 lines
6.0 KiB
JavaScript
196 lines
6.0 KiB
JavaScript
import { defineConfig } from 'vite'
|
|
import vue from '@vitejs/plugin-vue'
|
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
|
import path from 'path'
|
|
import { VitePWA } from 'vite-plugin-pwa'
|
|
|
|
// https://vitejs.dev/config/
|
|
export default defineConfig(async ({ mode }) => {
|
|
const isDev = mode === 'development'
|
|
const config = {
|
|
plugins: [
|
|
vue(),
|
|
vueJsx(),
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
workbox: {
|
|
maximumFileSizeToCacheInBytes: 8 * 1024 * 1024,
|
|
},
|
|
devOptions: {
|
|
enabled: true,
|
|
},
|
|
manifest: {
|
|
display: 'standalone',
|
|
name: 'Frappe CRM',
|
|
short_name: 'Frappe CRM',
|
|
start_url: '/crm',
|
|
description:
|
|
'Modern & 100% Open-source CRM tool to supercharge your sales operations',
|
|
icons: [
|
|
{
|
|
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
|
sizes: '192x192',
|
|
type: 'image/png',
|
|
purpose: 'any',
|
|
},
|
|
{
|
|
src: '/assets/crm/manifest/manifest-icon-192.maskable.png',
|
|
sizes: '192x192',
|
|
type: 'image/png',
|
|
purpose: 'maskable',
|
|
},
|
|
{
|
|
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
|
sizes: '512x512',
|
|
type: 'image/png',
|
|
purpose: 'any',
|
|
},
|
|
{
|
|
src: '/assets/crm/manifest/manifest-icon-512.maskable.png',
|
|
sizes: '512x512',
|
|
type: 'image/png',
|
|
purpose: 'maskable',
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(import.meta.dirname, 'src'),
|
|
// point at the package src dir (not index.ts) so subpath imports like
|
|
// `@framework/ui/components/Notifications` resolve. Importing subpaths avoids the
|
|
// barrel, which `export *`s components (Grid/Phone/FormLayout) that need a newer
|
|
// frappe-ui (`frappe-ui/internals`) than this app pins.
|
|
'@framework/ui': path.resolve(
|
|
import.meta.dirname,
|
|
'../../frappe/ui/src',
|
|
),
|
|
},
|
|
// ensure the linked framework package reuses the host app's single copy of each peer.
|
|
// `dompurify` is an implicit dep of @framework/ui's sanitize util (not declared in its
|
|
// package.json); dedupe resolves it to the host's copy since the symlinked source has
|
|
// no node_modules of its own.
|
|
// the editor packages must resolve to one copy each: tiptap imports
|
|
// `@tiptap/pm/model` while prosemirror-state/transform/tables import bare
|
|
// `prosemirror-model`, so a nested install of either throws "multiple
|
|
// versions of prosemirror-model were loaded" on mention insert. Unlike
|
|
// optimizeDeps (dev-only) this also applies to the production build.
|
|
dedupe: [
|
|
'vue',
|
|
'vue-router',
|
|
'frappe-ui',
|
|
'dompurify',
|
|
'@tiptap/core',
|
|
'@tiptap/pm',
|
|
'@tiptap/vue-3',
|
|
'prosemirror-model',
|
|
'prosemirror-state',
|
|
'prosemirror-view',
|
|
'prosemirror-transform',
|
|
],
|
|
},
|
|
optimizeDeps: {
|
|
include: [
|
|
'feather-icons',
|
|
'tailwind.config.js',
|
|
'prosemirror-state',
|
|
'prosemirror-view',
|
|
'lowlight',
|
|
'interactjs',
|
|
],
|
|
},
|
|
server: {
|
|
fs: {
|
|
// allow the bench `apps/` dir so Vite can serve linked local packages
|
|
// (frappe-ui, @framework/ui) that live in sibling app repos
|
|
allow: [path.resolve(import.meta.dirname, '../..')],
|
|
},
|
|
},
|
|
}
|
|
|
|
const frappeui = await importFrappeUIPlugin(isDev, config)
|
|
config.plugins.unshift(
|
|
frappeui({
|
|
frappeProxy: true,
|
|
lucideIcons: true,
|
|
jinjaBootData: true,
|
|
buildConfig: {
|
|
indexHtmlPath: '../crm/www/crm.html',
|
|
emptyOutDir: true,
|
|
sourcemap: true,
|
|
},
|
|
}),
|
|
)
|
|
|
|
return config
|
|
})
|
|
|
|
async function importFrappeUIPlugin(isDev, config) {
|
|
if (isDev) {
|
|
try {
|
|
// Check if local frappe-ui has the vite plugin file
|
|
const fs = await import('node:fs')
|
|
const localVitePluginPath = path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/vite/index.js',
|
|
)
|
|
|
|
if (fs.existsSync(localVitePluginPath)) {
|
|
const module = await import('../frappe-ui/vite/index.js')
|
|
console.info('Local frappe-ui vite plugin found, using local plugin')
|
|
config.resolve.alias = getAliases(config)
|
|
return module.default
|
|
} else {
|
|
console.warn('Local frappe-ui vite plugin not found, using npm package')
|
|
}
|
|
} catch (error) {
|
|
console.warn(
|
|
'Local frappe-ui not found, falling back to npm package:',
|
|
error.message,
|
|
)
|
|
}
|
|
}
|
|
// Fall back to npm package if local import fails
|
|
const module = await import('frappe-ui/vite')
|
|
return module.default
|
|
}
|
|
|
|
function getAliases(config) {
|
|
return {
|
|
...config.resolve.alias,
|
|
'frappe-ui/tailwind': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/tailwind/preset.js',
|
|
),
|
|
'frappe-ui/style.css': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/src/style.css',
|
|
),
|
|
'frappe-ui/frappe': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/frappe/index.js',
|
|
),
|
|
// subpath entries must precede the bare `frappe-ui` key: a plain string alias
|
|
// matches by prefix, so without these subpaths would rewrite under
|
|
// `.../src/index.ts`. `internals` is pulled in by @framework/ui.
|
|
'frappe-ui/icons': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/icons/index.ts',
|
|
),
|
|
'frappe-ui/editor': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/src/molecules/editor/index.ts',
|
|
),
|
|
'frappe-ui/editor-style.css': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/src/molecules/editor/style.css',
|
|
),
|
|
'frappe-ui/internals': path.resolve(
|
|
import.meta.dirname,
|
|
'../frappe-ui/internals.ts',
|
|
),
|
|
'frappe-ui': path.resolve(import.meta.dirname, '../frappe-ui/src/index.ts'),
|
|
}
|
|
}
|