Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline all assets into the index html page #621

Closed
mseele opened this issue Jul 24, 2020 · 12 comments
Closed

Inline all assets into the index html page #621

mseele opened this issue Jul 24, 2020 · 12 comments
Labels
enhancement New feature or request feat: html

Comments

@mseele
Copy link

mseele commented Jul 24, 2020

Is your feature request related to a problem? Please describe.
Long, short story: I need to embedd a vue app inside an Java SWT application via the SWT Browser Component. To make it work, the web app need to be one single index.html file embedded inside the Java application.

Describe the solution you'd like
With webpack it works with html-webpack-inline-source-plugin or facebook's InlineChunkHtmlPlugin.
I would love to see this feature in vite. To go away from webpack und use vite instead...

@mseele
Copy link
Author

mseele commented Jul 24, 2020

Just as an example how the vue app will be embedded into the Java/SWT app:

public static void main(String[] args) throws Exception {
	String html = Files.readString(new File("workflow-viewer/dist/index.html").toPath());

	Display display = new Display();
	Shell shell = new Shell(display);
	shell.setText("Snippet");
	shell.setLayout(new FillLayout());
	Browser browser = new Browser(shell, SWT.NONE);
	browser.setText(html);
	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch()) {
			display.sleep();
		}
	}
	display.dispose();
}

The browser class can not load dependend resources, so everything need to be inside index.html...

@yyx990803 yyx990803 added enhancement New feature or request feat: html labels Jul 29, 2020
@victornpb
Copy link
Contributor

victornpb commented Nov 7, 2020

I have the same requirement, I need the entire web to be a single index.html with all the assets (js,css,images) inlined, and gzipped.

The reason I need this is because the page is going to be embedded in a microcontroller which doesn't have a file system, it can only serve a blob it can't resolve files.

As a comparison this is what my vue.config.js (webpack) look like:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin");

// https://webpack.js.org/plugins/compression-webpack-plugin/#using-zopfli
const CompressionPlugin = require("compression-webpack-plugin");
const zopfli = require("@gfx/zopfli");

const webpack = require('webpack');

module.exports = {
  css: {
    extract: false,
  },
  configureWebpack: {
    
    optimization: {
      splitChunks: false, // makes there only be 1 js file - leftover from earlier attempts but doesn't hurt
    },
    plugins: [

      new HtmlWebpackPlugin({
        filename: "index.html", // the output file name that will be created
        template: "src/index.template.html", // this is important - a template file to use for insertion
        inlineSource: ".(js|css)$", // embed all javascript and css inline
      }),
      new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin),
      new CompressionPlugin({
        compressionOptions: {
          numiterations: 15,
        },
        algorithm(input, compressionOptions, callback) {
          return zopfli.gzip(input, compressionOptions, callback);
        },
      }),
    ],
  },
};

@richardtallent
Copy link

I have the same need. My vite.config.js does include the following, which at least should pump all CSS and other assets straight into the index.html, so now it's just down to the script:

module.exports = {
	assetsInlineLimit: 100000000,
	cssCodeSplit: false,
	outputOptions: {
		inlineDynamicImports: true,
	},
}

I tried playing with rollup-plugin-inline-js as a plugin under rollupInputOptions -- no effect. I understand from #793 that I should probably be using inputHtmlTransforms instead, but this just results in a Brotli error:

const inline = require("rollup-plugin-inline-js");
module.exports = {
	assetsInlineLimit: 100000000,
	cssCodeSplit: false,
	outputOptions: {
		inlineDynamicImports: true,
	},
	indexHtmlTransforms: [ inline ],
}

I also tried rollup-plugin-html-minifier, no error, but also no effect on the final dist\index.html.

I'm way out of my depth -- I've been using webpack and Vue for years, but this is literally my first time using vite or rollup. Very promising so far, if I can get past this issue! Worst case, I can hack something together in gulp, but I really wouldn't want to go that far.

@victornpb
Copy link
Contributor

I don’t know much about rollup, I only used a vary basic config for bundling a js library.
But I know roll up didn't support code splitting for a very long time, so it shouldn't be very hard to disable it, and embedding it into the html would be a simple matter of a simple post processing script.

@richardtallent
Copy link

richardtallent commented Nov 17, 2020

