import { defineConfig, HtmlTagDescriptor } from 'vite';
import path from 'path';
import fs from 'fs';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import federation from '@originjs/vite-plugin-federation';
import reactBabel from '@vitejs/plugin-react';
const STATIC_CDN = 'https://landingbuilder-cdn.tekoapis.com';
const injectHtmlsServe: HtmlTagDescriptor[] = [
{ tag: 'script', attrs: { src: '/env.js' }, injectTo: 'body' },
{ tag: 'script', attrs: { src: '/host-mapping.js' }, injectTo: 'body' },
{
tag: 'link',
attrs: { rel: 'icon', href: '/favicon.png' },
injectTo: 'head-prepend',
},
];
const injectHtmlsBuild: HtmlTagDescriptor[] = [
...injectHtmlsServe,
{ tag: 'script', attrs: { src: '/configs/env-local.js' }, injectTo: 'body' },
{
tag: 'script',
attrs: { src: '/configs/host-mapping.js' },
injectTo: 'body',
},
{
tag: 'script',
attrs: { src: '/configs/ga.js', async: true },
injectTo: 'body',
},
{
tag: 'script',
attrs: { src: '/configs/facebook.js', async: true },
injectTo: 'body',
},
{
tag: 'script',
attrs: { src: '/configs/tracking-seo.js', async: true },
injectTo: 'body',
},
];
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
// DEV - alias for package in workspace package packages/
const mappingDevMonorepoLibs = {
'@tempi/3rd-components': 'packages/3rd-components/src',
};
const sharedList =
mode === 'production'
? [
'@tempi/core-editor',
'@tempi/core-elements',
'@tempi/core-renderer',
'@tempi/editor-site',
'react',
'react-dom',
'@emotion/styled',
]
: ['react', 'react-dom'];
const dirInSrc = fs
.readdirSync('src', { withFileTypes: true })
.filter((dir) => dir.isDirectory())
.map((dir) => dir.name);
const alias = dirInSrc.map((el) => {
return {
find: new RegExp(`^${el}(.*)`),
replacement: path.join(path.resolve(__dirname, `src/${el}`), '$1'),
};
});
return {
server: {
port: 3000,
},
preview: {
port: 3000,
},
build: {
assetsDir: 'static',
outDir: 'build',
target: 'esnext',
},
base: mode === 'production' ? `${STATIC_CDN}/editor/` : '/',
optimizeDeps: {
include: ['react/jsx-runtime', 'react-dom', 'react', '@emotion/react'],
},
plugins: [
// append link, script when serve (dev)
{
name: 'serve-html',
apply: 'serve',
transformIndexHtml: (html) => {
return {
html,
tags: injectHtmlsServe,
};
},
},
// append link, script when build
{
name: 'build-html',
apply: 'build',
transformIndexHtml: (html) => {
return {
html,
tags: injectHtmlsBuild,
};
},
},
nodePolyfills({
exclude: ['constants'],
globals: {
global: true,
process: true,
},
}),
federation({
name: 'host-app',
remotes: {
dummy: 'dummy.js',
customElement: {
external: `Promise.resolve(new URLSearchParams(window.location.search)?.get('remoteUrl') || '')`,
externalType: 'promise',
},
},
shared: sharedList,
}),
/***
* Somehow reactBabel is not working in production mode
* and somehow reactSwc is not working in local mode
* So we need to use reactBabel in production and reactSwc in local
* (っ °Д °;)っ (っ °Д °;)っ (っ °Д °;)っ
*/
reactBabel({
jsxImportSource: '@emotion/react',
babel: {
plugins: ['@emotion/babel-plugin'],
},
}),
,
],
resolve: {
alias:
mode === 'production'
? [...alias]
: [
...Object.entries(mappingDevMonorepoLibs).map(([k, v]) => ({
find: k,
replacement: path.resolve(__dirname, '../../', v),
})),
...alias,
],
},
};
});