20

I have a vue project created with vue-cli. The normal output when running yarn build is a dist folder with an index.html and a js and css sub-directory with the corresponding .js and .css files.

I want the build output to be a single html file that contains the js and css.

I added a vue.config.js file in the root of my project and set it to output a single js file and that is working ok. But I want to only have a single html file with the js and any css already on the html file.

module.exports = {
    css: {
        extract: false,
    },
    configureWebpack: {
      optimization: {
        splitChunks: false
      }
    }
  }

Basically I want my html file to be something like this:

<html lang=en>
    <head>
        ... meta tags
        <title>my title</title>
    </head>
    <body>
        <div id=app></div>
        <script>
           // contents of the output js file here
        </script>
    </body>
</html>

Is this possible?

Using Vue 3.9.3

2
  • Could you describe your use case/scenario? I'm just curious, why you would do that Commented Oct 7, 2019 at 20:00
  • 6
    long story short, the document needs to be 100% standalone and offline ready to be downloaded and stored as a web view in an old (v1) cordova application Commented Oct 9, 2019 at 15:21

1 Answer 1

25

Someone answered with a suggestion to look into html-webpack-inline-source-plugin but removed their answer. But that was exactly what I needed to get this done.

The plugin is not Vue or Vue-CLI specific but it works if you do the following:

1) Add a vue.config.js file in the root of the app.

2) The linked plugin above is actually an extension of another package. You need both.

npm install --save-dev html-webpack-plugin 
npm install --save-dev html-webpack-inline-source-plugin 

3)

// vue.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
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: 'output.html', // the output file name that will be created
          template: 'src/output-template.html', // this is important - a template file to use for insertion
          inlineSource: '.(js|css)$' // embed all javascript and css inline
        }),
        new HtmlWebpackInlineSourcePlugin()
      ]
    }
  }

4) Add a template. This is necessary for working in the Vue context because without this the output html file by default won't have the necessary <div id="app"></div> and Vue won't mount to anything. I basically took the normal output html file and modified it a little.

<!-- output-template.html -->
<!DOCTYPE html>
<html lang=en>
    <head>
        <meta charset=utf-8>
        <meta http-equiv=X-UA-Compatible content="IE=edge">
        <meta name=viewport content="width=device-width,initial-scale=1">        
        <title>example title</title>
    </head>
    <body><noscript><strong>We're sorry but my example doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>
        <div id=app>

        </div>
        <!-- plugin will insert js here by default -->
    </body>
</html>

Then build like normal and the output.html file will be in the /dist folder

Sign up to request clarification or add additional context in comments.

7 Comments

For this to work today I had to instead npm install --save-dev html-webpack-inline-source-plugin@beta and initialize the inline source plugin as new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin)
How did you install html-webpack-plugin 4.5.1 via vue-cli UI? I can only select the latest and with that the build breaks with Cannot read property 'tap' of undefined
And with installing 4.5.1 via npm i I get Cannot read property 'getHooks' of undefined failing from html-webpack-inline-source-plugin.
Maybe it's a bit late, but i'm still documenting this for others: if u get the Cannot read property 'getHooks' of undefined message, you forgot to initialize the plugin as new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin) in the vue.config.js plugins array. Adding that solved the problem.
When you get 'tap' of undefined, you are probably using Webpack 4 with HtmlWebpackPlugin 5. Downgrade the latter to 4 and it works.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.