Yes, post-processing is an option, but feels suboptimal, and I'm not entirely certain it would work for a more complex application with lots of components, each of which might have their own asset imports.

I've been digging around for about an hour, but can't figure out if this is something that should be handled in buildPluginHtml, build\index, or elsewhere. I don't get the sense that this would fit the indexHtmlTransforms plugin model, since pre-processing I think happens before the assets are built, and post-processing occurs after they've been written to the file system. The CSS plugin has an option to either code-split or not, so it's able to handle both possibilities before any files get written.

I don't work in TypeScript, which makes this all much more difficult to reason about, unfortunately. So I may be missing an obvious solution for plugging in something to inject the assets into the index.html rather than writing them out to linked files.

(In case anyone thinks I'm crazy for wanting to do this -- it's because I'm building small HTML apps that are intended to be run offline, from the local file system, not from a server. The resulting HTML file can be large, but it's way easier to deploy than an index.html with a group of JS and CSS files. I've been doing it for years with webpack, but I'm really loving the DX of Vite so far, so I'm hoping to make the switch to it since I'm already planning to use Vue 3 for new projects like the one I started today. But I can imagine other use cases where someone might want to trade larger file sizes for fewer requests, even though that's likely almost never a performance-boosting option.)

@victornpb
Copy link
Contributor

Sorry if I wasn't clear, I didn't mean post processing as in something like what a gulp/grunt would do, I meant "post compilation" phase, but still in rollup.

I wrote something similar a while back for adding comment banners to a js file with some metadata.

@richardtallent
Copy link

I just noticed that when cssCodeSplit is set to false, npm run build generates a dist folder that includes no CSS -- not as a separate file, not as the original CSS files, and not (as I expected) embedded in the index.js.

I believe this is a bug (I'm going to file that separately), but it's related here because that means there are two files that need to be inlined during the build process -- one JS, one CSS.

I'm hoping there is a generalized solution...

I also haven't figured out an easy solution for inlining SVG files. There are a few plugins out there, but nothing that "just works" with vite for both dev and build and that support dynamic src. So for now I'm manually copying and pasting SVG nodes into my template.

@yyx990803
Copy link
Member

In 2.x, a plugin has access to the transformIndexHtml hook - which gets access to the entire bundle information during build. You can rewrite the HTML using that information.

@richardtallent
Copy link

Thanks @yyx990803 !

I hacked together a vite plugin for this -- vite-plugin-singlefile. It's rough, especially since it's my first vite (and rollup) plugin, but hopefully some other folks needing this functionality who have more experience with these plugins will be able to chip in and improve it!

Only supports JavaScript and CSS for now, and the CSS support is a bit weird since it's working around an bug in Vite 2.0 beta 15 with cssCodeSplit (#1141).

https://github.com/richardtallent/vite-plugin-singlefile

@victornpb and @mseele , would you have the ability to test to see how this works for you, and file any issues at the repo above?

@mseele
Copy link
Author

mseele commented Jan 9, 2021

@richardtallent Sounds great, i will try to evaluate it next week

@victornpb
Copy link
Contributor

@victornpb and @mseele , would you have the ability to test to see how this works for you, and file any issues at the repo above?

Thanks for putting something together, I'll check it out, i have a lot of things in progress atm but if I don’t get back to you until next weekend you can ping me

@mrienstra
Copy link

FYI, I'm using @richardtallent's https://github.com/richardtallent/vite-plugin-singlefile and it works great.

Wishing to also minify the resulting HTML, I tried this plugin: https://github.com/anncwb/vite-plugin-html (as per #1060), and so far so good, they seem to be playing well together.

import { defineConfig } from 'vite'
import { viteSingleFile } from 'vite-plugin-singlefile'
import { minifyHtml } from 'vite-plugin-html';

export default defineConfig({
  plugins: [
    viteSingleFile(),
    minifyHtml()
  ],
  build: {
    cssCodeSplit: false,
    assetsInlineLimit: 100000000,
    rollupOptions: {
      output: {
        manualChunks: () => "everything.js",
      },
    },
  }
})

@github-actions github-actions bot locked and limited conversation to collaborators Jul 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request feat: html
Projects
None yet
Development

No branches or pull requests

5 participants