UNPKG

@allakando/allakando-web-ui

Version:

Allakando's web component library

148 lines (144 loc) 5.52 kB
import { createLogger, defineConfig } from "vite" import pkg from "./package.json" import fs from "fs" import sass from "sass" import tsconfigPaths from "vite-plugin-tsconfig-paths"; const DIST_FOLDER = "dist" const EXPORT_NAME = "AllakandoWebUI" const LIBRARY_NAME = pkg.name const VERSION = pkg.version const AUTHOR = pkg.author const DESCRIPTION = pkg.description const BANNER = `/** @preserve @license @cc_on * ---------------------------------------------------------- * ${LIBRARY_NAME} version ${VERSION} * ${DESCRIPTION} * Copyright (c) ${new Date().getFullYear()} ${AUTHOR} * All Rights Reserved. MIT License * https://mit-license.org/ * ---------------------------------------------------------- */ ` //This allows us to overwrite certain warnings and errors that are irrelevant and that will spam the console otherwise. const ignoredErrorPatterns = [ //Vite seems to do its code analysis before the resolveId hook is fired, causing incorrect logs "Default and named imports from CSS files are deprecated.", //Vite seems to do its code analysis before the resolveId hook is fired, causing incorrect logs "Do not know how to load path: html:" ] const logger = createLogger() const originalWarning = logger.warn const originalError = logger.error logger.warn = (message, options) => { if (!ignoredErrorPatterns.find(pattern => message.includes(pattern))) { originalWarning(message, options) } } logger.error = (message, options) => { if (!ignoredErrorPatterns.find(pattern => message.includes(pattern))) { originalError(message, options) } } export default defineConfig({ customLogger: logger, build: { target: "esnext", outDir: "./dist", emptyOutDir: false, minify: "terser", lib: { entry: "./src/index.js", formats: ["es", "umd"], name: EXPORT_NAME, fileName: format => { return format === "umd" ? "js/bundle.js" : "js/esm-bundle.js" } } }, plugins: [ tsconfigPaths(), { //We want html imports and scss imports to be loaded as strings //To accomplish this in vanilla Vite we would need to pollute the import statements with ?inline for .scss and ?raw for .html //Using a transform plugins works in Rollup but for some reason not in build mode in vite. The "code" argument is empty for some file extensions. //This plugin is a bit of a hack but solves it globally and isolates the logic for these imports within the vite config file name: "inline-html-and-scss-imports", enforce: "pre", async resolveId(id, importer, options) { const isHTML = id.match(/ako-.*\.html$/) const isSCSS = id.match(/ako-.*\.scss(\?used)?$/) || id.match(/Stylesheets[/\\]External.*\.scss(\?used)?$/) //Vite adds ?used to some scss resources before this hook runs if ((isHTML || isSCSS) && !options.isEntry) { const res = await this.resolve(id, importer, { skipSelf: true, ...options }) if (!res || res.external) return res return `${res.id}${isSCSS ? "?inline" : "?raw"}` } } }, { //After the JavaScript build has completed we build all the css assets manually name: "build-stylesheets", writeBundle() { fs.mkdirSync(`${DIST_FOLDER}/css`, { recursive: true }) fs.readdirSync("./src/Stylesheets/External/").map(fileName => { const css = sass.compile(`./src/Stylesheets/External/${fileName}`, { style: "compressed", sourceMap: false }) fs.writeFileSync(`${DIST_FOLDER}/css/${fileName.replace(/.scss$/, "")}.css`, `${BANNER}${css.css}`, "utf-8") }) //This file is created due to some standard behaviour in Vite that cannot be turned off. We can safely remove it. fs.existsSync(`${DIST_FOLDER}/style.css`) && fs.rmSync(`${DIST_FOLDER}/style.css`) return null } }, { //Vite does not put the banner specified in rollupConfig at the very top of the file, but instead inside the UMD module. //This plugin adds the banner at the very top when writing the bundle to disk so as to guarantee its always in the right place. name: "add-banner", apply: "build", async writeBundle(_, bundle) { for (const fileName of Object.entries(bundle)) { const file = fileName[0] if (_.dir.endsWith("dist") && file.match(/(css|js)(\\|\/).*\.(css|js)$/i)) { const fileURL = `${DIST_FOLDER}/${file}` let data = fs.readFileSync(fileURL, { encoding: "utf8" }) data = `${BANNER} ${data}` fs.writeFileSync(fileURL, data) } } } }, { //The SCSS files are built outside of the scope of the input entrypoint file, so we need to manually tell the watcher to include them. name: "rebuild-on-css-changes", buildStart() { fs.readdirSync("./src/Stylesheets/External/").forEach(fileName => { this.addWatchFile(`./src/Stylesheets/External/${fileName}`) }) fs.readdirSync("./src/Stylesheets/Internal/").forEach(fileName => { this.addWatchFile(`./src/Stylesheets/Internal/${fileName}`) }) this.addWatchFile("./src/index.html") return null } }, { //This allows us to serve index.html from the root URL in the vanilla server even though it is located in src. //One can also manually go to /src/index.html in the browser name: "redirect-to-index-html", configureServer(server) { server.middlewares.use((req, res, next) => { if (req.url === "/") { req.url = "/src/index.html" } else if (req.url.startsWith("/Stylesheets") || req.url.startsWith("/Assets")) { req.url = `/src${req.url}` } next() }) } } ] })