package.json in sitepackage
{
"name": "site_package",
"private": true,
"type": "module",
"version": "0.0.0",
"scripts": {
"preinstall": "n auto",
"ce-linker": "spb-unlink && spb-link",
"dev": "vite --mode development",
"build": "vite build --mode production",
"build:watch": "vite build --watch --mode production",
"preview": "vite preview --port 4173 --mode production",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"postinstall": "vite build --mode production"
},
"devDependencies": {
"@analog-digitalagentur/content-element-linker": "1.0.0",
"@analog-digitalagentur/vite-shared-config": "^0.0.7"
},
"config": {
"content_element_path": "Modules/ContentElements",
"extension_name": "site_package"
},
"settings": {
"vite": {
"vendor": "analogde",
"extName": "site-package",
"assetsDir": "Assets",
"hashedAssetDir": true,
"port": 5111
}
}
}
vite.config.js in sitepackage
import fs from 'fs'
import path from 'path'
import {generateViteConfig} from '@analog-digitalagentur/vite-shared-config'
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Get the project root directory
const projectRoot = path.resolve(__dirname, './')
// Read the package.json
const packageJson = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf-8'))
// Extract the settings
const settings = packageJson.settings.vite
export default generateViteConfig(settings)
vite-shared-config/vite.config.js
// Import the required modules
import { defineConfig } from 'vite'
import path from 'path'
import { ViteFluid } from './vite.fluid.js'
import { ViteCleanUp } from './vite.cleanUp.js'
import copy from 'rollup-plugin-copy'
import { terser } from 'rollup-plugin-terser'
import fs from 'fs'
import crypto from 'crypto'
import autoprefixer from 'autoprefixer';
import { fileURLToPath } from 'url';
const __dirname = fileURLToPath(import.meta.url);
export function generateViteConfig(settings) {
const sourcePath = path.join(process.cwd(), './Modules')
const stylePath = path.join(process.cwd(), './Modules/ContentElements')
const stylePathSub = path.join(process.cwd(), './Modules/GlobalTemplates/SubParts')
let buildFiles = {}
const walkSync = (dir, filelist = []) => {
fs.readdirSync(dir).forEach((file) => {
const dirFile = path.join(dir, file)
try {
filelist = walkSync(dirFile, filelist)
} catch (err) {
if (err.code === 'ENOTDIR' || err.code === 'EBUSY') filelist = [...filelist, dirFile]
else throw err
}
})
return filelist
}
const scssFiles = walkSync(stylePath).filter((file) => file.match(/\\.scss$/))
const scssFilesSub = walkSync(stylePathSub).filter((file) => file.match(/\\.scss$/))
scssFiles.forEach((scssFile) => {
const fileName = path.basename(scssFile, '.scss')
buildFiles[fileName] = scssFile
})
scssFilesSub.forEach((scssFile) => {
const fileName = path.basename(scssFile, '.scss')
buildFiles[fileName] = scssFile
})
buildFiles.main = './Modules/GlobalTemplates/main.js'
console.log('buildFiles', buildFiles)
const mode = process.argv[process.argv.length - 1]
const extPath = `/vendor/${settings.vendor}/${settings.extName}/`
const hash = crypto.createHash('md5').update(extPath).digest('hex')
const hashedAssetDir = '/_assets/' + hash + '/' + settings.assetsDir + '/'
console.log('Vite is running in ' + mode + ' mode')
console.log('Vite is using the following settings:', settings)
let productionPath = `/typo3conf/ext/${settings.extName}/Resources/Public/${settings.assetsDir}/`
if (settings.hashedAssetDir) {
productionPath = hashedAssetDir
}
console.log('Vite is using the following public path:', productionPath)
console.log('')
return defineConfig({
base: mode === 'production' ? productionPath : './',
plugins: [
ViteFluid(),
ViteCleanUp(),
copy({
targets: [
{
src: path.resolve(sourcePath, 'GlobalTemplates/Assets/*'),
dest: path.resolve(process.cwd(), './Resources/Public/Modules/Assets'),
},
{
src: path.resolve(sourcePath, 'GlobalTemplates/Favicon/*'),
dest: path.resolve(process.cwd(), './Resources/Public/Modules/Assets/Favicon'),
},
]
}),
mode === 'production' && terser(),
],
server: {
port: settings.port,
origin: 'http://localhost:' + settings.port,
https: false,
hmr: {
host: 'localhost',
protocol: 'ws',
},
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
}
},
publicDir: false,
build: {
emptyOutDir: true,
manifest: true,
minify: true,
sourcemap: mode === 'development',
outDir: path.resolve(process.cwd(), `./Resources/Public/${settings.assetsDir}`),
rollupOptions: {
input: buildFiles
}
},
css: {
devSourcemap: true,
postcss: {
plugins: [
autoprefixer({
overrideBrowserslist: ['defaults'],
}),
],
}
},
esbuild: {
minify: mode === 'production',
target: 'es2015'
}
})
}
vite-shared-config/vite.cleanUp.js
export function ViteCleanUp() {
return {
name: 'remove-empty-chunks',
generateBundle(options, bundle) {
for (const name in bundle) {
const file = bundle[name];
if (file.type === 'chunk' && (!file.code || file.code.trim() === '')) {
delete bundle[name];
}
}
}
};
}
vite-shared-config/vite.fluid.js
export function ViteFluid() {
return {
name: "ViteFluid",
enforce: "post",
configureServer(server) {
const fullReload = () => {
server.ws.send({ type: "full-reload", path: "*" });
};
const hotReload = (file) => {
server.ws.send({ type: "update", updates: [{ type: "update", acceptedPath: file }] });
};
server.watcher.on("add", fullReload);
server.watcher.on("change", (file) => {
console.log(file);
if (
file.endsWith(".html") ||
file.endsWith(".typoscript") ||
file.endsWith(".yaml") ||
file.endsWith(".php")
) {
fullReload();
} else {
hotReload(file);
}
});
},
};
}