Use vite to replace webpack
2
.gitignore
vendored
|
@ -7,5 +7,5 @@ test/e2e/reports
|
|||
selenium-debug.log
|
||||
.idea/
|
||||
config/local.json
|
||||
static/emoji.json
|
||||
src/assets/emoji.json
|
||||
logs/
|
||||
|
|
24
build/service_worker_messages.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { languages, langCodeToJsonName } from '../src/i18n/languages.js'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
export const generateServiceWorkerMessages = async () => {
|
||||
const i18nDir = resolve(
|
||||
dirname(dirname(fileURLToPath(import.meta.url))),
|
||||
'src/i18n'
|
||||
)
|
||||
const msgArray = await Promise.all(languages.map(async lang => {
|
||||
const name = langCodeToJsonName(lang)
|
||||
const file = resolve(i18nDir, name + '.json')
|
||||
const fileContent = await readFile(file, 'utf-8')
|
||||
const msg = {
|
||||
notifications: JSON.parse(fileContent).notifications || {}
|
||||
}
|
||||
return [lang, msg]
|
||||
}))
|
||||
return msgArray.reduce((acc, [lang, msg]) => {
|
||||
acc[lang] = msg
|
||||
return acc
|
||||
}, {})
|
||||
}
|
128
build/sw_plugin.js
Normal file
|
@ -0,0 +1,128 @@
|
|||
import { fileURLToPath } from 'node:url'
|
||||
import { dirname } from 'node:path'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { build } from 'vite'
|
||||
import { generateServiceWorkerMessages } from './service_worker_messages.js'
|
||||
|
||||
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)))
|
||||
|
||||
export const devSwPlugin = ({
|
||||
swSrc,
|
||||
swDest,
|
||||
}) => {
|
||||
return {
|
||||
name: 'dev-sw-plugin',
|
||||
apply: 'serve',
|
||||
resolveId (id) {
|
||||
const name = id.startsWith('/') ? id.slice(1) : id
|
||||
if (name === swDest) {
|
||||
return swSrc
|
||||
}
|
||||
return null
|
||||
},
|
||||
async load (id) {
|
||||
if (id === swSrc) {
|
||||
return readFile(swSrc, 'utf-8')
|
||||
}
|
||||
return null
|
||||
},
|
||||
/**
|
||||
* vite does not bundle the service worker
|
||||
* during dev, and firefox does not support ESM as service worker
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1360870
|
||||
*/
|
||||
// async transform (code, id) {
|
||||
// if (id === swSrc) {
|
||||
// console.log('load virtual')
|
||||
// const res = await build({
|
||||
// entryPoints: [swSrc],
|
||||
// bundle: true,
|
||||
// write: false,
|
||||
// outfile: 'sw-pleroma.js',
|
||||
// alias: {
|
||||
// 'src': projectRoot + '/src',
|
||||
// },
|
||||
// define: {
|
||||
// 'import.meta.glob': 'require'
|
||||
// }
|
||||
// })
|
||||
// console.log('res', res)
|
||||
// const text = res.outputFiles[0].text
|
||||
// console.log('text', text)
|
||||
// return text
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Idea taken from
|
||||
// https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/plugins/build.ts
|
||||
// rollup does not support compiling to iife if we want to code-split;
|
||||
// however, we must compile the service worker to iife because of browser support.
|
||||
// Run another vite build just for the service worker targeting iife at
|
||||
// the end of the build.
|
||||
export const buildSwPlugin = ({
|
||||
swSrc,
|
||||
swDest,
|
||||
}) => {
|
||||
let config
|
||||
return {
|
||||
name: 'build-sw-plugin',
|
||||
enforce: 'post',
|
||||
apply: 'build',
|
||||
configResolved (resolvedConfig) {
|
||||
config = {
|
||||
define: resolvedConfig.define,
|
||||
resolve: resolvedConfig.resolve,
|
||||
plugins: [swMessagesPlugin()],
|
||||
publicDir: false,
|
||||
build: {
|
||||
...resolvedConfig.build,
|
||||
lib: {
|
||||
entry: swSrc,
|
||||
formats: ['iife'],
|
||||
name: 'sw_pleroma'
|
||||
},
|
||||
emptyOutDir: false,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: swDest
|
||||
}
|
||||
}
|
||||
},
|
||||
configFile: false
|
||||
}
|
||||
},
|
||||
closeBundle: {
|
||||
order: 'post',
|
||||
sequential: true,
|
||||
async handler () {
|
||||
console.log('Building service worker for production')
|
||||
await build(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const swMessagesName = 'virtual:pleroma-fe/service_worker_messages'
|
||||
const swMessagesNameResolved = '\0' + swMessagesName
|
||||
|
||||
export const swMessagesPlugin = () => {
|
||||
return {
|
||||
name: 'sw-messages-plugin',
|
||||
resolveId (id) {
|
||||
if (id === swMessagesName) {
|
||||
return swMessagesNameResolved
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
async load (id) {
|
||||
if (id === swMessagesNameResolved) {
|
||||
const messages = await generateServiceWorkerMessages()
|
||||
return `export default ${JSON.stringify(messages, undefined, 2)}`
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,23 @@
|
|||
|
||||
module.exports = {
|
||||
updateEmoji () {
|
||||
const emojis = require('@kazvmoe-infra/unicode-emoji-json/data-by-group')
|
||||
const fs = require('fs')
|
||||
import emojis from '@kazvmoe-infra/unicode-emoji-json/data-by-group.json' with { type: 'json' }
|
||||
import fs from 'fs'
|
||||
|
||||
Object.keys(emojis)
|
||||
.map(k => {
|
||||
emojis[k].map(e => {
|
||||
delete e.unicode_version
|
||||
delete e.emoji_version
|
||||
delete e.skin_tone_support_unicode_version
|
||||
})
|
||||
})
|
||||
Object.keys(emojis)
|
||||
.map(k => {
|
||||
emojis[k].map(e => {
|
||||
delete e.unicode_version
|
||||
delete e.emoji_version
|
||||
delete e.skin_tone_support_unicode_version
|
||||
})
|
||||
})
|
||||
|
||||
const res = {}
|
||||
Object.keys(emojis)
|
||||
.map(k => {
|
||||
const groupId = k.replace('&', 'and').replace(/ /g, '-').toLowerCase()
|
||||
res[groupId] = emojis[k]
|
||||
})
|
||||
const res = {}
|
||||
Object.keys(emojis)
|
||||
.map(k => {
|
||||
const groupId = k.replace('&', 'and').replace(/ /g, '-').toLowerCase()
|
||||
res[groupId] = emojis[k]
|
||||
})
|
||||
|
||||
console.info('Updating emojis...')
|
||||
fs.writeFileSync('static/emoji.json', JSON.stringify(res))
|
||||
console.info('Done.')
|
||||
}
|
||||
}
|
||||
console.info('Updating emojis...')
|
||||
fs.writeFileSync('src/assets/emoji.json', JSON.stringify(res))
|
||||
console.info('Done.')
|
||||
|
|
|
@ -167,6 +167,7 @@
|
|||
<div id="app" class="hidden"></div>
|
||||
<div id="modal"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
<div id="popovers" />
|
||||
<div id="popovers"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
10
package.json
|
@ -5,8 +5,8 @@
|
|||
"author": "Pleroma contributors <https://git.pleroma.social/pleroma/pleroma-fe/-/blob/develop/CONTRIBUTORS.md>",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "node build/dev-server.js",
|
||||
"build": "node build/build.js",
|
||||
"dev": "node build/update-emoji.js && vite dev",
|
||||
"build": "node build/update-emoji.js && vite build",
|
||||
"unit": "karma start test/unit/karma.conf.js --single-run",
|
||||
"unit:watch": "karma start test/unit/karma.conf.js --single-run=false",
|
||||
"e2e": "node test/e2e/runner.js",
|
||||
|
@ -27,6 +27,7 @@
|
|||
"@ruffle-rs/ruffle": "0.1.0-nightly.2025.1.13",
|
||||
"@vuelidate/core": "2.0.3",
|
||||
"@vuelidate/validators": "2.0.4",
|
||||
"@web3-storage/parse-link-header": "^3.1.0",
|
||||
"body-scroll-lock": "3.1.5",
|
||||
"chromatism": "3.0.0",
|
||||
"click-outside-vue3": "4.0.1",
|
||||
|
@ -58,6 +59,8 @@
|
|||
"@babel/register": "7.25.9",
|
||||
"@intlify/vue-i18n-loader": "5.0.1",
|
||||
"@ungap/event-target": "0.2.4",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vue/babel-helper-vue-jsx-merge-props": "1.4.0",
|
||||
"@vue/babel-plugin-jsx": "1.2.5",
|
||||
"@vue/compiler-sfc": "3.5.13",
|
||||
|
@ -123,6 +126,8 @@
|
|||
"stylelint-config-standard": "29.0.0",
|
||||
"stylelint-rscss": "0.4.0",
|
||||
"stylelint-webpack-plugin": "^3.3.0",
|
||||
"vite": "^6.1.0",
|
||||
"vite-plugin-pwa": "^0.21.1",
|
||||
"vue-loader": "17.4.2",
|
||||
"vue-style-loader": "4.1.3",
|
||||
"webpack": "5.97.1",
|
||||
|
@ -130,6 +135,7 @@
|
|||
"webpack-hot-middleware": "2.26.1",
|
||||
"webpack-merge": "0.20.0"
|
||||
},
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">= 16.0.0"
|
||||
},
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
module.exports = {
|
||||
import autoprefixer from 'autoprefixer'
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
autoprefixer
|
||||
]
|
||||
}
|
||||
|
|
0
static/.gitignore → public/static/.gitignore
vendored
0
public/static/.gitkeep
Normal file
Before Width: | Height: | Size: 628 KiB After Width: | Height: | Size: 628 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 396 KiB After Width: | Height: | Size: 396 KiB |
Before Width: | Height: | Size: 521 KiB After Width: | Height: | Size: 521 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
@ -1 +0,0 @@
|
|||
../../static/pleromatan_apology.png
|
|
@ -1 +0,0 @@
|
|||
../../static/pleromatan_apology_fox.png
|
|
@ -3,7 +3,8 @@ import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_con
|
|||
import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
|
||||
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
||||
import StillImage from 'src/components/still-image/still-image.vue'
|
||||
import MentionsLine, { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.vue'
|
||||
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
||||
import { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.js'
|
||||
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
|
||||
|
||||
import './rich_content.scss'
|
||||
|
|
|
@ -2,7 +2,8 @@ import BooleanSetting from '../helpers/boolean_setting.vue'
|
|||
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||
import FloatSetting from '../helpers/float_setting.vue'
|
||||
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
|
||||
import UnitSetting from '../helpers/unit_setting.vue'
|
||||
import { defaultHorizontalUnits } from '../helpers/unit_setting.js'
|
||||
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
|
||||
import Preview from './theme_tab/theme_preview.vue'
|
||||
import FontControl from 'src/components/font_control/font_control.vue'
|
||||
|
|
|
@ -221,12 +221,15 @@ export default {
|
|||
|
||||
// ## Components stuff
|
||||
// Getting existing components
|
||||
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
|
||||
const componentKeysAll = componentsContext.keys()
|
||||
const componentsContext = import.meta.glob(
|
||||
['/src/**/*.style.js', '/src/**/*.style.json'],
|
||||
{ eager: true }
|
||||
)
|
||||
const componentKeysAll = Object.keys(componentsContext)
|
||||
const componentsMap = new Map(
|
||||
componentKeysAll
|
||||
.map(
|
||||
key => [key, componentsContext(key).default]
|
||||
key => [key, componentsContext[key].default]
|
||||
).filter(([, component]) => !component.virtual && !component.notEditable)
|
||||
)
|
||||
exports.componentsMap = componentsMap
|
||||
|
|
|
@ -22,4 +22,4 @@
|
|||
</template>
|
||||
|
||||
<script src="./status_bookmark_folder_menu.js"></script>
|
||||
<stlye src="./status_bookmark_folder_menu.scss" />
|
||||
<style src="./status_bookmark_folder_menu.scss" />
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Popover from '../popover/popover.vue'
|
||||
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
||||
import { mapState } from 'vuex'
|
||||
import { ListsMenuContent } from '../lists_menu/lists_menu_content.vue'
|
||||
import { BookmarkFoldersMenuContent } from '../bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
||||
import ListsMenuContent from '../lists_menu/lists_menu_content.vue'
|
||||
import BookmarkFoldersMenuContent from '../bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { TIMELINES } from 'src/components/navigation/navigation.js'
|
||||
import { filterNavigation } from 'src/components/navigation/filter.js'
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Modal from 'src/components/modal/modal.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import pleromaTan from 'src/assets/pleromatan_apology.png'
|
||||
import pleromaTanFox from 'src/assets/pleromatan_apology_fox.png'
|
||||
import pleromaTanMask from 'src/assets/pleromatan_apology_mask.png'
|
||||
import pleromaTanFoxMask from 'src/assets/pleromatan_apology_fox_mask.png'
|
||||
|
||||
|
@ -14,6 +12,9 @@ library.add(
|
|||
|
||||
export const CURRENT_UPDATE_COUNTER = 1
|
||||
|
||||
const pleromaTan = '/static/pleromatan_apology.png'
|
||||
const pleromaTanFox = '/static/pleromatan_apology_fox.png'
|
||||
|
||||
const UpdateNotification = {
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -46,7 +46,7 @@ const ensureFinalFallback = codes => {
|
|||
return codeList.includes('en') ? codeList : codeList.concat(['en'])
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
languages,
|
||||
langCodeToJsonName,
|
||||
langCodeToCldrName,
|
||||
|
|
|
@ -9,23 +9,23 @@
|
|||
|
||||
import { isEqual } from 'lodash'
|
||||
import { languages, langCodeToJsonName } from './languages.js'
|
||||
import enMessages from './en.json'
|
||||
|
||||
const ULTIMATE_FALLBACK_LOCALE = 'en'
|
||||
|
||||
const hasLanguageFile = (code) => languages.includes(code)
|
||||
|
||||
const languageFileMap = import.meta.glob('./*.json')
|
||||
|
||||
const loadLanguageFile = (code) => {
|
||||
return import(
|
||||
/* webpackInclude: /\.json$/ */
|
||||
/* webpackChunkName: "i18n/[request]" */
|
||||
`./${langCodeToJsonName(code)}.json`
|
||||
)
|
||||
const jsonName = langCodeToJsonName(code)
|
||||
return languageFileMap[`./${jsonName}.json`]()
|
||||
}
|
||||
|
||||
const messages = {
|
||||
languages,
|
||||
default: {
|
||||
en: require('./en.json').default
|
||||
en: enMessages
|
||||
},
|
||||
setLanguage: async (i18n, language) => {
|
||||
const languages = (Array.isArray(language) ? language : [language]).filter(k => k)
|
||||
|
|
|
@ -179,9 +179,9 @@ const defaultState = {
|
|||
}
|
||||
|
||||
const loadAnnotations = (lang) => {
|
||||
const code = langCodeToCldrName(lang)
|
||||
return import(
|
||||
/* webpackChunkName: "emoji-annotations/[request]" */
|
||||
`@kazvmoe-infra/unicode-emoji-json/annotations/${langCodeToCldrName(lang)}.json`
|
||||
`../../node_modules/@kazvmoe-infra/unicode-emoji-json/annotations/${code}.json`
|
||||
)
|
||||
.then(k => k.default)
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ const instance = {
|
|||
},
|
||||
async getStaticEmoji ({ commit }) {
|
||||
try {
|
||||
const values = (await import(/* webpackChunkName: 'emoji' */ '../../static/emoji.json')).default
|
||||
const values = (await import('/src/assets/emoji.json')).default
|
||||
|
||||
const emoji = Object.keys(values).reduce((res, groupId) => {
|
||||
res[groupId] = values[groupId].map(e => ({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import escape from 'escape-html'
|
||||
import parseLinkHeader from 'parse-link-header'
|
||||
import { parseLinkHeader } from '@web3-storage/parse-link-header'
|
||||
import { isStatusNotification } from '../notification_utils/notification_utils.js'
|
||||
import punycode from 'punycode.js'
|
||||
|
||||
|
@ -484,8 +484,8 @@ export const parseLinkHeaderPagination = (linkHeader, opts = {}) => {
|
|||
const flakeId = opts.flakeId
|
||||
const parsedLinkHeader = parseLinkHeader(linkHeader)
|
||||
if (!parsedLinkHeader) return
|
||||
const maxId = parsedLinkHeader.next.max_id
|
||||
const minId = parsedLinkHeader.prev.min_id
|
||||
const maxId = parsedLinkHeader.next?.max_id
|
||||
const minId = parsedLinkHeader.prev?.min_id
|
||||
|
||||
return {
|
||||
maxId: flakeId ? maxId : parseInt(maxId, 10),
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import runtime from 'serviceworker-webpack5-plugin/lib/runtime'
|
||||
|
||||
function urlBase64ToUint8Array (base64String) {
|
||||
const padding = '='.repeat((4 - base64String.length % 4) % 4)
|
||||
const base64 = (base64String + padding)
|
||||
|
@ -19,7 +17,8 @@ function isPushSupported () {
|
|||
}
|
||||
|
||||
function getOrCreateServiceWorker () {
|
||||
return runtime.register()
|
||||
const swType = process.env.HAS_MODULE_SERVICE_WORKER ? 'module' : 'classic'
|
||||
return navigator.serviceWorker.register('/sw-pleroma.js', { type: swType })
|
||||
.catch((err) => console.error('Unable to get or create a service worker.', err))
|
||||
}
|
||||
|
||||
|
@ -98,14 +97,14 @@ export async function initServiceWorker (store) {
|
|||
|
||||
export async function showDesktopNotification (content) {
|
||||
if (!isSWSupported) return
|
||||
const { active: sw } = await window.navigator.serviceWorker.getRegistration()
|
||||
const { active: sw } = (await window.navigator.serviceWorker.getRegistration()) || {}
|
||||
if (!sw) return console.error('No serviceworker found!')
|
||||
sw.postMessage({ type: 'desktopNotification', content })
|
||||
}
|
||||
|
||||
export async function closeDesktopNotification ({ id }) {
|
||||
if (!isSWSupported) return
|
||||
const { active: sw } = await window.navigator.serviceWorker.getRegistration()
|
||||
const { active: sw } = (await window.navigator.serviceWorker.getRegistration()) || {}
|
||||
if (!sw) return console.error('No serviceworker found!')
|
||||
if (id >= 0) {
|
||||
sw.postMessage({ type: 'desktopNotificationClose', content: { id } })
|
||||
|
@ -116,7 +115,7 @@ export async function closeDesktopNotification ({ id }) {
|
|||
|
||||
export async function updateFocus () {
|
||||
if (!isSWSupported) return
|
||||
const { active: sw } = await window.navigator.serviceWorker.getRegistration()
|
||||
const { active: sw } = (await window.navigator.serviceWorker.getRegistration()) || {}
|
||||
if (!sw) return console.error('No serviceworker found!')
|
||||
sw.postMessage({ type: 'updateFocus' })
|
||||
}
|
||||
|
|
|
@ -146,9 +146,12 @@ const getTextColorAlpha = (directives, intendedTextColor, dynamicVars, staticVar
|
|||
}
|
||||
|
||||
// Loading all style.js[on] files dynamically
|
||||
const componentsContext = require.context('src', true, /\.style.js(on)?$/)
|
||||
componentsContext.keys().forEach(key => {
|
||||
const component = componentsContext(key).default
|
||||
const componentsContext = import.meta.glob(
|
||||
['/src/**/*.style.js', '/src/**/*.style.json'],
|
||||
{ eager: true }
|
||||
)
|
||||
Object.keys(componentsContext).forEach(key => {
|
||||
const component = componentsContext[key].default
|
||||
if (components[component.name] != null) {
|
||||
console.warn(`Component in file ${key} is trying to override existing component ${component.name}! You have collisions/duplicates!`)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { storage } from 'src/lib/storage.js'
|
|||
import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js'
|
||||
import { prepareNotificationObject } from './services/notification_utils/notification_utils.js'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import messages from './i18n/service_worker_messages.js'
|
||||
import messages from 'virtual:pleroma-fe/service_worker_messages'
|
||||
|
||||
const i18n = createI18n({
|
||||
// By default, use the browser locale, we will update it if neccessary
|
||||
|
@ -139,3 +139,5 @@ self.addEventListener('notificationclick', (event) => {
|
|||
if (clients.openWindow) return clients.openWindow('/')
|
||||
}))
|
||||
})
|
||||
|
||||
console.log('sw here')
|
||||
|
|
135
vite.config.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
import { fileURLToPath } from 'node:url'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { devSwPlugin, buildSwPlugin, swMessagesPlugin } from './build/sw_plugin.js'
|
||||
|
||||
const getLocalDevSettings = async () => {
|
||||
try {
|
||||
const settings = (await import('./config/local.json')).default
|
||||
if (settings.target && settings.target.endsWith('/')) {
|
||||
// replacing trailing slash since it can conflict with some apis
|
||||
// and that's how actual BE reports its url
|
||||
settings.target = settings.target.replace(/\/$/, '')
|
||||
}
|
||||
console.info('Using local dev server settings (/config/local.json):')
|
||||
console.info(JSON.stringify(settings, null, 2))
|
||||
return settings
|
||||
} catch (e) {
|
||||
console.info('Local dev server settings not found (/config/local.json)', e)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const projectRoot = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
export default defineConfig(async ({ command }) => {
|
||||
const settings = await getLocalDevSettings()
|
||||
const target = settings.target || 'http://localhost:4000/'
|
||||
const proxy = {
|
||||
'/api': {
|
||||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost',
|
||||
ws: true
|
||||
},
|
||||
'/nodeinfo': {
|
||||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost'
|
||||
},
|
||||
'/socket': {
|
||||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost',
|
||||
ws: true,
|
||||
headers: {
|
||||
'Origin': target
|
||||
}
|
||||
},
|
||||
'/oauth': {
|
||||
target,
|
||||
changeOrigin: true,
|
||||
cookieDomainRewrite: 'localhost'
|
||||
}
|
||||
}
|
||||
|
||||
const swSrc = 'src/sw.js'
|
||||
const swDest = 'sw-pleroma.js'
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
compilerOptions: {
|
||||
isCustomElement(tag) {
|
||||
if (tag === 'pinch-zoom') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
vueJsx(),
|
||||
devSwPlugin({ swSrc, swDest }),
|
||||
buildSwPlugin({ swSrc, swDest }),
|
||||
swMessagesPlugin()
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
src: '/src',
|
||||
components: '/src/components'
|
||||
}
|
||||
},
|
||||
define: {
|
||||
'process.env': JSON.stringify({
|
||||
NODE_ENV: command === 'serve' ? 'development' : 'production',
|
||||
HAS_MODULE_SERVICE_WORKER: command === 'serve'
|
||||
}),
|
||||
'COMMIT_HASH': JSON.stringify('DEV'),
|
||||
'DEV_OVERRIDES': JSON.stringify({})
|
||||
},
|
||||
build: {
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: 'index.html'
|
||||
},
|
||||
output: {
|
||||
inlineDynamicImports: false,
|
||||
entryFileNames (chunkInfo) {
|
||||
const id = chunkInfo.facadeModuleId
|
||||
if (id.endsWith(swSrc)) {
|
||||
return swDest
|
||||
} else {
|
||||
return 'static/js/[name].[hash].js'
|
||||
}
|
||||
},
|
||||
chunkFileNames (chunkInfo) {
|
||||
return 'static/js/[name].[hash].js'
|
||||
},
|
||||
assetFileNames (assetInfo) {
|
||||
const name = assetInfo.names?.[0] || ''
|
||||
if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(name)) {
|
||||
return 'static/img/[name].[hash][extname]'
|
||||
} else if (/\.css$/.test(name)) {
|
||||
return 'static/css/[name].[hash][extname]'
|
||||
} else {
|
||||
return 'static/misc/[name].[hash][extname]'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
server: {
|
||||
proxy,
|
||||
port: Number(process.env.PORT) || 8080
|
||||
},
|
||||
preview: {
|
||||
proxy
|
||||
}
|
||||
}
|
||||
})
|