Closed Adioz01 closed 10 months ago
I'm trying a very similar setup. I am able to get some stuff working by using the useRecommendedBuildConfig: false
and adding the default config from this plugin into the build option for rollup. But I can't get the JS to inline. I'm not sure why
import { resolve } from 'path';
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteSingleFile } from "vite-plugin-singlefile"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
viteSingleFile({
useRecommendedBuildConfig: false,
inlinePattern: [],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
rollupOptions: {
input: {
sidebar: resolve(__dirname, "./index.html"),
dialog: resolve(__dirname, "./index_dialog.html"),
}
},
assetsInlineLimit: 100000000,
chunkSizeWarningLimit: 100000000,
cssCodeSplit: false,
}
})
I actually came here to ask this very question
After a lot of testing I have some progress but I'm getting to a point that I don't know enough about Vite to fix it.
I don't know why (but I'm sure it makes sense) when we use rollupOptions.input
the javascript is referenced as a <link>
in the bundled html instead of a <script>
so the regex in this plugin code can't find it
This small patch to plugin.ts
will do the trick and inline the js
export function replaceScript(html: string, scriptFilename: string, scriptCode: string, removeViteModuleLoader = false): string {
const reScript = new RegExp(`<script([^>]*?) src="[./]*${scriptFilename}"([^>]*)></script>`)
const reScript2 = new RegExp(`<link([^>]*?) href="[./]*${scriptFilename}"([^>]*)>`)
// 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")
// console.log(scriptFilename, reScript2,html.match(reScript2))
let inlined = html.replace(reScript, (_, beforeSrc, afterSrc) => `<script${beforeSrc}${afterSrc}>\n${newCode}\n</script>`)
inlined = inlined.replace(reScript2, (_, beforeSrc, afterSrc) => `<script${beforeSrc}${afterSrc}>\n${newCode}\n</script>`)
return removeViteModuleLoader ? _removeViteModuleLoader(inlined) : inlined
}
However this is not enough. Since the assets generated now look like modules they have exports, and they aren't instantiated. And that's where I'm stuck. I'm sure I'm just a couple tests away from getting this to work. But it feels like there should be a vite option for the scripts not to be bundled as modules so that the simple regex that this script is built around continues working without further modifications
On further inspection I'm pretty sure this is failing because it's trying to do dynamic imports and according to this rollup link inlining dynamic imports is not possible with multiple inputs. I'm trying to figure out if it's possible not use dynamic imports
https://rollupjs.org/configuration-options/#output-inlinedynamicimports
EDIT: and I think it's been brought up in rollupitself https://github.com/rollup/rollup/issues/2756#issue-421951224
With the patch that I shared yesterday and this configuration it sort of works. I'm seeing all of my console logs printing, but I'm not seeing my UI loading. It's confusing but I'm on the right path, I think.
Note that import { viteSingleFile } from "./plugin"
is my local patch for this plugin
import { resolve } from 'path';
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// import { viteSingleFile } from "vite-plugin-singlefile"
import { viteSingleFile } from "./plugin"
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
viteSingleFile({
useRecommendedBuildConfig: false,
inlinePattern: [],
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
rollupOptions: {
input: {
sidebar: resolve(__dirname, "./index.html"),
dialog: resolve(__dirname, "./index_dialog.html"),
},
output: {
manualChunks: () => '',
},
},
assetsInlineLimit: 100000000,
chunkSizeWarningLimit: 100000000,
cssCodeSplit: false,
}
})
My bundles are getting mixed, tho. eg, I have the content of index_dialog
inside of index
I'm figuring out why
EDIT: no. NVM I still have issues with exports and imports
For the time being I'm falling back into using multiple vite.config.ts
files 🤷🏽♀️
Wow thank you @Darkade for all your testing and support. I think you are on the right way, to solve this issue!
Are there any other solutions to this problem @richardtallent ?
Hi @Adioz01 . As I've mentioned many times before when this has come up, the purpose of this plugin is simply to bundle a web site into a single file. Not multiple files. Not multiple pages with their own connected dependencies. Just one file. I made it because I had a need to be able to ship demo mini-apps to clients via email and to launch mini cross-platform tools from the file system with no installation.
If someone can get it working with multiple entry pages, awesome! If they can send a PR to add tests so we don't accidentally break that in the future, great! But it's not a use case I have any time to invest in myself, so it would need to be community-driven.
Closing this, since this plugin is for single files, not multiple files.
@Darkade It's been a little while, but did you just end up figuring anything else out?
@Darkade @am-maneaters the following build.ts
script, executed with tsx
, will run vite multiple times and achieve the individually isolated output files. For example, I'm using this for external web component embeds.
build.ts
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { build } from 'vite'
import * as glob from 'glob'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const entries = glob.sync(path.resolve(__dirname, 'src', '*', '*.html'))
for (const entry of entries) {
const componentName = path.basename(path.dirname(entry))
console.log('entry', componentName)
await build({
root: path.resolve(__dirname, './src'),
build: {
outDir: '../dist', // build to dist directory at root (omitting the src dir)
assetsDir: componentName,
rollupOptions: {
input: path.resolve(__dirname, `./src/${componentName}/index.html`),
output: {
entryFileNames: `${componentName}/element.js`,
},
},
},
})
}
and sample execution: rm -rf dist; yarn tsx ./build.ts
This accomplishes:
entryFileNames
if this is not a requirement)
I am using vite + your plugin to create Google Apps Scripts (AddOns for Google Sheets).
All JS and CSS have to be inlined, so that works perfectly.
The issue that i have is, that i need multiple view alá index.html files.
How can i achieve this?
My current approach is this:
vite.config.js
but i get this error: Invalid value for option "output.inlineDynamicImports" - multiple inputs are not supported when "output.inlineDynamicImports" is true.
Thank you for your support!