mirror of
https://github.com/MercuryWorkshop/adrift.git
synced 2025-05-12 13:50:01 -04:00
internalize vite-plugin-singlefile, fixing compilation on windows
This commit is contained in:
parent
9b03d3e086
commit
fa1d6bb260
4 changed files with 160 additions and 8 deletions
|
@ -38,7 +38,6 @@
|
||||||
"typescript": "^5.1.6",
|
"typescript": "^5.1.6",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.9",
|
||||||
"vite-plugin-singlefile": "git://github.com/CoolElectronics/vite-plugin-singlefile.git",
|
|
||||||
"vite-plugin-svelte": "^3.0.1"
|
"vite-plugin-svelte": "^3.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -238,12 +238,14 @@
|
||||||
<Button type="filled" on:click={() => (showTrackerList = true)}
|
<Button type="filled" on:click={() => (showTrackerList = true)}
|
||||||
>Start Browsing</Button
|
>Start Browsing</Button
|
||||||
>
|
>
|
||||||
<Button
|
{#if !import.meta.env.VITE_ADRIFT_SINGLEFILE}
|
||||||
type="text"
|
<Button
|
||||||
on:click={() => {
|
type="text"
|
||||||
downloadShortcut("adrift.html", "Homework");
|
on:click={() => {
|
||||||
}}>Get Shortcut</Button
|
downloadShortcut("adrift.html", "Homework");
|
||||||
>
|
}}>Get Shortcut</Button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
151
frontend/vite-singlefile.js
Normal file
151
frontend/vite-singlefile.js
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import micromatch from "micromatch"
|
||||||
|
|
||||||
|
const defaultConfig = {
|
||||||
|
useRecommendedBuildConfig: true,
|
||||||
|
removeViteModuleLoader: false,
|
||||||
|
deleteInlinedFiles: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceScript(
|
||||||
|
html,
|
||||||
|
scriptFilename,
|
||||||
|
scriptCode,
|
||||||
|
removeViteModuleLoader = false
|
||||||
|
) {
|
||||||
|
const reScript = new RegExp(
|
||||||
|
`<script([^>]*?) src="[./]*${scriptFilename}"([^>]*)></script>`
|
||||||
|
)
|
||||||
|
// we can't use String.prototype.replaceAll since it isn't supported in Node.JS 14
|
||||||
|
const preloadMarker = /"__VITE_PRELOAD__"/g
|
||||||
|
const newCode = scriptCode.replace(preloadMarker, "void 0")
|
||||||
|
const inlined = html.replace(
|
||||||
|
reScript,
|
||||||
|
(_, beforeSrc, afterSrc) =>
|
||||||
|
`<script${beforeSrc}${afterSrc}>\nimport "data:application/javascript;base64,${Buffer.from(
|
||||||
|
newCode
|
||||||
|
).toString("base64")}";\n</script>`
|
||||||
|
)
|
||||||
|
return removeViteModuleLoader ? _removeViteModuleLoader(inlined) : inlined
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceCss(html, scriptFilename, scriptCode) {
|
||||||
|
const reCss = new RegExp(`<link[^>]*? href="[./]*${scriptFilename}"[^>]*?>`)
|
||||||
|
const inlined = html.replace(reCss, `<style>\n${scriptCode}\n</style>`)
|
||||||
|
return inlined
|
||||||
|
}
|
||||||
|
|
||||||
|
const warnNotInlined = filename =>
|
||||||
|
console.warn(`WARNING: asset not inlined: ${filename}`)
|
||||||
|
|
||||||
|
export function viteSingleFile({
|
||||||
|
useRecommendedBuildConfig = true,
|
||||||
|
removeViteModuleLoader = false,
|
||||||
|
inlinePattern = [],
|
||||||
|
deleteInlinedFiles = true
|
||||||
|
} = defaultConfig) {
|
||||||
|
return {
|
||||||
|
name: "vite:singlefile",
|
||||||
|
config: useRecommendedBuildConfig ? _useRecommendedBuildConfig : undefined,
|
||||||
|
enforce: "post",
|
||||||
|
generateBundle: (_, bundle) => {
|
||||||
|
const jsExtensionTest = /\.[mc]?js$/
|
||||||
|
const htmlFiles = Object.keys(bundle).filter(i => i.endsWith(".html"))
|
||||||
|
const cssAssets = Object.keys(bundle).filter(i => i.endsWith(".css"))
|
||||||
|
const jsAssets = Object.keys(bundle).filter(i => jsExtensionTest.test(i))
|
||||||
|
const bundlesToDelete = []
|
||||||
|
for (const name of htmlFiles) {
|
||||||
|
const htmlChunk = bundle[name]
|
||||||
|
let replacedHtml = htmlChunk.source
|
||||||
|
for (const jsName of jsAssets) {
|
||||||
|
if (
|
||||||
|
!inlinePattern.length ||
|
||||||
|
micromatch.isMatch(jsName, inlinePattern)
|
||||||
|
) {
|
||||||
|
const jsChunk = bundle[jsName]
|
||||||
|
if (jsChunk.code != null) {
|
||||||
|
bundlesToDelete.push(jsName)
|
||||||
|
replacedHtml = replaceScript(
|
||||||
|
replacedHtml,
|
||||||
|
jsChunk.fileName,
|
||||||
|
jsChunk.code,
|
||||||
|
removeViteModuleLoader
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warnNotInlined(jsName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const cssName of cssAssets) {
|
||||||
|
if (
|
||||||
|
!inlinePattern.length ||
|
||||||
|
micromatch.isMatch(cssName, inlinePattern)
|
||||||
|
) {
|
||||||
|
const cssChunk = bundle[cssName]
|
||||||
|
bundlesToDelete.push(cssName)
|
||||||
|
replacedHtml = replaceCss(
|
||||||
|
replacedHtml,
|
||||||
|
cssChunk.fileName,
|
||||||
|
cssChunk.source
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
warnNotInlined(cssName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
htmlChunk.source = replacedHtml
|
||||||
|
}
|
||||||
|
if (deleteInlinedFiles) {
|
||||||
|
for (const name of bundlesToDelete) {
|
||||||
|
delete bundle[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const name of Object.keys(bundle).filter(
|
||||||
|
i =>
|
||||||
|
!jsExtensionTest.test(i) &&
|
||||||
|
!i.endsWith(".css") &&
|
||||||
|
!i.endsWith(".html")
|
||||||
|
)) {
|
||||||
|
warnNotInlined(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally remove the Vite module loader since it's no longer needed because this plugin has inlined all code.
|
||||||
|
// This assumes that the Module Loader is (1) the FIRST function declared in the module, (2) an IIFE, (4) is within
|
||||||
|
// a script with no unexpected attribute values, and (5) that the containing script is the first script tag that
|
||||||
|
// matches the above criteria. Changes to the SCRIPT tag especially could break this again in the future. It should
|
||||||
|
// work whether `minify` is enabled or not.
|
||||||
|
// Update example:
|
||||||
|
// https://github.com/richardtallent/vite-plugin-singlefile/issues/57#issuecomment-1263950209
|
||||||
|
const _removeViteModuleLoader = html =>
|
||||||
|
html.replace(
|
||||||
|
/(<script type="module" crossorigin>\s*)\(function(?: polyfill)?\(\)\s*\{[\s\S]*?\}\)\(\);/,
|
||||||
|
'<script type="module">\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
// Modifies the Vite build config to make this plugin work well.
|
||||||
|
const _useRecommendedBuildConfig = config => {
|
||||||
|
if (!config.build) config.build = {}
|
||||||
|
// Ensures that even very large assets are inlined in your JavaScript.
|
||||||
|
config.build.assetsInlineLimit = 100000000
|
||||||
|
// Avoid warnings about large chunks.
|
||||||
|
config.build.chunkSizeWarningLimit = 100000000
|
||||||
|
// Emit all CSS as a single file, which `vite-plugin-singlefile` can then inline.
|
||||||
|
config.build.cssCodeSplit = false
|
||||||
|
// Subfolder bases are not supported, and shouldn't be needed because we're embedding everything.
|
||||||
|
config.base = undefined
|
||||||
|
|
||||||
|
if (!config.build.rollupOptions) config.build.rollupOptions = {}
|
||||||
|
if (!config.build.rollupOptions.output) config.build.rollupOptions.output = {}
|
||||||
|
|
||||||
|
const updateOutputOptions = out => {
|
||||||
|
// Ensure that as many resources as possible are inlined.
|
||||||
|
out.inlineDynamicImports = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(config.build.rollupOptions.output)) {
|
||||||
|
for (const o in config.build.rollupOptions.output) updateOutputOptions(o)
|
||||||
|
} else {
|
||||||
|
updateOutputOptions(config.build.rollupOptions.output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
import { svelte } from "@sveltejs/vite-plugin-svelte"
|
import { svelte } from "@sveltejs/vite-plugin-svelte"
|
||||||
import { viteSingleFile } from "vite-plugin-singlefile"
|
import { viteSingleFile } from "./vite-singlefile"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue